Card Gateway API
Accept Visa, Mastercard, JCB, and Amex payments with 2D and 3D Secure support. Process card payments through a single API, with automatic fraud screening, velocity controls, and real-time settlement.
Overview
The Dapit Card Gateway provides a server-to-server API for processing credit and debit card payments. Send card details directly from your backend and receive real-time authorization results.
Authentication
All requests require your API key sent as a header:
X-Gateway-Key: your_api_key_here
You can also pass it as a query parameter api_key, but the header method is preferred. Your API key is available in the MaxaFi dashboard under the merchant's Instant Payments → Settings tab.
Base URL
# Production
https://www.maxafi.com/api/gateway/card_gateway.php
# All endpoints use the ?action= parameter
https://www.maxafi.com/api/gateway/card_gateway.php?action=create_charge
Create Charge
Process a card payment. The gateway automatically determines whether 3D Secure is required based on the card issuer and risk assessment.
Request Body (JSON)
| Parameter | Type | Required | Description |
|---|---|---|---|
| amount | number | Required | Charge amount (e.g. 49.99). Max 2 decimal places. |
| currency | string | Required | ISO 4217 code: USD, EUR, GBP, etc. |
| card_number | string | Required | Full card number (no spaces or dashes) |
| card_expiry | string | Required | Expiration date: MM/YYYY or MM/YY |
| card_cvv | string | Required | 3 or 4 digit security code |
| cardholder_name | string | Required | Full name as on card |
| string | Required | Cardholder email address | |
| phone | string | Required | Cardholder phone number |
| billing_address | string | Required | Billing street address |
| billing_city | string | Required | Billing city |
| billing_state | string | Required | Billing state/province |
| billing_zip | string | Required | Billing postal/zip code |
| billing_country | string | Required | ISO 3166-1 alpha-2 code: US, GB, etc. |
| order_id | string | Optional | Your internal order/reference ID |
| description | string | Optional | Description shown in reports |
| customer_id | string | Optional | Your internal customer identifier |
| return_url | string | Optional | URL to redirect after 3DS verification |
Example Request
// cURL
curl -X POST "https://www.maxafi.com/api/gateway/card_gateway.php?action=create_charge" \
-H "Content-Type: application/json" \
-H "X-Gateway-Key: your_api_key" \
-d '{
"amount": 49.99,
"currency": "USD",
"card_number": "4111111111111111",
"card_expiry": "12/2027",
"card_cvv": "123",
"cardholder_name": "John Doe",
"email": "john@example.com",
"phone": "12125551234",
"billing_address": "123 Main St",
"billing_city": "New York",
"billing_state": "NY",
"billing_zip": "10001",
"billing_country": "US",
"order_id": "ORD-20260402-001",
"description": "Widget purchase"
}'
Success Response (2D — No 3DS)
{
"success": true,
"charge_id": "ch_a1b2c3d4e5f6a7b8c9d0e1f2",
"status": "succeeded",
"amount": 49.99,
"currency": "USD",
"fees": {
"mdr": 1.45,
"transaction": 0.30,
"total": 1.75
},
"net_amount": 48.24,
"card_brand": "Visa",
"card_last4": "1111",
"merchant_order_id": "ORD-20260402-001"
}
3DS Required Response
{
"success": true,
"charge_id": "ch_a1b2c3d4e5f6a7b8c9d0e1f2",
"status": "pending_3ds",
"requires_action": true,
"action_type": "3ds_redirect",
"redirect_url": "https://3ds.provider.com/verify?token=abc123",
"message": "Redirect the cardholder to redirect_url for 3D Secure verification.",
"amount": 49.99,
"currency": "USD"
}
Declined Response
{
"success": true,
"charge_id": "ch_a1b2c3d4e5f6a7b8c9d0e1f2",
"status": "failed",
"error_message": "Insufficient funds",
"amount": 49.99,
"currency": "USD"
}
3D Secure Flow
When the issuing bank requires 3D Secure verification, the create_charge response will include requires_action: true and a redirect_url.
Handling 3DS in Your Code
// After calling create_charge
if (response.requires_action && response.redirect_url) {
// Store charge_id in your session/database
saveChargeId(response.charge_id);
// Redirect the cardholder to 3DS verification
window.location.href = response.redirect_url;
}
// Your webhook endpoint receives the result:
{
"event": "charge.succeeded",
"charge_id": "ch_a1b2c3d4e5f6a7b8c9d0e1f2",
"status": "succeeded",
"amount": 49.99,
"confirmed_at": "2026-04-02T14:30:00Z"
}
get_charge with the charge_id.
Get Charge
Retrieve the current status and details of a charge.
| Parameter | Type | Required | Description |
|---|---|---|---|
| charge_id | string | Required* | The charge ID returned from create_charge |
| order_id | string | Required* | Your merchant order ID (alternative to charge_id) |
* Provide either charge_id or order_id.
Response
{
"success": true,
"charge_id": "ch_a1b2c3d4e5f6a7b8c9d0e1f2",
"status": "succeeded",
"amount": 49.99,
"currency": "USD",
"fees": { "mdr": 1.45, "transaction": 0.30, "total": 1.75 },
"net_amount": 48.24,
"card_brand": "Visa",
"card_last4": "1111",
"merchant_order_id": "ORD-20260402-001",
"description": "Widget purchase",
"created_at": "2026-04-02 14:25:00",
"confirmed_at": "2026-04-02 14:25:02",
"refunded_amount": 0
}
Create Refund
Refund a succeeded charge. Supports full and partial refunds.
| Parameter | Type | Required | Description |
|---|---|---|---|
| charge_id | string | Required | The charge to refund |
| amount | number | Optional | Partial refund amount. Omit for full refund. |
| reason | string | Optional | Reason for refund |
Response
{
"success": true,
"refund_id": "rf_x1y2z3a4b5c6d7e8f9g0h1i2",
"charge_id": "ch_a1b2c3d4e5f6a7b8c9d0e1f2",
"status": "succeeded",
"amount": 49.99,
"refund_fee": 0.00,
"net_refund": 49.99
}
List Charges
Retrieve a paginated list of your charges with optional filters.
| Parameter | Type | Required | Description |
|---|---|---|---|
| status | string | Optional | Filter: succeeded, failed, pending_3ds, refunded |
| from | string | Optional | Start date: YYYY-MM-DD |
| to | string | Optional | End date: YYYY-MM-DD |
| limit | integer | Optional | Results per page (default 50, max 200) |
| offset | integer | Optional | Pagination offset |
Charge Statuses
| Status | Description | Is Final? |
|---|---|---|
succeeded | Payment authorized and captured successfully | Yes |
failed | Payment declined by issuer or gateway | Yes |
pending_3ds | Awaiting 3D Secure cardholder verification | No — will become succeeded or failed |
processing | Payment submitted, awaiting confirmation | No — will become succeeded or failed |
refunded | Fully refunded | Yes |
partially_refunded | Partially refunded (check refunded_amount) | Yes |
disputed | Cardholder filed a chargeback | No — pending resolution |
Webhooks
Set your callback_url in the MaxaFi dashboard (Instant Payments → Settings). We POST JSON to this URL when:
- A 3DS charge completes (succeeded or failed)
- A processing charge reaches final status
- A refund is processed
Webhook Payload
{
"event": "charge.succeeded",
"charge_id": "ch_a1b2c3d4e5f6a7b8c9d0e1f2",
"merchant_order_id": "ORD-20260402-001",
"amount": 49.99,
"currency": "USD",
"status": "succeeded",
"card_brand": "Visa",
"card_last4": "1111",
"confirmed_at": "2026-04-02T14:30:00Z",
"timestamp": "2026-04-02T14:30:01+00:00"
}
Webhook Events
| Event | Description |
|---|---|
charge.succeeded | Payment was authorized and captured |
charge.failed | Payment was declined after 3DS or async processing |
refund.succeeded | Refund processed successfully |
refund.failed | Refund attempt failed |
Error Codes
When a request fails, the response includes success: false and an error field:
{
"success": false,
"error": "Amount exceeds single transaction limit of USD 5,000.00"
}
| Error | Cause |
|---|---|
Missing API key | No X-Gateway-Key header or api_key parameter |
Invalid or inactive API key | Key doesn't match or merchant is disabled |
Amount must be positive | Amount is zero or negative |
Amount below minimum | Below the merchant's configured min_txn_amount |
Amount exceeds maximum | Above the merchant's configured max_txn_amount |
Daily volume limit exceeded | Merchant's daily processing cap reached |
Monthly volume limit exceeded | Merchant's monthly processing cap reached |
Velocity limit: card per day | Same card used too many times today |
Velocity limit: card per hour | Same card used too many times this hour |
Velocity limit: card amount per day | Same card exceeded daily $ limit |
Velocity limit: IP per day | Too many transactions from same IP |
Velocity limit: email per day | Too many transactions from same email |
Transaction declined | Card issuer declined the transaction |
Insufficient funds | Card has insufficient balance |
Invalid card number | Card number failed validation |
Expired card | Card expiration date has passed |
Test Cards
Use these card numbers in test mode. The first card below is the gateway provider's official test card with specific CVV and expiry.
| Card Number | Brand | CVV | Expiry | Result |
|---|---|---|---|---|
4444 3333 2222 1111 | Visa | 666 | 06/2026 | Approved (2D) — Primary Test Card |
4111 1111 1111 1111 | Visa | Any 3 digits | Any future date | Approved (2D) |
5500 0000 0000 0004 | Mastercard | Any 3 digits | Any future date | Approved (2D) |
4000 0000 0000 0002 | Visa | Any 3 digits | Any future date | Declined |
4000 0000 0000 3220 | Visa | Any 3 digits | Any future date | 3DS Required |
3530 1113 3330 0000 | JCB | Any 3 digits | Any future date | Approved |
3782 822463 10005 | Amex | Any 4 digits | Any future date | Approved |
Code Examples
PHP
// PHP — Create a charge
$ch = curl_init('https://www.maxafi.com/api/gateway/card_gateway.php?action=create_charge');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-Gateway-Key: your_api_key'
],
CURLOPT_POSTFIELDS => json_encode([
'amount' => 49.99,
'currency' => 'USD',
'card_number' => '4111111111111111',
'card_expiry' => '12/2027',
'card_cvv' => '123',
'cardholder_name' => 'John Doe',
'email' => 'john@example.com',
'phone' => '12125551234',
'billing_address' => '123 Main St',
'billing_city' => 'New York',
'billing_state' => 'NY',
'billing_zip' => '10001',
'billing_country' => 'US',
'order_id' => 'ORD-001',
]),
CURLOPT_RETURNTRANSFER => true,
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
if ($result['success'] && $result['status'] === 'succeeded') {
// Payment approved!
echo "Charge " . $result['charge_id'] . " approved.";
} elseif ($result['requires_action']) {
// Redirect for 3DS
header('Location: ' . $result['redirect_url']);
} else {
// Declined
echo "Error: " . $result['error_message'];
}
Node.js
// Node.js — Create a charge
const response = await fetch(
'https://www.maxafi.com/api/gateway/card_gateway.php?action=create_charge',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Gateway-Key': 'your_api_key',
},
body: JSON.stringify({
amount: 49.99,
currency: 'USD',
card_number: '4111111111111111',
card_expiry: '12/2027',
card_cvv: '123',
cardholder_name: 'John Doe',
email: 'john@example.com',
phone: '12125551234',
billing_address: '123 Main St',
billing_city: 'New York',
billing_state: 'NY',
billing_zip: '10001',
billing_country: 'US',
order_id: 'ORD-001',
}),
}
);
const data = await response.json();
if (data.status === 'succeeded') {
console.log('Approved:', data.charge_id);
} else if (data.requires_action) {
console.log('Redirect to:', data.redirect_url);
} else {
console.log('Declined:', data.error_message);
}
Python
# Python — Create a charge
import requests
result = requests.post(
'https://www.maxafi.com/api/gateway/card_gateway.php?action=create_charge',
headers={
'Content-Type': 'application/json',
'X-Gateway-Key': 'your_api_key',
},
json={
'amount': 49.99,
'currency': 'USD',
'card_number': '4111111111111111',
'card_expiry': '12/2027',
'card_cvv': '123',
'cardholder_name': 'John Doe',
'email': 'john@example.com',
'phone': '12125551234',
'billing_address': '123 Main St',
'billing_city': 'New York',
'billing_state': 'NY',
'billing_zip': '10001',
'billing_country': 'US',
}
).json()
if result['status'] == 'succeeded':
print(f"Approved: {result['charge_id']}")
elif result.get('requires_action'):
print(f"3DS redirect: {result['redirect_url']}")
else:
print(f"Declined: {result.get('error_message')}")