Skip to main content
This walks you from credentials to a settled charge. Budget about fifteen minutes.

Before you start

You need a credential set from AptaPay: app_id, key_id, api_key and signing_secret. You will be issued a test set and a live set — start with test.
Test mode is not a sandbox. Eversend has no sandbox, so test mode is a real provider account with a low-balance wallet and a low amount ceiling. Small real amounts move. See Modes.
1

Store your credentials

Put them in your secret manager, not in source control.
.env
The signing secret and the outbound secret are different values. The first signs your requests to us; the second verifies our webhooks to you.
2

Add the signing helper

Every request carries four headers, with an HMAC-SHA256 over a ten-field canonical string. Copy the reference implementation from Authentication — it needs nothing but Node’s built-in crypto.There is no login call and no token endpoint. You sign per request.
3

Confirm auth works

Call a cheap read first, so a failure here is unambiguously about signing and not about money.
check-auth.ts
A 200 means your signing is correct. A 401 means it is not — work through 401 triage, starting with your clock.
4

Check the corridor you need

A corridor is country + currency + method. Confirm yours is supported and learn its limits rather than hardcoding them.
See Capabilities and corridors.
5

Charge a customer

Amounts are integer minor units. UGX, RWF, XAF and XOF are zero-decimal, so 500000 UGX is five hundred thousand shillings.
charge.ts
You get 201 with a gateway reference and, almost always, status pending. The customer sees their provider’s own prompt — a mobile money PIN request, a redirect, or an OTP.
6

Wait for the real answer

A charge does not settle synchronously. Treat the webhook as the outcome, or poll if you must:
Do not treat pending as failure and do not retry it with a new idempotency key.
7

Receive and verify the webhook

Register your callback_url_test, then verify every delivery before trusting it — see Webhooks for the verifier.Correlate on data.metadata, which echoes what you sent at charge time. Do not parse our reference; it carries none of your structure.

What to get right before going live

Every error carries exactly one of terminal, retriable or ambiguous. An ambiguous outcome must never be reversed — poll it to a terminal status instead. See Errors.
Never mint a new key to get past a failure. Same operation, same key — that is what stops one charge becoming two. See Idempotency.
Check observed_amount_minor and observed_currency against what you expected, not just status.
Delivery is at-least-once and unordered. Track processed event_ids and use sequence to discard stale arrivals.

Next

Collections

Money in, end to end.

Payouts

Money out, and the float model.

Authentication

The signing scheme in full.

API reference

Every endpoint.