Every endpoint, parameter and response.
Test dataNumbers and cards that succeed, fail or time out.
SupportOpen a ticket, see your open ones.
Quickstart
Four calls take you from nothing to a confirmed MoMo payment. Everything below runs against the sandbox with test numbers, so no money moves.
- Create a sandbox account and copy your API key from the dashboard.
- Initiate a payment with the customer's phone number and amount.
- The customer approves the prompt on their phone (in sandbox, the test number decides the outcome).
- Confirm the status, or let a webhook tell you.
Amounts are in pesewas, so 2500 is GH₵ 25.00. The response returns a payment object with status pending and an id you'll use for everything else.
Authentication
Every request carries a bearer token. Test keys start with sk_test_, live keys with sk_live_. Keys belong to a business, not a person, and can be rotated from the dashboard without downtime: the old key keeps working for 24 hours.
Environments and test data
| Environment | Base URL | Keys | Money |
|---|---|---|---|
| Sandbox | https://sandbox.api.saopayglobal.com/v1 | sk_test_… | None. Outcomes are decided by test numbers. |
| Live | https://api.saopayglobal.com/v1 | sk_live_… | Real. Needs a verified business. |
See Test data for the phone numbers and cards that produce each outcome, including timeouts and insufficient funds.
Mobile money
Sends a payment prompt to the customer's phone. Supported networks: mtn, telecel, airteltigo. If you omit network, Sao detects it from the number prefix.
| Field | Type | Required | Notes |
|---|---|---|---|
| amount | integer | yes | Pesewas. Minimum 100. |
| phone | string | yes | E.164 without the plus, e.g. 233244123456 |
| network | string | no | mtn, telecel, airteltigo |
| reference | string | yes | Your unique id. Repeating it returns the original payment (idempotent). |
| callback_url | string | no | Overrides the webhook endpoint for this payment. |
| metadata | object | no | Up to 20 keys, returned on every event. |
Prompts expire after 90 seconds. Most approvals arrive within 10 seconds; design for the customer walking away, and offer a "resend prompt" button.
Cards
Cards use 3D Secure. You receive an authorization_url to send the customer to, and a webhook when they return. Use the hosted checkout unless you are PCI certified.
Payment links and checkout
Create a link for an amount or an open amount, share it on WhatsApp or SMS, and get paid without writing checkout code. Links can be single-use or reusable, and can collect the payer's name and a note.
Confirming status
Status is one of pending, success, failed, expired. Poll no more than once every 3 seconds, and stop after 2 minutes. Prefer webhooks; polling is a fallback for when your endpoint is down.
Webhooks
Register an HTTPS endpoint and Sao posts events to it: payment.success, payment.failed, refund.completed, payout.completed. Each request carries an X-Sao-Signature header, an HMAC-SHA256 of the raw body with your webhook secret.
Respond with 200 within 5 seconds. Sao retries failed deliveries with backoff for 24 hours, and you can replay any event from the dashboard.
Refunds
Refund all or part of a successful payment. Money goes back the way it came; MoMo refunds land in minutes, card refunds in 3 to 7 days. The Sao fee is returned on full refunds.
Payouts
Send money to a MoMo number or bank account, one at a time or in batches of up to 1,000. Name lookup is free: call GET /v1/lookup/momo?phone=… first and show the registered name before you send.
Go-live checklist
- Business verified in the dashboard (Ghana Card, registration if any, payout account confirmed).
- Webhook endpoint verified and signature checked.
- Handled pending, failed and expired, with a resend option.
- Swapped sk_test_ for sk_live_ and the base URL.
- Made one real GH₵ 1 payment and refunded it.
Errors
| Code | Meaning | What to do |
|---|---|---|
| 400 invalid_phone | Number is not a Ghanaian mobile | Validate before sending |
| 402 insufficient_funds | Customer's wallet is short | Show the message, offer another method |
| 409 duplicate_reference | Reference already used with different data | Use a new reference per attempt |
| 429 rate_limited | Over 50 requests per second | Back off and retry with jitter |
| 503 network_unavailable | The telco is down | Retry later, offer another network |