1. Collections
Asteria API DOCs
  • Getting Started
  • Webhooks
  • Auth
    • Validate & Generate Access Token
      POST
  • Collections
    • Pay via Bank Transfer
      • Get Banks
      • Generate Dynamic VIrtual Account
      • Check Payment Status
    • Cards
      • Generate Payment Advice
      • Charge Card
      • Check Card Payment Status
    • Mpesa
      • Mpesa API
    • International Cards
      • Setup Card
      • Check Enrollment
      • Validate Challenge
      • Get Status
  • Payouts
    • Get Bank List
      GET
    • Validate Account
      POST
    • Initiate Transfer
      POST
    • Check Payout Status
      POST
  • Account
    • Get Wallet Balance
      GET
  1. Collections

International Cards

International Card Collections#

Use these APIs to charge international cards in USD. Authenticate with your existing API key and JWT, the same way you call other Collections endpoints.

Flow#

1.
Call Setup.
2.
Load the returned ddcForm in the browser (hidden iframe). Wait for it to finish.
3.
Call Check Enrollment.
4.
If authStatus is FRICTIONLESS_SUCCESS, skip to step 6.
5.
If authStatus is CHALLENGE_REQUIRED, load challengeForm, wait for the customer to finish, then call Validate.
6.
Call Status until status is PAID.
nextAction on every response tells you what to do next: LOAD_DDC, LOAD_CHALLENGE, CONFIRM_STATUS, RETRY_STATUS, or DONE.

1. Setup#

POST /collections/intl-card/setup
Creates a USD payment session and returns the device-data collection form.
Request:
{
  "amount": 20,
  "reference": "INTL-CARD-123456",
  "cardNumber": "4456530000001005",
  "expiredMonth": "01",
  "expiredYear": "2029",
  "customerName": "QA Test",
  "customerEmail": "qa@example.com",
  "narration": "International card payment"
}
customerName, customerEmail, and narration are optional.
Response:
{
  "responseStatus": "SUCCESSFUL",
  "message": "International card setup initiated successfully",
  "data": {
    "txnRef": "435df745-6a24-4b39-8c81-9f89da1213a0",
    "reference": "INTL-CARD-123456",
    "amount": "20.0",
    "currency": "USD",
    "ddcUrl": "https://centinelapistag.cardinalcommerce.com/V1/Cruise/Collect",
    "ddcJwt": "eyJhbGciOiJIUzI1NiIs...",
    "ddcForm": "<iframe name=\"ddc-iframe\" ...",
    "nextAction": "LOAD_DDC"
  }
}
Frontend: inject data.ddcForm into the page (or POST ddcJwt to ddcUrl in a hidden iframe named ddc-iframe). This step is required before enrollment.

2. Check Enrollment#

POST /collections/intl-card/check-enrollment
Call this after the DDC iframe has completed. Send the same card plus billing details.
Request:
{
  "txnRef": "435df745-6a24-4b39-8c81-9f89da1213a0",
  "cardNumber": "4456530000001005",
  "expiredMonth": "01",
  "expiredYear": "2029",
  "cvv": "123",
  "cardHolderName": "QA Test",
  "billingEmail": "qa@example.com",
  "billingPhone": "08012345678",
  "billingAddress": "8 Admiralty Road",
  "billingCity": "Lagos",
  "billingState": "LA",
  "billingCountry": "NG",
  "billingPostalCode": "100010"
}
billingState and billingCountry must be 2-letter codes.

Frictionless success#

nextAction is CONFIRM_STATUS. Call Status next.
{
  "responseStatus": "SUCCESSFUL",
  "data": {
    "txnRef": "435df745-6a24-4b39-8c81-9f89da1213a0",
    "authStatus": "FRICTIONLESS_SUCCESS",
    "stepUpUrl": null,
    "accessToken": null,
    "challengeForm": null,
    "csPaymentId": "7906722562756753903814",
    "approvalCode": "541485",
    "nextAction": "CONFIRM_STATUS"
  }
}

Challenge required#

Inject data.challengeForm so the customer can complete 3DS, then call Validate.
{
  "responseStatus": "SUCCESSFUL",
  "data": {
    "txnRef": "b99e4c10-7ec6-4a24-8826-f39cc7f041f1",
    "authStatus": "CHALLENGE_REQUIRED",
    "stepUpUrl": "https://centinelapistag.cardinalcommerce.com/V2/Cruise/StepUp",
    "accessToken": "eyJhbGciOiJIUzI1NiIs...",
    "challengeForm": "<iframe name=\"step-up-iframe\" ...",
    "csPaymentId": null,
    "approvalCode": null,
    "nextAction": "LOAD_CHALLENGE"
  }
}

3. Validate Challenge#

POST /collections/intl-card/validate
Only if enrollment returned CHALLENGE_REQUIRED, after the challenge iframe completes.
Request:
{
  "txnRef": "b99e4c10-7ec6-4a24-8826-f39cc7f041f1"
}
Response:
{
  "responseStatus": "SUCCESSFUL",
  "data": {
    "txnRef": "b99e4c10-7ec6-4a24-8826-f39cc7f041f1",
    "status": "AUTHORIZED",
    "csPaymentId": "7906730242056000403813",
    "approvalCode": "972480",
    "nextAction": "CONFIRM_STATUS"
  }
}

4. Get Status#

GET /collections/intl-card/status/{txnRef}
Confirms the final outcome. Use this after frictionless success or after validate. Repeat until status is PAID.
Response:
{
  "responseStatus": "SUCCESSFUL",
  "data": {
    "txnRef": "435df745-6a24-4b39-8c81-9f89da1213a0",
    "reference": "INTL-CARD-123456",
    "status": "PAID",
    "collectionStatus": "SUCCESS",
    "amount": "20.00",
    "currency": "USD",
    "csPaymentId": "7906722562756753903814",
    "approvalCode": "541485",
    "nextAction": "DONE"
  }
}
When status is PAID, the merchant USD wallet is credited (minus the configured USD card collection fee).

Notes#

Currency is always USD. Do not send a currency field.
reference must be unique per merchant.
Never log or store CVV. Card numbers are masked in Asteria records.
Keep using the same txnRef for enrollment, validate, and status.
Modified at 2026-10-21 13:38:20
Previous
Mpesa API
Next
Setup Card
Built with