Payed · Payments API v1

Payed Payments API

Take payments by mobile money (Orange Money, SMEGA) or card with one API. Create a payment, check its status, and get the result on your webhook.

Base URL https://payedchat.com/api/v1 Format JSON Amounts pula (BWP)

Authorisation

Send your API key in the X-API-KEY header on every request. In the code, replace {PAYED_API_KEY} with your key and keep it on your server.

KeyStarts withWhat happens
Stagingpk_test_Payments go to the providers' test systems (Tingg and SMEGA). Pay with their test cards and test mobile money numbers; no real money moves.
Livepk_live_Payments go to the providers' live systems.

A key only reaches its own payments, in its own environment.

Create Payment

POST/payments

One call creates the payment and starts it. Choose the method with method, then send the fields for mobile money or card below.

FieldType
amountnumberRequired. In pula, e.g. 92.00.
currencystringBWP.
descriptionstringRequired. What the customer is paying for, up to 160 characters.
referencestringYour own id for the payment, up to 64 characters. One payment per reference.
metadataobjectAnything you want back with the payment and in webhooks, up to 4,000 characters.
methodstringRequired. orange_money or smega (mobile money), or card.

Mobile Money orange_money smega

The customer gets a payment request on their phone and approves it with their PIN. You learn the result from your webhook or from Payment Status.

FieldType
methodstringorange_money or smega.
phonestringRequired. The customer's mobile money number, e.g. 73251730.

Request

Response 201

{
  "action": {
    "type": "approve_on_phone",
    "message": "Check your phone (73251730): approve the SMEGA payment with your PIN."
  },
  "payment": {
    "reference": "PW1A2B3C4D5E6F",
    "kind": "payment",
    "status": "pending",
    "amount": 92.0,
    "currency": "BWP",
    "description": "Order INV-1001",
    "method": "smega",
    "provider": "smega",
    "channel": "api",
    "orderRef": null,
    "failure": null,
    "createdAt": "2026-10-26T14:20:05Z",
    "paidAt": null,
    "env": "live",
    "merchantReference": "INV-1001",
    "metadata": {
      "customerId": "C-381"
    },
    "fee": null,
    "net": null
  }
}

Card card

Send the customer to action.url, their bank's 3-D Secure page. When they've confirmed, they come back to your return_url with ?payment=…&status=…. Treat the payment as paid only when your webhook or Payment Status says paid.

FieldType
methodstringcard.
namestringRequired. Name on the card.
numberstringRequired. Card number.
month, yearnumberRequired. Expiry, e.g. 12 and 2030.
cvvstringRequired. The 3 or 4 digits on the back.
phonestringRequired. The customer's mobile number.
return_urlstringWhere the customer lands after the bank.

Request

Response 201

{
  "action": {
    "type": "redirect",
    "message": "Confirm the payment with your bank.",
    "url": "https://checkout.tingg.africa/3ds/…"
  },
  "payment": {
    "reference": "PW9C8B7A6F5E4D",
    "kind": "payment",
    "status": "pending",
    "amount": 92.0,
    "currency": "BWP",
    "description": "Order INV-1002",
    "method": "card",
    "provider": "tingg",
    "channel": "api",
    "orderRef": null,
    "failure": null,
    "createdAt": "2026-10-26T14:20:05Z",
    "paidAt": null,
    "env": "live",
    "merchantReference": "INV-1002",
    "metadata": null,
    "fee": null,
    "net": null
  }
}

Payment Status

GET/payments/{REF}

The payment as it stands. While it's pending, each call checks with the provider. Replace {REF} with the payment's reference.

Request

Response 200

{
  "reference": "PW1A2B3C4D5E6F",
  "kind": "payment",
  "status": "paid",
  "amount": 92.0,
  "currency": "BWP",
  "description": "Order INV-1001",
  "method": "smega",
  "provider": "smega",
  "channel": "api",
  "orderRef": null,
  "failure": null,
  "createdAt": "2026-10-26T14:20:05Z",
  "paidAt": "2026-10-26T14:21:40Z",
  "env": "live",
  "merchantReference": "INV-1001",
  "metadata": {
    "customerId": "C-381"
  },
  "fee": 1.38,
  "net": 90.62
}
statusMeaning
pendingWaiting for the customer to approve or finish paying.
paidConfirmed with the provider. fee and net show Payed's fee and what is owed to you.
failedDeclined; failure says why. Create a new payment to try again.
cancelledCancelled before it was paid.

Cancel Payment

POST/payments/{REF}/cancel

Cancels a payment that hasn't been paid. A paid payment is left as it is.

Request

Response 200

{
  "ok": true,
  "payment": {
    "reference": "PW1A2B3C4D5E6F",
    "kind": "payment",
    "status": "cancelled",
    "amount": 92.0,
    "currency": "BWP",
    "description": "Order INV-1001",
    "method": "smega",
    "provider": "smega",
    "channel": "api",
    "orderRef": null,
    "failure": null,
    "createdAt": "2026-10-26T14:20:05Z",
    "paidAt": null,
    "env": "live",
    "merchantReference": "INV-1001",
    "metadata": {
      "customerId": "C-381"
    },
    "fee": null,
    "net": null
  }
}

Webhooks

Payed sends each payment's result to your server as soon as it's known, so you don't have to keep checking.

PUT/webhook

Set the address that receives your webhooks. The response gives your signing secret: keep it with your API key. Send "rotate_secret": true to get a new one, or an empty url to stop webhooks.

Request

Response 200

{
  "url": "https://your-server.example/payed-webhook",
  "secret": "whsec_Dj6O…",
  "events": [
    "payment.paid",
    "payment.failed"
  ]
}

Receive webhooks

Each webhook is a POST to your address with the header X-Payed-Signature: the HMAC-SHA256 of the raw body, keyed with your secret. Check it before trusting the webhook, then answer 200. We retry up to three times if you don't. Replace {PAYED_WEBHOOK_SECRET} with your secret.

Receiver

Transaction details

The body of every webhook:

{
  "event": "payment.paid",
  "payment": {
    "reference": "PW1A2B3C4D5E6F",
    "kind": "payment",
    "status": "paid",
    "amount": 92.0,
    "currency": "BWP",
    "description": "Order INV-1001",
    "method": "smega",
    "provider": "smega",
    "channel": "api",
    "orderRef": null,
    "failure": null,
    "createdAt": "2026-10-26T14:20:05Z",
    "paidAt": "2026-10-26T14:21:40Z",
    "env": "live",
    "merchantReference": "INV-1001",
    "metadata": {
      "customerId": "C-381"
    },
    "fee": 1.38,
    "net": 90.62
  }
}
Field
eventpayment.paid or payment.failed.
payment.referencePayed's id for the payment.
payment.merchantReferenceYour reference from Create Payment.
payment.statuspaid or failed.
payment.amount, currencyWhat the customer paid.
payment.fee, netPayed's fee, and the amount owed to you.
payment.method, providerHow they paid: orange_money, smega or card, and through which provider.
payment.metadataWhat you sent with Create Payment.
payment.failureWhy it failed (failed payments only).
payment.paidAtWhen it was paid (UTC).
payment.envtest (staging key) or live.