Developers

An API your team will actually enjoy

Predictable REST, idempotency keys, signed webhooks and a sandbox with simulated rails so you can integrate end to end before moving a single franc.

Create account
Built for developers

Your first collection in one request

Clean REST, a predictable JSON envelope and a request id on every response. The sandbox mirrors production: same API, same statuses, same webhooks.

  • Sandbox and production keys, scoped per app
  • HMAC-signed webhooks with replay protection
  • Idempotency keys on every money-moving call
  • Typed errors that tell you exactly what to fix
  • OpenAPI spec, Postman collection and llms.txt, all published
  • Hosted checkout sessions and flat callbacks for CRM, ERP and shop connectors
POST /v1/collections
curl https://api.capayglobal.com/v1/collections \
  -H "Authorization: Bearer sk_test_..." \
  -H "Idempotency-Key: 9f1c-collect-01" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "2500",
    "currency": "XAF",
    "country": "CM",
    "method": "mobile_money",
    "msisdn": "2376XXXXXXXX",
    "merchant_reference": "order-1042"
  }'
201 Created
{
  "status": "success",
  "data": {
    "id": "col_9xKQ2mD41Vb8",
    "object": "collection",
    "status": "pending",
    "amount": "2500",
    "currency": "XAF",
    "country": "CM",
    "method": "mobile_money",
    "merchant_reference": "order-1042",
    "fees": {
      "platform_fee": "50",
      "provider_fee": "0",
      "total_fee": "50",
      "bearer": "merchant"
    },
    "net_amount": null,
    "livemode": false,
    "created_at": "2026-08-30T12:04:11Z"
  },
  "request_id": "req_b0f3d2c1"
}

Your first collection

One request creates a payment intent, returns a request id and, for mobile money, pushes the prompt to the payer's handset. The sandbox behaves exactly like production.

Get your test keysCreate an account and the sandbox keys are on your developer page immediately. Production keys open after business verification.
POST /v1/collections
curl -X POST https://api.capayglobal.com/v1/collections \
  -H "Authorization: Bearer sk_test_XXXXXXXXXXXX" \
  -H "Idempotency-Key: col-order-10482-a1b2c3" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "5000",
    "currency": "XAF",
    "country": "CM",
    "method": "mobile_money",
    "msisdn": "+237650000001",
    "merchant_reference": "order-10482"
  }'
Response
{
  "status": "success",
  "data": {
    "id": "col_7Qm3k1Xa9Zr4",
    "object": "collection",
    "status": "pending",
    "amount": "5000",
    "currency": "XAF",
    "auth_model": "STK_PROMPT",
    "livemode": false
  },
  "request_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}
201 Created
Amounts are decimal strings at the API boundary and minor units in the ledger, so nothing is lost to floating point. Every money-moving call takes an idempotency key and every response carries a request id you can quote to support.

Server SDKs

Thin, typed wrappers over the same REST API, with idempotency and signature verification built in.

TypeScript and NodePublishing soon@capay/sdk
Import
import { Capay } from '@capay/sdk';

Not on npm yet. The import line above is final, so your integration will not change when it is published.

Read the guide
PythonPublishing sooncapay
Import
from capay import Capay

Not on PyPI yet. The import line above is final, so your integration will not change when it is published.

Read the guide
PHPPublishing sooncapay/capay-php
Import
use Capay\CapayClient;

Not on Packagist yet. The import line above is final, so your integration will not change when it is published.

Read the guide

Verify every webhook

Signatures are computed over the raw body and compared in constant time, and a timestamp older than 300 seconds is rejected. Never trust a webhook you have not verified.

X-Capay-Signature
# T is the t= value from X-Capay-Signature; delivery.json is the raw body as received.
T=1767225600
SECRET=whsec_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

{ printf '%s.' "$T"; cat delivery.json; } \
  | openssl dgst -sha256 -hmac "$SECRET" -r | cut -d' ' -f1
# Compare the printed hex with each v1= value in the header (either may match
# during a secret rotation), and reject the delivery if |now - T| > 300 s.
Signature header
X-Capay-Signature: t=1767225600,v1=6f8b4c2d9e0a1b3c5d7e9f0a2b4c6d8e0f1a3b5c7d9e1f0a2b4c6d8e0f1a3b5c
X-Capay-Event-Id: evt_2n4Kq8Zr41Xa
X-Capay-Event-Type: collection.completed
Delivery and retries

A failed delivery is retried on a fixed schedule: 1m, 5m, 30m, 2h, 6h, 12h, 24h, 24h. An endpoint that fails 8 times in a row is disabled and you are told, so a dead endpoint never silently swallows events.

Two signing secrets can be active at once, so you can rotate without dropping an event. Reject anything outside the 300 second window and store the event id to make replays harmless.

The rest of the kit

Machine-readable specs, a collection you can import, and the tools that read them.

llms.txtThe whole documentation set flattened for coding assistants, so your AI answers about our API from our text.OpenAPI specThe full contract, generated from the API. Import it to build a client in any language.Postman collectionEvery endpoint with example bodies and environment variables, ready to run against the sandbox.
Command lineComingCreate test payments, tail events and replay a webhook to your local machine.@capay/cli
MCP serverComingGive your coding assistant read access to your sandbox so it can answer with your real data.@capay/mcp
Checkout scriptComingOpen the hosted checkout in a modal on your own page instead of redirecting.https://pay.capayglobal.com/capay.js

Start collecting payments across Africa today

Create a free account, build against the sandbox and go live after verification.

Create account

Tell us about your corridors and volumes at any time.