1. Overview
AWDPay Checkout API V2 allows a merchant to initiate a payment from their platform, redirect the customer to AWDPay for OTP/payment confirmation, and receive payment status updates.
/api/v2/checkout/....
Older routes using /api/checkout/v2/... may remain available for existing integrations.
2. Base URL
https://www.awdpay.com
3. Authentication
All protected requests must include the merchant private key in the Authorization header.
Authorization: Bearer YOUR_PRIVATE_KEY
Content-Type: application/json
4. Initiate Checkout
Create a checkout transaction and receive a hosted payment URL.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
amount | number | Yes | Payment amount. |
currency | string | Yes | Currency code, for example XOF, USD, EUR. |
customIdentifier | string | Yes | Your internal order/payment reference. |
callbackUrl | string | Recommended | Webhook URL to receive payment updates. |
successUrl | string | Yes | Customer redirect URL after successful payment. |
failedUrl | string | Yes | Customer redirect URL if payment fails or is cancelled. |
logo | string | No | Merchant logo URL displayed on checkout page. |
test | boolean | No | Use true for test mode and false for production. |
cURL example
curl -X POST https://www.awdpay.com/api/v2/checkout/initiate \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_PRIVATE_KEY" \
-d '{
"amount": 1000,
"currency": "XOF",
"customIdentifier": "ORDER-2026-0001",
"callbackUrl": "https://merchant.com/api/awdpay/v2/callback",
"successUrl": "https://merchant.com/payment/success",
"failedUrl": "https://merchant.com/payment/failed",
"logo": "https://merchant.com/logo.png",
"test": false
}'
Success response
{
"success": true,
"message": "Checkout initiated successfully",
"trxId": "TRX_ID",
"redirectUrl": "https://www.awdpay.com/checkout/..."
}
5. Send Customer OTP
Send or validate the customer OTP step depending on the checkout flow.
Example
curl -X POST https://www.awdpay.com/api/v2/checkout/customer/otp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_PRIVATE_KEY" \
-d '{
"trxId": "TRX_ID",
"otp": "123456"
}'
6. Confirm Customer Payment
Confirm the payment after the OTP or customer authorization step.
Example
curl -X POST https://www.awdpay.com/api/v2/checkout/customer/pay \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_PRIVATE_KEY" \
-d '{
"trxId": "TRX_ID",
"otp": "123456"
}'
success status should be considered as confirmed payment.
7. Verify Payment
Verify a payment by transaction ID or merchant custom identifier.
Examples
curl -X GET "https://www.awdpay.com/api/v2/checkout/verify?trxId=TRX_ID" \
-H "Authorization: Bearer YOUR_PRIVATE_KEY"
curl -X GET "https://www.awdpay.com/api/v2/checkout/verify?customIdentifier=ORDER-2026-0001" \
-H "Authorization: Bearer YOUR_PRIVATE_KEY"
Response example
{
"success": true,
"trxId": "TRX_ID",
"status": "success",
"amount": 1000,
"currency": "XOF",
"customIdentifier": "ORDER-2026-0001",
"paidBy": "customer@example.com",
"test": false,
"updatedAt": "2026-05-09T10:00:00.000Z"
}
8. Find Pending Payment
Find a checkout payment if the merchant needs to recover a pending transaction.
Example
curl -X GET "https://www.awdpay.com/api/v2/checkout/find?trxId=TRX_ID" \
-H "Authorization: Bearer YOUR_PRIVATE_KEY"
9. Merchant Callback
AWDPay sends an HTTP POST callback to the merchant’s callbackUrl
when the payment status changes.
Callback payload example
{
"event": "payment.success",
"status": "success",
"trxId": "TRX_ID",
"amount": 1000,
"currency": "XOF",
"customIdentifier": "ORDER-2026-0001",
"paidBy": "customer@example.com",
"timestamp": "2026-05-09T10:00:00.000Z"
}
Callback headers
Content-Type: application/json
X-AWDPAY-Event: payment.success
X-AWDPAY-Timestamp: TIMESTAMP
X-AWDPAY-Signature: sha256=SIGNATURE
HTTP 200 OK after successful processing.
10. Verify Callback Signature
Use the raw body and your webhook secret to verify X-AWDPAY-Signature.
import crypto from "crypto";
function verifyAwdpaySignature(rawBody, signatureHeader, webhookSecret) {
const expected =
"sha256=" +
crypto.createHmac("sha256", webhookSecret)
.update(rawBody)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signatureHeader)
);
}
11. Payment Statuses
| Status | Description |
|---|---|
pending | Payment initiated but not completed. |
success | Payment completed successfully. |
failed | Payment failed or was cancelled. |
12. Best Practices
- Do not expose your private key in frontend code.
- Create checkout requests from your backend only.
- Store
trxIdandcustomIdentifierwith your order. - Do not mark an order as paid only because the customer reaches
successUrl. - Always verify the final status using callback or
/api/v2/checkout/verify. - Only
successis a final successful payment. - Always verify
X-AWDPAY-Signaturebefore confirming an order.
Forfaits prépayés et Formules d’abonnement
AWDPay Checkout API V2 supporte maintenant trois types d’intégration :
payment, prepaid et subscription.
Cette évolution permet aux marchands de vendre des paiements simples, des forfaits prépayés
et des formules d’abonnement avec un seul endpoint.
POST https://www.awdpay.com/checkout/v2/initiate
Types disponibles
| Type | Description | Webhook succès |
|---|---|---|
payment |
Paiement simple et ponctuel. | payment.success |
prepaid |
Forfait payé une fois avec validité, unités ou accès. | prepaid.payment.success |
subscription |
Formule d’abonnement liée à un plan. | subscription.activated |
Exemple — Paiement simple
curl -X POST https://www.awdpay.com/checkout/v2/initiate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "payment",
"amount": 5000,
"currency": "XOF",
"country": "CI",
"customIdentifier": "ORDER-2026-0001",
"paymentName": "Commande Boutique",
"callbackUrl": "https://merchant.com/api/awdpay/callback",
"successUrl": "https://merchant.com/payment/success",
"failedUrl": "https://merchant.com/payment/failed",
"logo": "https://merchant.com/logo.png"
}'
Exemple — Forfait prépayé
curl -X POST https://www.awdpay.com/checkout/v2/initiate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "prepaid",
"amount": 10000,
"currency": "XOF",
"country": "CI",
"customIdentifier": "PACK-2026-0001",
"paymentName": "Forfait SMS",
"customer": {
"name": "Client Test",
"email": "client@example.com",
"phone": "+2250700000000",
"external_id": "CUSTOMER-001"
},
"prepaid": {
"plan_id": "PACK_SMS_5000",
"name": "Pack SMS 5000",
"validity_days": 30,
"units": 5000,
"unit_type": "sms"
},
"metadata": {
"order_id": "ORDER-2026-0001",
"service": "sms_pack"
},
"callbackUrl": "https://merchant.com/api/awdpay/callback",
"successUrl": "https://merchant.com/payment/success",
"failedUrl": "https://merchant.com/payment/failed",
"logo": "https://merchant.com/logo.png"
}'
Exemple — Formule d’abonnement
curl -X POST https://www.awdpay.com/checkout/v2/initiate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "subscription",
"amount": 15000,
"currency": "XOF",
"country": "CI",
"customIdentifier": "SUB-ORDER-2026-0001",
"paymentName": "Premium Mensuel",
"customer": {
"name": "Client Abonnement",
"email": "client@example.com",
"phone": "+2250500000000",
"external_id": "CUSTOMER-SUB-001"
},
"subscription": {
"plan_id": "PREMIUM_MONTHLY",
"name": "Premium Mensuel",
"interval": "monthly",
"interval_count": 1,
"auto_renew": true,
"renewal_mode": "wallet_auto_debit",
"grace_period_days": 3
},
"metadata": {
"merchant_user_id": "USER-001",
"package": "premium"
},
"callbackUrl": "https://merchant.com/api/awdpay/callback",
"successUrl": "https://merchant.com/subscription/success",
"failedUrl": "https://merchant.com/subscription/failed",
"logo": "https://merchant.com/logo.png"
}'
Réponse checkout
{
"success": true,
"message": "Generated Checkout Link",
"trxId": "NOQTFCL3U7V9",
"type": "subscription",
"planId": "PREMIUM_MONTHLY",
"subscriptionId": "SUB-NOQTFCL3U7V9",
"redirectUrl": "https://www.awdpay.com/checkoutv2?trxId=NOQTFCL3U7V9"
}
Headers webhook
X-AWD-Event: subscription.activated
X-AWD-Timestamp: 1778426580
Content-Type: application/json
Webhook — Forfait prépayé payé
{
"event": "prepaid.payment.success",
"status": "success",
"trxId": "R1Q4SWHHVHV4",
"type": "prepaid",
"amount": 10000,
"currency": "XOF",
"customIdentifier": "PACK-2026-0001",
"planId": "PACK_SMS_5000",
"subscriptionId": null,
"country": "CI",
"paymentName": "Forfait SMS",
"paidBy": "client@example.com",
"customer": {
"name": "Client Test",
"email": "client@example.com",
"phone": "+2250700000000",
"external_id": "CUSTOMER-001"
},
"prepaid": {
"plan_id": "PACK_SMS_5000",
"name": "Pack SMS 5000",
"validity_days": 30,
"units": 5000,
"unit_type": "sms"
},
"subscription": null,
"metadata": {
"order_id": "ORDER-2026-0001",
"service": "sms_pack"
},
"timestamp": "2026-05-10T15:23:00.000Z"
}
Webhook — Abonnement activé
{
"event": "subscription.activated",
"status": "success",
"trxId": "NOQTFCL3U7V9",
"type": "subscription",
"amount": 15000,
"currency": "XOF",
"customIdentifier": "SUB-ORDER-2026-0001",
"planId": "PREMIUM_MONTHLY",
"subscriptionId": "SUB-NOQTFCL3U7V9",
"country": "CI",
"paymentName": "Premium Mensuel",
"paidBy": "client@example.com",
"customer": {
"name": "Client Abonnement",
"email": "client@example.com",
"phone": "+2250500000000",
"external_id": "CUSTOMER-SUB-001"
},
"prepaid": null,
"subscription": {
"plan_id": "PREMIUM_MONTHLY",
"name": "Premium Mensuel",
"interval": "monthly",
"interval_count": 1,
"auto_renew": true,
"renewal_mode": "wallet_auto_debit",
"grace_period_days": 3
},
"metadata": {
"merchant_user_id": "USER-001",
"package": "premium"
},
"timestamp": "2026-05-10T15:23:00.000Z"
}
Codes d’erreur
{
"success": false,
"code": "INVALID_PAYMENT_TYPE",
"message": "Invalid payment type. Allowed values: payment, prepaid, subscription."
}
{
"success": false,
"code": "SUBSCRIPTION_INTERVAL_REQUIRED",
"message": "subscription.interval is required."
}
Renouvellement automatique des abonnements
Lorsqu’une transaction de type subscription est payée avec succès,
AWDPay crée un abonnement actif. Le système peut ensuite renouveler automatiquement
l’abonnement selon son intervalle, créer une facture de renouvellement et envoyer un webhook au marchand.
Cycle de vie d’un abonnement
| Statut | Description | Action AWDPay |
|---|---|---|
active |
L’abonnement est actif et peut être renouvelé automatiquement. | AWDPay surveille nextBillingAt. |
past_due |
Le renouvellement a échoué, par exemple solde client insuffisant. | AWDPay envoie subscription.payment.failed. |
cancelled |
L’abonnement est désactivé ou annulé. | Aucun renouvellement automatique n’est exécuté. |
Champs importants
{
"subscriptionId": "SUB-HC8HBMYWJJZN",
"subscriptionStatus": "active",
"currentPeriodStart": "2026-05-10T16:38:02.000Z",
"currentPeriodEnd": "2026-06-10T16:38:02.000Z",
"nextBillingAt": "2026-06-10T16:38:02.000Z",
"lastBillingAt": "2026-05-10T16:46:08.000Z"
}
Webhook — Abonnement renouvelé
{
"event": "subscription.renewed",
"status": "success",
"trxId": "RNWVYQQTISKG138",
"type": "subscription",
"amount": 15000,
"currency": "XOF",
"customIdentifier": "RENEWAL-SUB-HC8HBMYWJJZN-1778426768",
"transactionNumber": "subscription-renewal-rnwvyqqtiskg138",
"planId": "PREMIUM_MONTHLY",
"subscriptionId": "SUB-HC8HBMYWJJZN",
"invoiceId": "INV-RNWVYQQTISKG138",
"billingReason": "renewal",
"subscriptionStatus": "active",
"currentPeriodStart": "2026-05-10T16:38:02.000Z",
"currentPeriodEnd": "2026-06-10T16:38:02.000Z",
"nextBillingAt": "2026-06-10T16:38:02.000Z",
"paidBy": "client@example.com",
"customer": {
"name": "Client Abonnement",
"email": "client@example.com",
"phone": "+2250500000000",
"external_id": "CUSTOMER-SUB-001"
},
"subscription": {
"plan_id": "PREMIUM_MONTHLY",
"name": "Premium Mensuel",
"interval": "monthly",
"interval_count": 1,
"auto_renew": true,
"renewal_mode": "wallet_auto_debit",
"subscription_status": "active"
},
"metadata": {},
"timestamp": "2026-05-10T16:46:08.000Z"
}
Webhook — Échec de renouvellement
{
"event": "subscription.payment.failed",
"status": "failed",
"trxId": null,
"type": "subscription",
"amount": 15000,
"currency": "XOF",
"planId": "PREMIUM_MONTHLY",
"subscriptionId": "SUB-HC8HBMYWJJZN",
"invoiceId": "INV-FAILED-SUB-HC8HBMYWJJZN-1778426768",
"billingReason": "renewal",
"subscriptionStatus": "past_due",
"currentPeriodStart": "2026-05-10T16:38:02.000Z",
"currentPeriodEnd": "2026-06-10T16:38:02.000Z",
"nextBillingAt": "2026-06-10T16:38:02.000Z",
"paidBy": "client@example.com",
"customer": {
"name": "Client Abonnement",
"email": "client@example.com"
},
"subscription": {
"plan_id": "PREMIUM_MONTHLY",
"interval": "monthly",
"auto_renew": true
},
"metadata": {},
"timestamp": "2026-05-10T16:46:08.000Z"
}
Headers webhook
X-AWD-Event: subscription.renewed
X-AWD-Timestamp: 1778426768
Content-Type: application/json
past_due et le marchand reçoit
subscription.payment.failed.