Skip to main content
This page lists changes that affect how you integrate. New pages and wording fixes in the documentation are not listed. The current API version is 2026-05-18. See API versioning.
API
Business limits
  • Limit errors. A transaction that would take your business over one of its limits returns 403 with BUSINESS_LIMIT_EXCEEDED, and details.friendlyMessage names the limit and the period. BUSINESS_TRANSACTION_DAILY_LIMIT_EXCEEDED is no longer returned. A transaction below the smallest amount a limit allows returns 400 with BUSINESS_TRANSACTION_MIN_AMOUNT_NOT_MET.
  • Reset times. Usage for daily, weekly, and monthly limits resets at 00:00 UTC: every day, every Monday, and on the 1st of each month. See Business limits.
APIWebhooks
Webhook trigger for checkouts
  • Trigger the checkout webhook with the checkoutId. Trigger webhook accepts the checkoutId that create checkout session returns as the entityId for CHECKOUT_SESSION.CREATED. The checkout must belong to your business, and the webhook is sent with the checkoutId as its sessionId, like the real one. Before, the trigger needed a UUID that only exists once a customer opens the checkout.
API
Error statuses and validation
  • Error statuses that fit the error. Several errors came back as 503, so a client that retries 503 kept retrying a request that could not succeed. They now return the status that fits. A wallet balance that is too low returns 402 with BALANCE_INSUFFICIENT. An unsupported country, currency, channel, or virtual account type, a payment method with no route, and a payment method whose currency does not match return 422. A swap your business has not enabled returns 403. The codes and bodies are unchanged. See Errors.
  • Malformed IDs. A malformed customerId on create payment method, or a malformed batchId on the payment batch endpoints, returns 400. It used to return 500.
  • Payment method for the business owner. Create payment method without a customerId attaches the payment method to the business owner, as documented. It used to return 404 with BUSINESS_CUSTOMER_NOT_FOUND.
  • Status filter. ?status=IN_REVIEW on list transactions now matches the transactions the API reports as IN_REVIEW. Values the API never returns are no longer accepted as status filters.
  • Checkout metadata is kept. The metadata you send when you create a checkout is stored and returned in the CHECKOUT_SESSION.CREATED webhook. It used to be dropped.
  • Rejected up front. These now return a clear client error instead of failing later or returning 500: a payment batch recipient with no amount, a media upload fileName that is empty once cleaned, a date of birth with a month that does not exist, and an SME registration step with no data.
API
Checkout, and requests that were not validated
  • Checkout ID. Create checkout session returns a checkoutId. It is the sessionId in the CHECKOUT_SESSION.CREATED webhook, so you can match the webhook to the checkout you created.
  • References stay held while a checkout is open. You can’t create another checkout with the same merchantReference while an earlier one is still open. It returns 409.
  • A paid checkout closes. Once a checkout’s payment is credited, it can’t be opened again.
  • A wrong document value is rejected. Verify customer returns 400 with INVALID_KYC_DOCUMENT_TYPE when the customer already has that document type on file and your docValue differs. It used to return 200 as if the value had been verified, without comparing it.
  • Malformed transaction IDs. GET /transaction/{transactionId}/advice returns 400 for a malformed ID, like GET /transaction/{transactionId}. It used to return 500.
  • toDate on its own. List transactions accepts toDate without fromDate. It is compared with fromDate only when you send both. It used to be rejected.
  • Stricter limits that were already documented. Create virtual account caps a one-time amount at 5,000,000, and the webhook trigger needs a 24-character hexadecimal entityId (for CHECKOUT_SESSION.CREATED, see October 17). Requests outside those limits are rejected.
API
Checkout channels and failure reasons
  • Checkout channels are decided when the customer opens the page. Create checkout session no longer narrows channels to what the currency supports, so it no longer returns 422 when none of them suit the currency. The response channels is the list you sent, or every channel when you sent none.
  • New failure reason. meta.failureReason.code can now be AFX_RECIPIENT_WALLET_LIMIT_REACHED, when the recipient’s wallet has reached a limit at the destination. See Failure reasons.
API
Pool account
  • Pool account. Get pool account returns 404 with BUSINESS_PAYMENT_METHOD_NOT_FOUND when your business has no pool account in the country you ask for. It used to return 503, so a client that retried 503 kept retrying an answer that never changes.
API
Virtual account errors
  • Virtual account errors. Create virtual account returns 400 with VIRTUAL_ACCOUNT_BVN_REQUIRED when a permanent NGN account needs a BVN and the holder has none. UNSUPPORTED_VIRTUAL_ACCOUNT_CURRENCY and UNSUPPORTED_VIRTUAL_ACCOUNT_TYPE now come back as their own errors instead of 503, and as 422 since October 16.
APIWebhooks
Webhook event IDs, request IDs, and transaction types
  • Webhook event IDs. Every webhook body now carries id, unique to the event, and createdAt, when the event was created, alongside event and data. Retries keep both values, and the signature covers them. Use id to skip duplicate and replayed deliveries. If your handler rejects unknown fields in the body, allow these two. See Duplicates, ordering, and replays.
  • Request IDs. Every API response now carries an x-request-id header. Quote it when you contact support. See Request IDs.
  • Transaction types. POST /transaction accepts only DEPOSIT, WITHDRAW, and SWAP. It rejects any other type.
APIWebhooks
Rate limits and webhook response time
  • Rate limits. POST /transaction is limited to 60 requests per 60 seconds for each business, and customer verification to 100 per 24 hours. Both limits apply in production and in sandbox. Responses from these endpoints carry X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset, and a 429 also carries Retry-After. See Rate limits.
  • Webhook response time. Each webhook delivery attempt now waits up to 15 seconds for your response, down from 30. Return a 2xx quickly and do slow work afterwards. See Webhooks.
API
Per-endpoint API key permissions
  • API key permissions. Every endpoint now checks for a permission on the API key, and POST /transaction checks the permission for the transaction type. Keys created before permissions existed keep access to every endpoint. See Permissions.
API
Fee wallet and Nigerian mobile money
API
Cards are hosted checkout only
  • Cards. The API no longer accepts card payment methods or card deposits. Cards are available only in the hosted checkout.
API
Withdrawal quotes
  • Quote a withdrawal. New endpoint: GET /transaction/quote prices a withdrawal with the same calculation that charges it, so you can show the amounts before you create the transaction.
Sandbox
Sandbox emulator
  • Mobile money and virtual accounts. The sandbox emulator now handles mobile money deposits and virtual accounts. Choose a transaction’s outcome with /simulate, and send an incoming transfer to a virtual account with simulate transfer. See Testing in sandbox.
API
Checkout sessions in production
  • Checkout sessions. Checkout sessions are available in production. Create a session with a production key to take real payments, and with a sandbox key to try the flow in test mode. They were sandbox only before.