Card Collection

Accept card payments from customers in NGN and USD with 3-D Secure where required. Transfaar hosts the payment UI, so raw card data never touches your servers and you do not need PCI certifications.

Quick Facts

  • Supported currencies: NGN, USD
  • Base URL: https://api.transfaar.com/api/v1
  • Authentication: HMAC (X-API-Key, X-Timestamp, X-Signature) — required only for initialize / verify / refund; the payment itself runs on the public hosted checkout, authenticated by the access_code
  • PCI model: hosted checkout — card data is encrypted client-side and handled by Transfaar's payment provider

Quote vs checkout: card collection is a checkout flow, not a Quotes flow. Only initialization (and verify/refund) use your signed API key. The customer completes payment on the public hosted page, authenticated by the access_code alone, so it runs in a browser or mobile client without exposing your keys.

Flow

  1. Initialize — Create a checkout session from your backend (POST /client/checkout/initialize).
  2. Redirect — Send the customer to the returned checkout_link to pay on the hosted page.
  3. Confirm — Receive the result via webhooks (source of truth) and optionally the verify API.
  4. Reconcile — Store your reference with the returned transactionRef for support and reconciliation.

If you want to build your own card form instead of the hosted page, see API-driven card checkout.

Initialize Payment

POST /client/checkout/initialize (protected — HMAC API key)

This is the only step that uses your signed API key — never perform it on the browser or mobile client.

Request Body

json
{  "email": "customer@example.com",  "first_name": "John",  "last_name": "Doe",  "amount": "1000.00",  "currency": "USD",  "reference": "ORDER-12345",  "redirectUrl": "https://your-website.com/payment-success",  "logoUrl": "https://your-website.com/logo.png",  "description": "Payment for order #12345",  "checkout_display_name": "My Store",  "customer_phone_number": "+2348012345678",  "hide_card": true,  "metadata": {    "custom_field": "value"  }}
ParameterTypeRequiredDescription
emailstringYesCustomer email address
first_namestringYesCustomer first name
last_namestringYesCustomer last name
amountstringYesDecimal string such as "1000.00"
currencystringYesNGN or USD
referencestringYesYour unique payment reference
redirectUrlstringNoCustomer redirect destination after checkout
logoUrlstringNoMerchant logo shown on hosted checkout
descriptionstringNoPayment description
checkout_display_namestringNoMerchant name shown on checkout
customer_phone_numberstringNoCustomer phone number
hide_cardbooleanNoSet to true to remove card from the checkout's payment methods (useful when you want to force bank transfer / mobile money)
metadataobjectNoOptional tracking fields

Success Response

json
{  "success": true,  "message": "Transaction Initialized Successfully",  "data": {    "access_code": "AbCdEfGhIjKlMnOpQrStUv",    "checkout_link": "https://checkout.transfaar.com/checkout/AbCdEfGh...",    "transactionRef": "TXN-123456789",    "reference": "ORDER-12345",    "redirectUrl": "https://your-website.com/payment-success",    "valid_until": "2026-05-02T12:30:00Z"  }}

Keep the access_code — it authenticates the payment endpoints below.

Payment Endpoints (Public)

These endpoints are used by the hosted checkout page and are public — no API key or signature is required. They are authenticated by the access_code returned from initialization.

1. Discover methods for a currency

GET /checkout/currency-methods/:currency

Lists the payment methods available for a currency, so you can render the right options without hardcoding them.

Example — GET /checkout/currency-methods/USD

Response:

json
["CARD"]

Example — GET /checkout/currency-methods/NGN

Response:

json
["CARD", "BANK_TRANSFER", "OPAY", "USSD"]

2. Select the payment method

POST /checkout/:access_code/select-method

Selects the payment method for the checkout session. For card payments, send CARD.

Request Body

json
{  "method": "CARD"}

Success Response

json
{  "quote_id": "3d8b1e2f-5a1c-4f2a-9c3e-6f7a8b9c0d1e",  "transaction_id": "6196e335-a293-4c9e-b292-1e1ab219ea20",  "transaction_reference": "TXN-123456789",  "payment_details": {    "quote_id": "3d8b1e2f-5a1c-4f2a-9c3e-6f7a8b9c0d1e",    "type": "card"  },  "total_payable": "1000.00",  "timeline": {    "created_at": "2026-05-02T12:00:00Z",    "valid_until": "2026-05-02T12:30:00Z"  },  "status": "AWAITING_PAYMENT"}

3. Charge the card

POST /card/card-charge

Submits the card payment for a checkout session. The request is a hybrid-encrypted envelope: the card data payload is encrypted with AES-256-GCM, and the AES key is encrypted with RSA-OAEP-SHA256 using the checkout public key. The envelope is authenticated by the access_code in the payload, so no HMAC signature is required.

Envelope Request Body

json
{  "access_code": "AbCdEfGhIjKlMnOpQrStUv",  "encrypted_key": "<base64 RSA-OAEP-encrypted AES key>",  "iv": "<base64 AES-GCM nonce/IV (12 bytes)>",  "encrypted_payload": "<base64 AES-GCM ciphertext + tag>"}

Decrypted inner payload (encrypted_payload before encryption)

json
{  "card_number": "5399838383838381",  "cvv": "123",  "expiry_month": "12",  "expiry_year": "25",  "amount": "1000.00",  "currency": "USD",  "customer_email": "customer@example.com",  "name_on_card": "John Doe",  "customer_phone_number": "+18005550199",  "transaction_reference": "TXN-123456789",  "description": "Payment for order #12345",  "webhook_url": "https://your-website.com/card-webhook",  "business_code": "your-business-code"}

Success Response (payment completed)

json
{  "success": true,  "message": "Card charge initiated successfully",  "paymentCompleted": true,  "data": {    "transaction_reference": "TXN-123456789",    "status": "completed",    "amount": "1000.00",    "currency": "USD",    "authorization_code": "AUTH123456",    "payment_method": "card",    "paymentCompleted": true  }}

Response (3-D Secure required)

When 3-D Secure is required, the payment is not yet complete. Redirect the customer to the returned threeDsUrl to complete the challenge, then poll for the final status:

json
{  "success": true,  "message": "3DS authentication required",  "do3dsAuth": true,  "threeDsUrl": "https://pay.3ds-provider.com/challenge/abc123",  "paymentCompleted": false,  "data": {    "transaction_reference": "TXN-123456789",    "status": "pending",    "amount": "1000.00",    "currency": "USD",    "paymentCompleted": false  }}

4. Check payment status

GET /checkout/:access_code/payment-status

Returns the current payment status for a checkout session.

Example — GET /checkout/AbCdEfGhIjKlMnOpQrStUv/payment-status

Response:

json
{  "status_id": 5,  "status_name": "COMPLETED",  "deposit_confirmed_at": "2026-05-02T12:25:00Z",  "rail_name": "CARD",  "transaction_status_id": 3,  "transaction_status_name": "COMPLETED",  "payment_completed": true}

Verify Payment Status

GET /client/payment/verify?reference={transaction_reference} (protected — HMAC API key)

or, for checkout sessions, use the reference you supplied during initialization:

GET /client/payment/verify?origin_reference={your_checkout_reference}

QueryRequiredDescription
referenceRequired if origin_reference is not sentTransfaar transaction_reference returned during initialization
origin_referenceRequired if reference is not sentYour checkout reference, stored by Transfaar as origin_reference

When origin_reference is used, Transfaar resolves the matching checkout quote/transaction and returns the same response shape.

Success Response

json
{  "transaction_id": "6196e335-a293-4c9e-b292-1e1ab219ea20",  "transaction_reference": "ABA261C575EEFC76",  "status_name": "COMPLETED",  "status_id": 2,  "amount_tendered_with_fees": "1020.00",  "amount_tendered_without_fees": "1000.00",  "amount_received": "1000.00",  "source_currency": "NGN",  "target_currency": "NGN",  "payment_completed": true,  "paymentCompleted": true,  "transaction_status": "COMPLETED",  "status": "COMPLETED",  "amount": "1020.00",  "currency": "NGN",  "message": "Payment status retrieved successfully",  "provider_transaction_status": "completed",  "provider_status_reason": "Approved"}
FieldDescription
status_nameCanonical status such as PENDING, PROCESSING, COMPLETED, FAILED
amount_tendered_with_feesTotal amount charged to the customer
amount_receivedNet amount credited after fees
payment_completedBoolean completion flag

Refunds

Refunds share a single endpoint across all supported currencies — see the full Refunds page for request/response fields, eligibility rules, status values, and error handling. When initiating a refund, pass the deposit's transaction_reference, not its internal transaction_id UUID.

  • POST /client/payment/refund — initiate a refund
  • GET /client/payment/refund/status/:refund_reference — check refund status
  • GET /client/payment/refund/history — list refund history

Testing

Use staging for all test card scenarios and webhook validation.

Test Cards

Card TypeCard Number3DSExpiryCVVResult
Visa4508 7500 1574 1019Yes01/39100Approved
Mastercard5123 4500 0000 0008Yes01/39100Approved
Mastercard5111 1111 1111 1118No01/39100Approved

To simulate failures, use these expiry dates:

  • 05/39 for decline
  • 04/27 for expired card
  • 08/28 for timeout behavior

Recommended Test Matrix

  1. Successful 3DS payment
  2. Successful non-3DS payment
  3. Declined card scenario
  4. Expired card scenario
  5. Timeout scenario
  6. Webhook retry handling
  7. Manual verify fallback after checkout completion

Best Practices

  1. Always use webhooks — network issues can prevent a customer from reaching your redirectUrl. Webhooks ensure you never miss a payment.
  2. Verify amounts — before providing service, verify that the amount in the webhook/verify response matches your expected order total.
  3. Use unique references — unique reference values for every initialization prevent duplicate charges for the same order.
  4. Secure your keys — never perform API calls or HMAC signing on the frontend. These should always happen on your secure backend.
  5. Keep references together — store your reference with the returned transactionRef for support and reconciliation.

Related Pages