CartDna Api Documentation

Supported Payment Methods

CartDna supports a variety of payment methods to accommodate customers worldwide. Each payment method has a unique code that you'll use when initiating payment requests.

Available Payment Methods

Payment MethodMethod CodeSupported CurrenciesRegion
iDEALcartdna_pixBRLBrazil
Boletocartdna_boletoBRLBrazil
Bancontactcartdna_bancontactEURBelgium
Klarnacartdna_klarnaEUR, USD, GBP, SEK, NOK, DKKEurope, US
Credit/Debit Cardcartdna_cardUSD, EUR, GBP, LKR, AUD, CAD, JPYGlobal
BLIKcartdna_blikPLNGermany, Austria
Przelewy24cartdna_p24PLNPoland

Currency Codes

CartDna supports the following currency codes in accordance with ISO 4217 standards:

CurrencyCode
US DollarUSD
EuroEUR
British PoundGBP
Sri Lankan RupeeLKR
Brazilian RealBRL
Australian DollarAUD
Canadian DollarCAD
Japanese YenJPY
Swedish KronaSEK
Norwegian KroneNOK
Danish KroneDKK
Polish ZłotyPLN

Specifying Payment Method

To use a specific payment method, include the payment_method parameter in your payment request with the corresponding method code:

{
  "merchant_id": "MERCHANT_12345",
  "order_id": "ORDER_67890",
  "amount": "250.00",
  "currency": "BRL",
  "payment_method": "cartdna_pix",
  "signature": "A1B2C3D4E5F6...",
  "webhook_url": "https://yourdomain.com/webhook",
  "response_url": "https://yourdomain.com/payment-success",
  "cancel_url": "https://yourdomain.com/payment-cancel"
}

STEP 01 : Authentication

All API endpoints require authentication using a Bearer token. Before accessing any other API endpoints, you must first obtain an access token through the authentication process.

Getting Your Credentials

To authenticate, you'll need your API credentials from CartDna:

  • Public_key(Client ID) - Your unique client identifier
  • private_key (Client Secret) - Your secret key (keep this secure and never share publicly)
  • Merchant ID - Merchant identifier
  • Signature Key - generate and verify signature using this key

You can obtain these credentials from your CartDna (Contact us - info@cartdna.com).

Authentication Request

Use HTTP Basic Authentication to obtain an access token. Encode your client_id and client_secret in the format client_id:client_secret and base64 encode the string.

curl -X POST https://api.fiatdna.com/v1/auth/token \
  -H "Authorization: Basic BASE64_ENCODED_CREDENTIALS" \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "client_credentials"
  }'

Example in PHP

<?php

$client_id = 'YOUR_CLIENT_ID';
$client_secret = 'YOUR_CLIENT_SECRET';

// Create base64 encoded credentials
$credentials = base64_encode("$client_id:$client_secret");

$url = "https://api.fiatdna.com/v1/auth/token";

$data = json_encode([
    "grant_type" => "client_credentials"
]);

$ch = curl_init($url);

curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "Authorization: Basic $credentials",
        "Content-Type: application/json"
    ],
    CURLOPT_POSTFIELDS => $data
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

if (curl_errno($ch)) {
    echo "cURL Error: " . curl_error($ch);
    curl_close($ch);
    exit;
}

curl_close($ch);

if ($httpCode === 200) {
    $result = json_decode($response, true);
    echo "Access Token: " . $result['access_token'];
} else {
    echo "Authentication failed. HTTP Code: $httpCode\n";
    echo "Response: $response";
}

Authentication Response

A successful authentication returns an access token:

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "payment"
}

Using the Access Token

Include the access token as a Bearer token in the Authorization header for all subsequent API requests:

curl -X GET https://api.fiatdna.com/v1/some-endpoint \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json"

Important: Access tokens expire after the time specified in expires_in (in seconds). You'll need to request a new token when the current one expires.

Token Expiration

When your token expires, you'll receive a 401 Unauthorized response. Simply request a new token using the same authentication process.

STEP 02 : Create Payment Request

The Payment Request API allows you to initiate payment transactions. All payment requests require a secure signature generated using SHA256 hashing algorithm.

🔐 Required Security Headers

Every payment request must include these headers:

HeaderRequiredDescriptionExample
AuthorizationYesOAuth Bearer tokenBearer YOUR_TOKEN
Content-TypeYesJSON formatapplication/json
X-TimestampYesUTC Unix timestamp (seconds)1707300000
X-Idempotency-KeyYesUnique key per request (UUID recommended)550e8400-e29b-41d4-a716-446655440000
X-SignatureYesSHA-256 signatureB7C8D9E0F1A2…

Timestamp rules

  • Must be UTC Unix timestamp (seconds)
  • Must be integer
  • Must be within ± 5 minutes of CartDNA server time

Payment Request Parameters

Include the following parameters in your payment request:

Primary Details

ParameterTypeRequiredDescriptionExample
order_idStringYesUnique order reference from merchant systemORD-100234
amountDecimalYesTotal payment amount2500.00
currencyStringYesISO currency codeEUR
transaction_typeStringYesSupport types - Payment / preauth
payment_methodStringYesPayment method codecartdna_boleto
customer.nameStringYesCustomer full nameJohn Micheal
customer.emailStringYesCustomer email addressinfo@example.com
customer.phoneStringNoCustomer mobile number1234567890
return_urlURLYesRedirect after successful paymenthttps://clientsite.com/success
cancel_urlURLYesRedirect if user cancelshttps://clientsite.com/cancel
callback_urlURLYesWebhook URL for notificationshttps://clientsite.com/webhook
metadataObjectNoAdditional merchant data{ "cart_id":"CART-5566" }
SignatureStringYesGenerated SignatureB7C8D9E0F1A2….

Billing Address Details

ParameterTypeRequiredDescriptionExample
billing_address.address_lineStringYes (if provided)Billing street line 1123 Main Street
billing_address.cityStringYes (if provided)Billing cityLondon
billing_address.stateStringNoBilling state/provinceWestern
billing_address.postal_codeStringNoBilling postal code00500
billing_address.countryStringYes (if provided)ISO country codeGB

Shipping Address Details

ParameterTypeRequiredDescriptionExample
shipping_address.address_lineStringYes (if provided)Delivery street line 1123 Main Street
shipping_address.cityStringYes (if provided)Delivery cityLondon
shipping_address.stateStringNoDelivery state/provinceWestern
shipping_address.postal_codeStringNoDelivery postal code00500
shipping_address.countryStringYes (if provided)ISO country codeGB

Example Payment Request

curl -X POST https://api.fiatdna.com/v1/payments \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Timestamp: 1707300000" \
  -H "X-Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -H "X-Signature: B7C8D9E0F1A2...." \
  -d '{
    "order_id": "ORD-100234",
    "amount": 2500.00,
    "currency": "LKR",
    "payment_method": "cartdna_boleto",
    "transaction_type": "payment",

    "customer": {
      "name": "John Robert",
      "email": "info@example.com",
      "phone": "1234567890"
    },

    "return_url": "https://yourdomain.com/payment-success",
    "cancel_url": "https://yourdomain.com/payment-cancel",
    "callback_url": "https://yourdomain.com/webhook",

    "metadata": {
      "cart_id": "CART-5566"
    },

    "billing_address": {
      "address_line": "123 Main Street",
      "city": "London",
      "state": "Western",
      "postal_code": "00500",
      "country": "GB"
    },

    "shipping_address": {
      "address_line": "123 Main Street",
      "city": "London",
      "state": "Western",
      "postal_code": "00500",
      "country": "GB"
    }
  }'

Response

Successful payment initiation returns:

{
  "status": "success",
  "payment_id": "PAY_ABC123XYZ",
  "order_id": "ORD-100234",
  "payment_url": "https://payment.fiatdna.com/checkout/PAY_ABC123XYZ",
  "expires_at": "2026-02-07T05:43:00Z"
}

Common Errors you may see

ErrorCause
EXPIRED_REQUESTTimestamp too old/new
INVALID_SIGNATUREWrong signature rules
DUPLICATE_REQUESTSame Idempotency-Key used twice
UNAUTHORIZEDInvalid token

Creating a Payment Signature

To ensure secure and consistent payment processing, you must generate a signature using SHA-256 hashing. The signature prevents tampering and guarantees data integrity of your request.

Fields used in the signature

You will use the following fields:

  • merchant_id — Your unique merchant identifier
  • order_id — Unique order reference number
  • amount — Payment amount in decimal format (e.g., 100.00)
  • currency — ISO currency code (e.g., USD, EUR, LKR)
  • timestamp — UTC Unix timestamp (seconds) sent in X-Timestamp header
  • signature_key — Your private signature key (must never be sent in the request)

Step 01 : Mandatory rule — sort parameters A → Z

Before creating the signature, you must sort the parameters alphabetically (a–z) by parameter name.

Correct sorted order

After sorting alphabetically by name, your order MUST be:

  1. amount
  1. currency
  1. merchant_id
  1. order_id
  1. timestamp
❗ If parameters are not sorted correctly, the signature will be rejected.

Step 02 : Convert amount to integer (MANDATORY)

Multiply amount by 100 and remove decimals.

Your amountValue you MUST use
100.0010000
2500.50250050
1.75175

👉 Use this value for signature generation.

Step 03 : MD5 the Signature Key

Do NOT sort signature_key.

Instead:

  • Generate MD5 hash
  • Append it at the end

Example:

md5("signature_key_999") =5d41402abc4b2a76b9719d911017c592

Step 04 : Build the final string

Concatenate in this exact format:

amount_integer + currency + merchant_id + order_id + timestamp + md5(signature_key)

Example result:

10000usdmerchant_abcorder_12317073000005d41402abc4b2a76b9719d911017c592

Apply SHA-256

Hash the string using SHA-256 and convert to UPPERCASE hex:

SHA256(10000usdmerchant_abcorder_12317073000005d41402abc4b2a76b9719d911017c592)
→ A1B2C3D4E5F6...

This is your final payment signature

Signature Generation Process

Concatenate the above fields and hash them using SHA256:

<?php

$merchant_id     = "MERCHANT_ABC";
$order_id        = "ORDER_123";
$amount_decimal  = "100.00";
$currency        = "USD";
$signature_key = "Signature_KEY_999";

// STEP 1: Convert amount to integer
$amount_integer = (int) round($amount_decimal * 100);

// STEP 2: Lowercase values
$merchant_id = strtolower($merchant_id);
$order_id    = strtolower($order_id);
$currency    = strtolower($currency);

// STEP 3: MD5 the secret (must be last)
$md5_signature_key = md5(strtolower($signature_key));

// STEP 4: Concatenate in sorted order
$signatureString =
    $amount_integer .
    $currency .
    $merchant_id .
    $order_id .
    $md5_signature_key;

// STEP 5: SHA-256 + uppercase
$signature = strtoupper(hash("sha256", $signatureString));

echo "Signature: " . $signature;

Common mistakes to avoid

MistakeResult
Forgetting to include timestampInvalid signature
Using local time instead of UTCInvalid signature
Not multiplying amount by 100Invalid signature
Not sorting parameters A → ZInvalid signature
Forgetting MD5 of merchant_secretInvalid signature
Sending uppercase valuesInvalid signature
Using 100 instead of 10000Invalid signature

Webhook Notifications

CartDna will send payment notifications to your webhook URL whenever a payment status changes. The webhook payload includes all transaction details and a signature that you must verify to ensure the authenticity of the notification.

Webhook Payload Structure

The webhook will send a POST request to your webhook_url with the following payload:

{
  "merchant_id": "MERCHANT_12345",
  "order_id": "ORDER_67890",
  "payment_id": "PAY_ABC123XYZ",
  "amount": "250.00",
  "currency": "USD",
  "status": "success",
  "transaction_id": "TXN_987654321",
  "payment_method": "cartdna_card",
  "timestamp": "2026-02-07T05:45:00Z",
  "metadata": {
      "cart_id": "CART-5566"
    },
  "acquirer": {
    "acquirer_reference": "PH-55667788",
    "acquirer_status": "APPROVED",
    "acquirer_status_code": "00",
    "acquirer_reason_code": "000",
    "acquirer_reason_message": "Transaction Approved",
  },

  "signature": "B7C8D9E0F1A2..."
}

FieldTypeDescriptionExample
acquirer.acquirer_referenceStringGateway/processor reference numberPH-55667788
acquirer.acquirer_statusStringFinal status from the gatewayAPPROVED / DECLINED
acquirer.acquirer_status_codeStringNumeric code from gateway00
acquirer.acquirer_reason_codeStringGateway-specific reason code000
acquirer.acquirer_reason_messageStringHuman-readable gateway messageTransaction Approved

Verifying Webhook Signature

To ensure the webhook notification truly came from CartDNA and was not altered in transit, you must recreate the signature using the same rules as the payment request and compare it with the signature you received in the webhook payload.

If the two signatures do not match, the notification must be rejected.

Fields used for verification

You will use these fields from the webhook payload:

  • merchant_id
  • order_id
  • payment_id
  • amount
  • currency
  • signature_key (your signature key — NOT in the payload)

Mandatory normalization rules (must follow exactly)

Before building the verification string:

  1. Multiply amount by 100 and convert to integer
Amount in payloadValue you must use
250.0025000
99.959995

After sorting, the order becomes:

amount
currency
merchant_id
order_id
payment_id
  1. Do NOT include signature_key in sorting

    Instead, convert it to MD5 and append it LAST.

Final concatenation format

Build the string exactly like this:

amount_integer+ currency+ merchant_id+ order_id+ payment_id+ status+ md5(signature_key)

Then:

  • Apply SHA-256
  • Convert result to UPPERCASE hexadecimal

Step-by-step verification process

  1. Extract signature from the webhook payload
  1. Sort parameters A → Z
  1. Append md5(merchant_secret) at the end
  1. SHA-256 hash the concatenated string
  1. Convert hash to uppercase
  1. Compare with received signature

If they match → accept the webhook

If they do not match → reject the webhook

Common mistakes to avoid in Signature verification

MistakeResult
Not multiplying amount by 100Invalid signature
Not sorting A→ZInvalid signature
Including merchant_secret in sortingInvalid signature
Forgetting MD5 on merchant_secretInvalid signature
Comparing lowercase hashInvalid signature

Example Verification Code (PHP)

<?php

// --------------------------------------------------
// 1) Your merchant secret (NEVER read this from payload)
// --------------------------------------------------
$signature_key = "SIGNATURE_KEY_999";

// --------------------------------------------------
// 2) Webhook payload you received (example)
//    In real life this comes from: json_decode(file_get_contents("php://input"), true);
// --------------------------------------------------
$payload = [
    "merchant_id"   => "MERCHANT_12345",
    "order_id"      => "ORDER_67890",
    "payment_id"    => "PAY_ABC123XYZ",
    "amount"        => "250.00",
    "currency"      => "USD",
    "status"        => "success",
    "signature"     => "B7C8D9E0F1A2..."   // signature sent by CartDNA
];

// --------------------------------------------------
// 3) Extract received signature
// --------------------------------------------------
$receivedSignature = $payload['signature'];

// --------------------------------------------------
// 4) Normalize values
// --------------------------------------------------

// Convert amount to integer (× 100)
$amount_integer = (int) round($payload['amount'] * 100);

// Lowercase text fields
$merchant_id = strtolower($payload['merchant_id']);
$order_id    = strtolower($payload['order_id']);
$payment_id  = strtolower($payload['payment_id']);
$currency    = strtolower($payload['currency']);
$status      = strtolower($payload['status']);

// --------------------------------------------------
// 5) Sort parameters A → Z by name
//    Final order must be:
//    amount, currency, merchant_id, order_id, payment_id, status
// --------------------------------------------------
$sortedValues = [
    "amount"       => $amount_integer,
    "currency"     => $currency,
    "merchant_id"  => $merchant_id,
    "order_id"     => $order_id,
    "payment_id"   => $payment_id
];

ksort($sortedValues);   // ensures A → Z order

// --------------------------------------------------
// 6) MD5 the merchant secret (must be LAST)
// --------------------------------------------------
$md5_secret = md5(strtolower($merchant_secret));

// --------------------------------------------------
// 7) Build the signature string
// --------------------------------------------------
$signatureString =
    $sortedValues['amount'] .
    $sortedValues['currency'] .
    $sortedValues['merchant_id'] .
    $sortedValues['order_id'] .
    $sortedValues['payment_id'] .
    $sortedValues['status'] .
    $md5_secret;

// --------------------------------------------------
// 8) Generate SHA-256 and uppercase
// --------------------------------------------------
$calculatedSignature = strtoupper(hash("sha256", $signatureString));

// --------------------------------------------------
// 9) Compare signatures
// --------------------------------------------------
if (hash_equals($calculatedSignature, $receivedSignature)) {
    echo "✅ Webhook VERIFIED — process the payment update.";
} else {
    echo " INVALID SIGNATURE — reject webhook.";
}

Webhook Response

Your webhook endpoint should respond with HTTP status code 200 to acknowledge receipt. If CartDna doesn't receive a 200 response, it will retry sending the webhook notification up to 3 times with exponential backoff.

Payment Status Values

The status field in the webhook payload can have the following values:

  • success - Payment completed successfully
  • pending - Payment is being processed
  • failed - Payment failed
  • cancelled - Payment was cancelled by the customer
  • refunded - Payment has been refunded

Security Best Practices

  • Always verify the signature - Never process a webhook without signature verification
  • Use HTTPS - Ensure your webhook URL uses HTTPS for secure communication
  • Keep your merchant_secret secure - Never expose this in client-side code or public repositories
  • Log webhook attempts - Keep logs of all webhook notifications for debugging and auditing
  • Implement idempotency - Handle duplicate webhook notifications gracefully by checking if the order has already been processed

Capture Payment (For transaction_type = auth)

If the original payment request was created with:

transaction_type = auth

then the funds are only authorized (reserved) and not charged yet.

To complete the payment, you must call the Capture Payment API.

Endpoint

POST /v1/payments/{payment_id}/capture
  • {payment_id} → The payment ID returned in the authorization response.

Required Headers

HeaderRequiredDescriptionExample
AuthorizationYesOAuth Bearer tokenBearer YOUR_TOKEN
Content-TypeYesJSON formatapplication/json
X-TimestampYesUTC Unix timestamp (seconds)1707300000
X-Idempotency-KeyYesUnique key per request550e8400-e29b-41d4-a716-446655440000
X-SignatureYesSHA-256 signatureC9D0E1F2A3B4…

Request Body Parameters

ParameterTypeRequiredDescriptionExample
amountDecimalNoAmount to capture (allows partial capture)1500.00
If amount is not provided, CartDNA will capture the full authorized amount.

Signature Rule for Capture Request

To generate the signature, follow the same security rules as the payment request, but use these fields:

amount_integer+ currency+ merchant_id+ payment_id+ timestamp+ md5(signature_key)

Steps

  1. Multiply amount by 100 and convert to integer
  1. Lowercase all text values
  1. Sort parameters A → Z
  1. Append md5(signature_key) last
  1. Apply SHA-256 and convert to UPPERCASE


Example cURL Request

curl -X POST https://api.fiatdna.com/v1/payments/PAY_ABC123XYZ/capture \
  -H"Authorization: Bearer YOUR_TOKEN" \
  -H"Content-Type: application/json" \
  -H"X-Timestamp: 1707300000" \
  -H"X-Idempotency-Key: 660e8400-e29b-41d4-a716-446655440111" \
  -H"X-Signature: C9D0E1F2A3B4...." \
  -d '{
    "amount": 1500.00
  }'

Success Response (201 Created)

{
  "status": "success",
  "payment_id": "PAY_ABC123XYZ",
  "captured_amount": 1500.00,
  "currency": "USD",
  "capture_status": "CAPTURED",
  "captured_at": "2026-02-07T06:10:00Z"
}

Capture Status Values

StatusMeaning
CAPTUREDFull authorized amount captured
PARTIALLY_CAPTUREDOnly part of the amount captured
FAILEDCapture attempt failed
VOIDEDAuthorization was cancelled before capture
EXPIREDAuthorization window expired

Important Rules

  • You cannot capture if status is not AUTHORIZED
  • You can capture multiple times (partial capture) until the full amount is used
  • Capture must happen within the authorization window defined by CartDNA
  • Each capture request must use a new X-Idempotency-Key

Get Payment Status API

Overview

This endpoint allows merchants to retrieve the latest status of a payment created through CartDNA. It returns the current payment state, amount, currency, gateway details, and timestamps. This API is useful when a webhook was missed, delayed, or when manual verification is required.

GET /payments/{payment_id}

Required Headers

HeaderRequiredDescriptionExample
AuthorizationYesBearer TokenBearer YOUR_TOKEN
Content-TypeYesRequest formatapplication/json

Path Parameter

ParameterTypeRequiredDescriptionExample
payment_idStringYesUnique payment identifierPAY_ABC123XYZ

cURL Example

curl -X GET"https://api.fiatdna.com/v1/payments/PAY_ABC123XYZ" \
  -H"Authorization: Bearer YOUR_API_KEY" \
  -H"Content-Type: application/json"

Success Response (200 OK)

{
  "merchant_id": "MERCHANT_12345",
  "order_id": "ORDER_67890",
  "payment_id": "PAY_ABC123XYZ",
  "amount": "250.00",
  "currency": "USD",
  "status": "success",
  "transaction_id": "TXN_987654321",
  "payment_method": "cartdna_card",
  "timestamp": "2026-02-07T05:45:00Z",

  "acquirer": {
    "acquirer_reference": "PH-55667788",
    "acquirer_status": "APPROVED",
    "acquirer_status_code": "00",
    "acquirer_reason_code": "000",
    "acquirer_reason_message": "Transaction Approved",
  }
}

Possible Payment Status Values

StatusMeaning
PENDINGPayment initiated but not completed
AUTHORIZEDFunds reserved (preauth) but not captured yet
CAPTUREDAuthorized payment fully captured
SUCCESSImmediate payment completed successfully (when transaction_type = payment)
FAILEDPayment attempted but failed
CANCELLEDUser or merchant cancelled the payment/authorization
REFUNDEDFull amount was refunded
PARTIALLY_REFUNDEDPart of the amount was refunded
EXPIREDAuthorization window expired before capture

Error Responses

404 Not Found

{
"status":"error",
"error_code":"NOT_FOUND",
"message":"Payment ID not found"
}

401 Unauthorized

{
"status":"error",
"error_code":"UNAUTHORIZED",
"message":"Invalid or missing API key"
}

Void Authorization (For transaction_type = auth)

If the original payment was created with:

transaction_type = auth

and you no longer want to capture the funds, you can void (cancel) the authorization before any capture happens.

Once voided, no funds can be captured from that authorization.


Endpoint

POST /v1/payments/{payment_id}/void
  • {payment_id} → The authorized payment ID returned in the original response.

Required Headers

HeaderRequiredDescriptionExample
AuthorizationYesOAuth Bearer tokenBearer YOUR_TOKEN
Content-TypeYesJSON formatapplication/json
X-TimestampYesUTC Unix timestamp (seconds)1707300000
X-Idempotency-KeyYesUnique key per request770e8400-e29b-41d4-a716-446655440222
X-SignatureYesSHA-256 signatureD1E2F3A4B5C6…

Request Body Parameters

No body is required.

(You can optionally send metadata if you want an audit reason.)

ParameterTypeRequiredDescriptionExample
reasonStringNoBusiness reason for void“Customer cancelled order”

Example body (optional):

{"reason":"Customer cancelled order"}

Signature Rule for Void Request

Use the same normalization rules as before, but the fields are:

currency+ merchant_id+ payment_id+ timestamp+ md5(signature_key)

Steps

  1. Lowercase all text values
  1. Sort parameters A → Z
  1. Append md5(merchant_secret) last
  1. Apply SHA-256 and convert to UPPERCASE
Note: No amount is used for void because nothing is being captured or refunded.

Example cURL Request

curl -X POST https://api.fiatdna.com/v1/payments/PAY_ABC123XYZ/void \
  -H"Authorization: Bearer YOUR_TOKEN" \
  -H"Content-Type: application/json" \
  -H"X-Timestamp: 1707300000" \
  -H"X-Idempotency-Key: 770e8400-e29b-41d4-a716-446655440222" \
  -H"X-Signature: D1E2F3A4B5C6...." \
  -d '{
    "reason": "Customer cancelled order"
  }'

Success Response (200 OK)

{
"status":"success",
"payment_id":"PAY_ABC123XYZ",
"void_status":"VOIDED",
"voided_at":"2026-02-07T06:20:00Z",
"message":"Authorization successfully voided"
}

Void Status Values

StatusMeaning
VOIDEDAuthorization successfully cancelled
FAILEDVoid attempt failed
ALREADY_CAPTUREDCannot void because funds were already captured
EXPIREDAuthorization already expired

Refund Payment API — Detailed Specification

Overview

This endpoint allows merchants to request a full or partial refund for a completed payment.

Refunds are processed asynchronously — the final outcome should be checked via the Refund Status API or received through a refund webhook.

Endpoint

POST /payments/{payment_id}/refund

Required Headers

HeaderRequiredDescriptionExample
AuthorizationYesBearer access tokenBearer eyJhbGciOiJIUzI1Ni...
Content-TypeYesRequest formatapplication/json

Path Parameter

ParameterTypeRequiredDescriptionExample
payment_idStringYesCartDNA payment identifierPAY_ABC123XYZ

Request Body Parameters

ParameterTypeRequiredDescriptionExample
amountDecimalYesRefund amount (can be partial)500.00

CURL Example

curl -X POST"https://api.fiatdna.com/v1/payments/PAY_ABC123XYZ/refund" \
  -H"Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H"Content-Type: application/json" \
  -d '{
    "amount": 500.00,
    "reason": "Customer requested cancellation"
  }'

Success Response (201 Created)

{
  "status": "success",
  "refund_id": "RF_998877",
  "payment_id": "PAY_ABC123XYZ",
  "requested_amount": 500.00,
  "currency": "USD",
  "refund_status": "PROCESSING",
  "requested_at": "2026-02-07T06:00:00Z"
}

Response Fields

FieldTypeDescriptionExample
statusStringOverall request resultsuccess
refund_idStringCartDNA refund identifierRF_998877
payment_idStringOriginal payment referencePAY_ABC123XYZ
requested_amountDecimalAmount requested for refund500.00
currencyStringCurrency of refundLKR
refund_statusStringCurrent refund statePROCESSING
requested_atDateTimeTime refund was requested2026-02-07T06:00:00Z

Refund Status Values

StatusMeaning
PROCESSINGRefund is being handled by gateway
REFUNDEDFull refund completed
PARTIALLY_REFUNDEDPartial refund completed
FAILEDRefund rejected or failed
CANCELLEDRefund request cancelled

How CartDNA determines final status

  • If amount = original payment amountREFUNDED
  • If amount < original payment amountPARTIALLY_REFUNDED

Error Responses

400 Bad Request

{
  "status": "error",
  "error_code": "INVALID_REQUEST",
  "message": "Refund amount exceeds original payment amount"
}

404 Not Found

{
  "status": "error",
  "error_code": "NOT_FOUND",
  "message": "Payment ID not found"
}

401 Unauthorized

{
  "status": "error",
  "error_code": "UNAUTHORIZED",
  "message": "Invalid or missing access token"
}

Gateway Error Codes — Reference Table (with Internal Code)

Public Error CodeInternal CodeHTTP StatusCategoryMeaningWhen it occursSuggested Action
INVALID_REQUESTCDN-400-001400ValidationRequest format is invalidMissing fields, wrong data type, or invalid valuesFix request payload and retry
MISSING_REQUIRED_FIELDCDN-400-002400ValidationRequired parameter not providede.g., missing order_id, amount, or currencyAdd required field and retry
INVALID_AMOUNTCDN-400-003400ValidationAmount is zero or negativeamount ≤ 0Send valid amount
INVALID_CURRENCYCDN-400-004400ValidationUnsupported currencyCurrency not allowed by gatewayUse supported currency
INVALID_PAYMENT_METHODCDN-400-005400ValidationPayment method not supportedWrong payment_method codeUse valid method
UNAUTHORIZEDCDN-401-001401AuthenticationAPI key is missing or invalidNo Bearer token or wrong keyProvide valid API key
INVALID_SIGNATURECDN-401-002401SecurityRequest signature mismatchTampered payload or wrong secretRegenerate correct signature
FORBIDDENCDN-403-001403AuthorizationMerchant not allowedInactive merchant or feature blockedContact CartDNA support
NOT_FOUNDCDN-404-001404ResourcePayment ID does not existWrong payment_id usedVerify payment ID
PAYMENT_NOT_FOUNDCDN-404-002404ResourceNo matching paymentDeleted or never createdCreate payment first
REFUND_NOT_ALLOWEDCDN-400-010400RefundRefund not permittedPayment not completed or already refundedCheck payment status
REFUND_AMOUNT_EXCEEDEDCDN-400-011400RefundRefund > original amountTrying to refund more than paidReduce refund amount
GATEWAY_TIMEOUTCDN-504-001504GatewayPayment provider did not respondPayHere/Stripe/Bank delayRetry later
GATEWAY_ERRORCDN-502-001502GatewayProvider rejected paymentCard declined, insufficient funds, etc.Ask customer to retry
DUPLICATE_ORDERCDN-409-001409BusinessOrder already processedSame order_id reusedUse unique order_id
SESSION_EXPIREDCDN-410-001410SessionPayment link expiredCheckout URL used after expiryCreate new payment
INTERNAL_ERRORCDN-500-001500SystemCartDNA system failureUnexpected server errorRetry or contact support
SERVICE_UNAVAILABLECDN-503-001503SystemSystem temporarily downMaintenance or overloadTry again later