Cards API
The Cards API allows you to initialize and track card payment sessions for your customers.
Overview
The card payment flow provides a simple integration pattern:
- Initialize Payment: Call the initialize API to create a payment session
- Persist References: Store
access_code,transactionRef, and yourreference - Webhook Notification: Receive payment status updates via webhooks
Benefits
- PCI Compliance: We handle all card data, so you don't need PCI DSS certification
- 3D Secure Support: Automatic handling of 3D Secure authentication
- Secure: All card data is encrypted and never touches your servers
- Easy Integration: Simple API calls to get started
Initialize Payment
Create a payment session and receive checkout references for your payment flow.
Endpoint
POST /api/v1/client/checkout/initialize
Authentication
This endpoint requires HMAC authentication. Include your API key and signature in the request headers:
x-api-key: <your-api-key>
x-timestamp: <rfc3339-timestamp>
x-signature: <hmac-sha256-signature>Request Body
{
"email": "customer@example.com",
"first_name": "John",
"last_name": "Doe",
"amount": "1000.00",
"currency": "NGN",
"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": "Instant Business",
"customer_phone_number": "+2348012345678"
}Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
email | string | Yes | Customer's email address |
first_name | string | Yes | Customer's first name |
last_name | string | Yes | Customer's last name |
amount | string | Yes | Payment amount (decimal string, e.g., "1000.00") |
currency | string | Yes | Currency code (ISO 4217, e.g., "NGN", "USD") |
reference | string | Yes | Your unique reference for this payment (for tracking) |
redirectUrl | string | No | URL to redirect customer after payment completion |
logoUrl | string | No | URL to your logo (displayed on checkout page) |
description | string | No | Description of the payment (displayed to customer) |
checkout_display_name | string | No | Merchant/business name displayed on checkout |
customer_phone_number | string | No | Customer's phone number (E.164 format recommended) |
Success Response (201 Created)
{
"success": true,
"message": "Transaction Initialized Successfully",
"data": {
"access_code": "AbCdEfGhIjKlMnOpQrStUv",
"checkout_link": "https://checkout.transfaar.com/checkout/AbCdEfGhIjKlMnOpQrStUv",
"transactionRef": "TXN-123456789",
"reference": "ORDER-12345",
"redirectUrl": "https://your-website.com/payment-success"
}
}Response Fields
| Field | Type | Description |
|---|---|---|
success | boolean | Indicates if the request was successful |
message | string | Human-readable message |
data.access_code | string | Unique 22-character access code for this payment |
data.checkout_link | string | Checkout session URL |
data.transactionRef | string | Transaction reference for tracking |
data.reference | string | Your original reference |
data.redirectUrl | string | Your redirect URL (if provided) |
Error Responses
400 Bad Request - Invalid request data
{
"error": "missing required fields: email, first_name, last_name, amount, currency, and reference are required"
}Other common 400 examples:
{
"error": "invalid amount"
}{
"error": "invalid currency: XYZ"
}{
"error": "invalid email"
}{
"error": "Reference is already used"
}401 Unauthorized - Invalid or missing authentication
{
"error": "unauthorized"
}Integration Flow
Step 1: Initialize Payment
When a customer is ready to pay, call the initialize endpoint with their details:
curl -X POST https://api.transfaar.com/api/v1/client/checkout/initialize \
-H "Content-Type: application/json" \
-H "x-api-key: your-api-key" \
-H "x-timestamp: 2025-01-15T10:30:00Z" \
-H "x-signature: your-hmac-signature" \
-d '{
"email": "customer@example.com",
"first_name": "John",
"last_name": "Doe",
"amount": "1000.00",
"currency": "NGN",
"reference": "ORDER-12345",
"redirectUrl": "https://your-website.com/payment-success",
"description": "Payment for order #12345"
}'Step 2: Receive Webhook Notification
You'll receive a webhook notification with the payment status. Configure your webhook URL in your business settings to receive real-time payment status updates.
Verify Payment Status
Verify a transaction status after checkout/3DS and get a normalized client response payload.
Endpoint
GET /api/v1/client/payment/verify
Authentication
This endpoint requires HMAC authentication headers:
x-api-key: <your-api-key>
x-timestamp: <rfc3339-timestamp>
x-signature: <hmac-sha256-signature>Query Parameters
Use a single query key for consistency:
| Parameter | Required | Description |
|---|---|---|
reference | Yes | Transaction reference |
For GET /api/v1/client/transactions/reference, use:
| Parameter | Required | Description |
|---|---|---|
transaction_ref | Yes | Transaction reference |
Success Response (200 OK)
{
"transaction_id": "6196e335-a293-4c9e-b292-1e1ab219ea20",
"transaction_reference": "ABA261C575EEFC76",
"status_name": "CANCELLED",
"status_id": 5,
"amount_tendered_with_fees": "120.00",
"amount_tendered_without_fees": "118.00",
"amount_received": "0.00",
"source_currency": "NGN",
"target_currency": "NGN",
"payment_completed": false,
"paymentCompleted": false,
"transaction_status": "CANCELLED",
"status": "CANCELLED",
"amount": "120.00",
"currency": "NGN",
"message": "Payment status retrieved from local records"
}Response Fields
| Field | Type | Description |
|---|---|---|
transaction_id | string | Internal transaction UUID |
transaction_reference | string | Transaction reference |
status_name | string | Canonical status name (PENDING, PROCESSING, COMPLETED, FAILED, CANCELLED) |
status_id | number | Canonical status ID |
amount_tendered_with_fees | string | Tendered amount including fees |
amount_tendered_without_fees | string | Tendered amount excluding fees |
amount_received | string | Final amount received |
source_currency | string | Source currency code |
target_currency | string | Target currency code |
payment_completed | boolean | Canonical completion flag |
message | string | Context message for retrieval source |
provider_transaction_status | string | Provider status (present when provider verification is used) |
provider_status_reason | string | Provider reason/details (present when provider verification is used) |
Legacy compatibility fields are also returned: paymentCompleted, transaction_status, status, amount, currency.
Error Responses
400 Bad Request
{
"error": "reference is required"
}401 Unauthorized
{
"error": "unauthorized"
}404 Not Found
{
"error": "payment not found"
}500 Internal Server Error
{
"error": "failed to verify payment status"
}Webhook Events
You'll receive webhook notifications for payment status changes. The webhook payload includes:
{
"transaction_reference": "TXN-123456789",
"transaction_status": "successful",
"amount": "1000.00",
"currency": "NGN",
"reference": "ORDER-12345",
"status": "completed"
}For more details on webhook handling, see the Webhooks documentation.
Initiate Refund
Request a refund for a previously completed card charge.
Endpoint
POST /api/v1/client/payment/refund
Authentication
This endpoint requires HMAC authentication headers:
x-api-key: <your-api-key>
x-timestamp: <rfc3339-timestamp>
x-signature: <hmac-sha256-signature>Request Body
{
"transaction_reference": "ORDER-12345",
"refund_amount": "500.00",
"refund_reason": "Customer requested cancellation"
}Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
transaction_reference | string | Yes | Your transaction reference from the original charge |
refund_amount | string | Yes | Amount to refund (must be greater than zero) |
refund_reason | string | Yes | Reason for the refund |
Success Response (200 OK)
{
"message": "refund initiated successfully",
"transaction_reference": "ORDER-12345",
"status": "PENDING",
"refund_reference": "REF-98765",
"refund_amount": 500,
"currency": "NGN"
}Response Fields
| Field | Type | Description |
|---|---|---|
message | string | Human-readable message |
transaction_reference | string | Your original transaction reference |
status | string | Refund status (PENDING, PROCESSING, COMPLETED, FAILED, CANCELLED) |
refund_reference | string | Reference for tracking this refund (use for status checks) |
refund_amount | number | Amount being refunded |
currency | string | Currency code |
Error Responses
400 Bad Request
{
"error": "transaction_reference is required"
}{
"error": "refund_amount must be greater than zero"
}{
"error": "refund_reason is required"
}404 Not Found
{
"error": "payment not found"
}502 Bad Gateway
{
"error": "failed to initiate refund"
}Check Refund Status
Check the current status of a previously initiated refund.
Endpoint
GET /api/v1/client/payment/refund/status/:reference
Authentication
This endpoint requires HMAC authentication headers:
x-api-key: <your-api-key>
x-timestamp: <rfc3339-timestamp>
x-signature: <hmac-sha256-signature>Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
reference | string | Yes | The refund_reference returned from the initiate refund response |
Success Response (200 OK)
{
"message": "refund status retrieved",
"refund_reference": "RF20260312-YK8ATTL92B0JUSD",
"refund_status": "COMPLETED",
"original_transaction_reference": "BE27E31B45508365",
"refund_amount": 17.78
}Response Fields
| Field | Type | Description |
|---|---|---|
message | string | Human-readable message |
refund_reference | string | The refund reference you queried |
refund_status | string | Refund status (PENDING, PROCESSING, COMPLETED, FAILED, CANCELLED) |
original_transaction_reference | string | The original transaction reference from the charge |
refund_amount | number | Amount refunded |
Error Responses
400 Bad Request
{
"error": "reference is required"
}502 Bad Gateway
{
"error": "failed to check refund status"
}Refund History
Retrieve a paginated list of refund records with optional date filtering.
Endpoint
GET /api/v1/client/payment/refund/history
Authentication
This endpoint requires HMAC authentication headers:
x-api-key: <your-api-key>
x-timestamp: <rfc3339-timestamp>
x-signature: <hmac-sha256-signature>Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
start_at | integer | No | Pagination offset (defaults to 1, must be a positive integer) |
start_date | string | No | Filter start date (YYYY-MM-DD) |
end_date | string | No | Filter end date (YYYY-MM-DD) |
Example Request
curl -X GET "https://api.transfaar.com/api/v1/client/payment/refund/history?start_at=1&start_date=2026-01-01&end_date=2026-03-04" \
-H "x-api-key: your-api-key" \
-H "x-timestamp: 2026-03-04T10:30:00Z" \
-H "x-signature: your-hmac-signature"Success Response (200 OK)
{
"message": "refund history retrieved",
"refunds": [
{
"refund_reference": "RF20260312-YK8ATTL92B0JUSD",
"refund_status": "COMPLETED",
"original_transaction_reference": "BE27E31B45508365",
"refund_amount": 17.78
},
{
"refund_reference": "RF20260310-AB3CDEF45G6H",
"refund_status": "PENDING",
"original_transaction_reference": "9F4A2B7C83DD1E02",
"refund_amount": 2000
}
],
"total": 2,
"page": 0,
"size": 10
}Response Fields
| Field | Type | Description |
|---|---|---|
message | string | Human-readable message |
refunds | array | List of refund records |
refunds[].refund_reference | string | Refund reference |
refunds[].refund_status | string | Refund status (PENDING, PROCESSING, COMPLETED, FAILED, CANCELLED) |
refunds[].original_transaction_reference | string | The original transaction reference from the charge |
refunds[].refund_amount | number | Amount refunded |
total | integer | Total number of refund records |
page | integer | Current page number |
size | integer | Page size |
Error Responses
400 Bad Request
{
"error": "start_at must be a positive integer"
}502 Bad Gateway
{
"error": "failed to fetch refund history"
}Best Practices
1. Store Transaction References
Always store the transactionRef returned from the initialize endpoint. This allows you to:
- Track payment status
- Reconcile payments with your orders
- Handle webhook notifications
- Look up payment details later
2. Set Appropriate Redirect URLs
Use your redirectUrl to:
- Show payment success/failure pages
- Update order status in your system
- Send confirmation emails to customers
- Provide a seamless return experience for customers
3. Handle Webhooks
Don't rely solely on redirect URLs for payment confirmation. Always verify payment status via webhooks, as customers may close their browser before redirect.
4. Validate Amounts
Ensure the amount matches what the customer expects and verify it in your system before initialization.
5. Error Handling
Handle initialization errors gracefully:
- Invalid amounts (must be greater than zero)
- Invalid currency codes
- Missing required fields
- Authentication failures
Test Card Details (Sandbox)
Use the following cards in test/sandbox environments only.
| Card Type | Card Number | 3D Secure (3DS) | Expiry Date | CVV |
|---|---|---|---|---|
| Visa | 4508750015741019 | true | 01/39 | 100 |
| Mastercard | 5123450000000008 | true | 01/39 | 100 |
| Mastercard | 5111111111111118 | false | 01/39 | 100 |
Simulated Expiry Date Responses
The expiry date used in test transactions determines the system response:
| Expiry Date | Response |
|---|---|
01/39 | APPROVED |
05/39 | DECLINED |
04/27 | EXPIRED_CARD |
08/28 | TIMED_OUT |
01/37 | ACQUIRER_SYSTEM_ERROR |
02/37 | UNSPECIFIED_FAILURE |
05/37 | UNKNOWN |
These test scenarios help simulate different transaction outcomes so merchants can validate their integration.
Status Response Note: Client-facing status values are normalized to
SUCCESS,FAILED,PENDING, orPROCESSING. Additional provider/context details can be returned in themessagefield.
Example: Complete Integration
Here's a complete example of integrating card payments:
async function processCardPayment(orderData) {
try {
// Step 1: Initialize payment
const initResponse = await initializePayment({
email: orderData.customerEmail,
first_name: orderData.customerFirstName,
last_name: orderData.customerLastName,
amount: orderData.amount.toFixed(2),
currency: orderData.currency,
reference: orderData.orderId,
redirectUrl: `https://your-website.com/orders/${orderData.orderId}/payment-complete`,
description: `Payment for order #${orderData.orderId}`
});
if (initResponse.success) {
// Step 2: Store transaction references
await saveTransactionReference(orderData.orderId, initResponse.data.transactionRef);
await saveAccessCode(orderData.orderId, initResponse.data.access_code);
} else {
throw new Error(initResponse.error || 'Failed to initialize payment');
}
} catch (error) {
console.error('Payment initialization failed:', error);
showErrorMessage('Failed to start payment. Please try again.');
}
}
async function initializePayment(paymentData) {
const timestamp = new Date().toISOString();
const signature = generateHMACSignature(JSON.stringify(paymentData), timestamp);
const response = await fetch('https://api.transfaar.com/api/v1/client/checkout/initialize', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': YOUR_API_KEY,
'x-timestamp': timestamp,
'x-signature': signature
},
body: JSON.stringify(paymentData)
});
return await response.json();
}Security Considerations
- Never store raw card data: Ensure your integration is PCI-compliant and tokenized/encrypted where required
- Use HTTPS: Always use HTTPS for all API calls
- Verify webhooks: Always verify webhook signatures before processing
- Protect API keys: Keep your API keys secure and never expose them in client-side code
- Validate amounts: Always validate payment amounts on your server before initializing
Supported Currencies
Card payments are currently supported for:
- NGN (Nigerian Naira)
- USD (US Dollar)
Additional currencies may be added in the future.
Support
For questions or issues with card payments, contact our support team.