Payments
Create a payment
POST /v1/payments
Sends an Orange Money payment request to the customer's phone. The customer confirms it with their PIN; you learn the outcome through a webhook.
Headers
Authorization: Bearer sk_(test|live)_…Idempotency-Key: <uuid>(recommended — see Idempotency)Content-Type: application/json
Body
{
"merchant_ref": "ORDER-001",
"amount": "150.00",
"currency": "SLE",
"provider": "orange_money_sl",
"payer": {
"phone": "+23276123456",
"email": "customer@example.com",
"name": "Aminata Kamara",
"country": "SL"
},
"description": "Order #001",
"success_url": "https://shop.example.com/success",
"failed_url": "https://shop.example.com/cancel",
"callback_url": "https://shop.example.com/webhooks/soamtar",
"metadata": { "cart_id": "abc-123" }
}| Field | Type | Required | Notes |
|---|---|---|---|
merchant_ref | string, max 255 | yes | Unique per merchant. Acts as business idempotency. |
amount | decimal | yes | Amount in leones, at most two decimals (e.g. 150.00). Minimum 1. A more precise amount is rejected, never rounded. |
currency | enum | optional | SLE (default), USD or EUR. |
provider | string | optional | orange_money_sl. If omitted → hosted checkout. |
phone / payer.phone | string | optional | Customer's Orange Money number, E.164 (+232 + 8 digits). Needed to push the request to the phone; otherwise use the hosted checkout. |
payer.email, payer.name, payer.country | optional | If a phone is given, a customer profile is created or updated. | |
success_url / failed_url | url | optional | Return URLs (public HTTPS). return_url / cancel_url are accepted as aliases. Defaults: URLs configured on your account. |
callback_url | url | optional | Public HTTPS URL that receives every event of this transaction (same payload, same X-Soamtar-Signature, same retries as your endpoints), in addition to your registered endpoints. Signed with the secret of your oldest active endpoint of the same environment: register at least one endpoint, otherwise the callback is skipped. See Webhooks. |
metadata | object | optional | Returned as is in every webhook (50 keys max, scalar values). |
Response 201
{
"data": {
"id": "0e85b3c2-7c4f-4f1d-9b3a-1c8a2d4e5f6a",
"object": "transaction",
"reference": "TXN-1A2B3C4D-ABCDEF123456",
"merchant_ref": "ORDER-001",
"provider_ref": null,
"type": "payment",
"payment_method": "orange_money_sl",
"status": "pending",
"next_action": null,
"amount": "150.00",
"currency": "SLE",
"payer": { "phone": "+23276123456", "name": "Aminata Kamara", ... },
"payment_url": "https://app.so-amtar.com/pay/checkout/0e85b3c2-...",
"is_test": true,
"initiated_at": "2026-10-21T09:40:00+00:00",
"expires_at": "2026-10-21T11:40:00+00:00"
},
"livemode": false
}provider_ref receives the Orange Money transaction id once the payment is confirmed.
Statuses
| Status | Meaning |
|---|---|
initiated | Created on SOAMTAR, not yet sent to Orange Money (hosted checkout) |
pending | Request sent to the customer's phone, waiting for their PIN confirmation |
processing | An action from the payer is still expected |
success | Payment confirmed, funds received |
failed | Refused by Orange Money (insufficient balance, wrong PIN, prompt not confirmed in time…) |
cancelled | Cancelled by the payer |
expired | expires_at passed without a final status (2 hours by default) |
partially_refunded | A successful payment on which part of the amount was refunded |
refunded | Refunds total the full amount of the payment |
Forbidden transitions are rejected to guarantee state integrity. See Payment statuses.
What the customer sees
With Orange Money Sierra Leone there is no OTP or redirect to handle: the customer receives a payment request on their phone (in English), checks the merchant name and the amount in leones, and confirms with their Orange Money PIN. The prompt stays open for about 5 minutes. Show a "Check your phone to confirm the payment" screen and wait for the webhook.
Retrieve a payment
GET /v1/payments/{id_or_reference}
Accepts the UUID id or the reference (TXN-…).
List payments
GET /v1/payments?status=success&provider=orange_money_sl&created_from=2026-10-01&per_page=50
Filters: status, provider, created_from. Sort: created_at DESC.
Force verification (pull from Orange Money)
POST /v1/payments/{id}/verify
For the rare cases where the webhook is lost. Idempotent: no-op on a transaction that is already final.
Refund a payment
A successful payment can be refunded, fully or partially, with POST /v1/refunds. The amount is credited back to the payer's Orange Money number. See Refunds.
Errors
| Code | HTTP | Cause |
|---|---|---|
payment_rejected | 422 | Unsupported currency, too many decimals, merchant limit exceeded, provider unavailable |
gateway_error | 502 | Orange Money refused to start the payment (timeout, format) |
idempotency_conflict | 409 | Same key, different body |
transaction_not_found | 404 | Unknown id or reference for this merchant |