QuataPay
Developer docs

Quickstart

Pick an integration, create a payment, redirect the customer and handle the webhook.

Browse developer docs
Back to developer docs

Build with AI

Copy one prompt, paste it into Claude Code, Codex, Cursor, Windsurf, Copilot or any AI assistant, in any language or framework. It tells the assistant how QuataPay works, asks you what you are building, then writes the payment, the signed webhook and a test. It contains no keys: yourQUATAPAY_API_KEYstays in your own environment.

Or open it as a text file, or install it as a skill or rules file for your tool (see Build with AI).

Take a first test payment, then go live.


Which integration should I use?

You haveUseWhat you do
No server, one product or open amounts (a social page, a WhatsApp shop, a static site)Payment linkCreate the link in the merchant panel under Payment links and share https://quatapay.com/pay/{slug}. No code, no API key.
A server (or a backend you can add), orders with an amount, and you want to know automatically when an order is paidHosted checkout through the API (recommended)Your server calls POST /gateway/payments, redirects the customer to checkout_url, and marks the order paid from a signed webhook. The rest of this page.
The API above, and you want the checkout in a popup instead of a full-page redirectBrowser script (quatapay.js)Your server still creates the payment. The page calls QuataPay.openCheckout({ slug }). Never put an API key in the page.
A Node or Python backend and a live keySDK (optional)Typed helpers for live payments and webhook verification (source in the sdk/ folder of the QuataPay repository). The SDKs only call live paths, so a test key does not work with them: use plain HTTP while testing.
A mobile app (Flutter, Kotlin, Swift, React Native)Your own backend + the APIThe app calls your backend, your backend calls QuataPay, and the app opens the returned checkout_url in the browser. The app never holds a key.

No plugin exists yet for WordPress or WooCommerce: use a payment link, or build a small custom plugin with the steps below.

Building with an AI coding assistant? Use the Copy master prompt button above: it contains everything on this page in a form the assistant can follow.


1 — Register a merchant account

Create a merchant account. Once you are in, open Developer → API keys.


2 — Get your API key

ModePrefixDescription
Testqpay_test_…Test mode, no real money. Uses the /gateway/sandbox/… paths.
Liveqpay_live_…Real XAF. Uses the /gateway/… paths.

The key is shown once, when you create it. Put it in an environment variable (for example QUATAPAY_API_KEY) on your server. Never put it in client-side code, a mobile app, a URL or git. The wrong pairing (a test key on a live path, or the reverse) answers 403.


3 — Create a payment (test mode)

Amounts are integer XAF (5000 means 5,000 francs). XAF has no smaller unit, so never send decimals and never multiply by 100.

curl -X POST https://api.quatapay.com/api/v1/gateway/sandbox/payments \
  -H "Authorization: Bearer $QUATAPAY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "amount": 5000,
    "currency": "XAF",
    "description": "Order #1042",
    "customer_reference": "order_1042",
    "return_url": "https://your-site.example/pay/return?order=order_1042",
    "cancel_url": "https://your-site.example/pay/cancel?order=order_1042"
  }'

Response (201, abridged):

{
  "success": true,
  "data": {
    "payment": {
      "id": "3f2b8c1e-5d7a-4e0b-9a61-2c4d8e7f9a10",
      "slug": "Xb3kP0qLm7Rt2VwY9cZa4Hn1",
      "mode": "test",
      "status": "requested",
      "amount": 5000,
      "currency": "XAF",
      "expires_at": "2026-10-28T10:00:00Z"
    },
    "checkout_url": "https://quatapay.com/checkout/Xb3kP0qLm7Rt2VwY9cZa4Hn1"
  },
  "error": null
}

Save data.payment.id with your order. Send a new Idempotency-Key for each checkout attempt and reuse it only when retrying that same attempt: a retry then returns the original payment instead of creating a second one.


4 — Redirect the customer

Send the customer's browser to data.checkout_url. On the hosted page they pay with MTN Mobile Money (no QuataPay account needed) or from a QuataPay wallet. For Mobile Money the page shows a payer fee on top of your amount (currently 1.3%, set by QuataPay) before they confirm; you do not add it yourself.

When they finish, the browser goes to your return_url (paid), cancel_url (cancelled) or failure_url (failed or expired). QuataPay adds no query parameters, so put your own order id in the URL. The return page only says "we are confirming your payment": anyone can open it, so do not mark the order paid there.


5 — Finish a test payment

A test-mode checkout cannot be paid in a browser. Finish it from your server or terminal with the slug from step 3:

curl -X POST https://api.quatapay.com/api/v1/gateway/sandbox/payments/SLUG/simulate \
  -H "Authorization: Bearer $QUATAPAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "outcome": "succeeded" }'

This sends the same gateway.payment.* webhooks as live, with "simulated": true in data. See Sandbox.


6 — Receive the webhook

In the merchant panel open Developer → Webhooks and add an endpoint (a public https:// URL; use a tunnel such as cloudflared or ngrok while developing). Its signing secret is shown once: store it in an environment variable. QuataPay then POSTs each payment event:

{
  "event": "gateway.payment.succeeded",
  "data": {
    "id": "3f2b8c1e-5d7a-4e0b-9a61-2c4d8e7f9a10",
    "customer_reference": "order_1042",
    "amount": 5000,
    "currency": "XAF",
    "status": "succeeded"
  }
}

Verify every request before you trust it: X-QuataPay-Signature is sha256= plus the hex HMAC-SHA256 of X-QuataPay-Timestamp + "." + raw body, and the timestamp must be within 300 seconds of now. Make the handler idempotent (the same event can arrive twice), then mark the order paid only on gateway.payment.succeeded. Verification code in Node, Python and PHP is on the Webhooks page.


7 — Go live

  1. Create a Live API key and set it only in your production environment. Your code picks the live path from the key prefix.
  2. Register your production webhook URL and put its secret in the production environment.
  3. Make one small real payment and check the order is marked paid exactly once.

Live today: QuataPay wallet and MTN Mobile Money. Orange Money, bank transfer, international cards and payouts to MoMo are coming soon.


Next steps