Payments
A payment represents a single customer checkout. You create a payment server-side, redirect the customer to checkout_url, and NahuPay handles the method selection, USSD push, or bank redirect.
The payment object
{
"id": "pay_01hx9m2k4bw3zfjq",
"object": "payment",
"amount": 50000,
"currency": "ETB",
"status": "completed",
"method": "telebirr",
"checkout_url": "https://checkout.nahupay.com/pay/ch_abc123",
"success_url": "https://yourstore.com/success",
"cancel_url": "https://yourstore.com/cart",
"metadata": {
"order_id": "ORD-1234"
},
"created_at": "2026-07-10T08:15:00Z",
"expires_at": "2026-07-10T08:45:00Z",
"completed_at": "2026-07-10T08:17:32Z"
}Fields
| Field | Type | Description |
|---|---|---|
id | string | Unique payment identifier. Prefix: pay_ |
object | string | Always "payment" |
amount | integer | Amount in ETB cents. 50000 = 500.00 ETB |
currency | string | Always "ETB" in current API version |
status | string | pending | processing | completed | failed | expired | refunded |
method | string | null | Payment method used. null until the customer selects one |
checkout_url | string | Redirect the customer here. Expires after 30 min |
success_url | string | Where NahuPay redirects after success |
cancel_url | string | Where NahuPay redirects if the customer cancels |
metadata | object | Up to 20 key/value pairs you can attach for your own use |
created_at | ISO 8601 | When the payment was created |
expires_at | ISO 8601 | When the checkout URL expires |
completed_at | ISO 8601 | null | When payment was confirmed |
Create a payment
POST/v1/payments
curl https://api.nahupay.com/v1/payments \
-H "Authorization: Bearer test_sk_abc123" \
-H "Content-Type: application/json" \
-d '{
"amount": 50000,
"currency": "ETB",
"methods": ["telebirr", "bank_transfer"],
"success_url": "https://yourstore.com/success",
"cancel_url": "https://yourstore.com/cart",
"metadata": { "order_id": "ORD-1234" }
}'Request parameters
| Parameter | Required | Type | Description |
|---|---|---|---|
amount | ✓ | integer | Payment amount in ETB cents. Min: 100 (1 ETB). |
currency | ✓ | string | Must be "ETB". |
methods | ✓ | array | Payment methods to offer. At least one required. |
success_url | ✓ | string | HTTPS URL to redirect to after successful payment. |
cancel_url | ✓ | string | HTTPS URL to redirect to if the customer cancels. |
metadata | object | Up to 20 key/value pairs. Values must be strings. | |
idempotency_key | string | Pass a unique string to safely retry failed requests. | |
expires_in | integer | Seconds until the checkout expires. Default: 1800. |
Retrieve a payment
GET/v1/payments/:id
curl https://api.nahupay.com/v1/payments/pay_01hx9m2k4bw3zfjq \
-H "Authorization: Bearer test_sk_abc123"Returns the full payment object. Use this to poll status before going live — in production, rely on webhooks instead.
List payments
GET/v1/payments
curl "https://api.nahupay.com/v1/payments?limit=20&status=completed" \
-H "Authorization: Bearer test_sk_abc123"Query parameters
| Parameter | Default | Description |
|---|---|---|
limit | 10 | Number of results (1–100). |
after | | Cursor from previous page's next_cursor. |
status | | Filter by status: pending | completed | failed | etc. |
method | | Filter by method: telebirr | mpesa | bank_transfer | etc. |
created_gte | | ISO 8601 timestamp — only payments created after this. |
created_lte | | ISO 8601 timestamp — only payments created before this. |
Test scenarios
In sandbox mode, use these test phone numbers to trigger specific outcomes on TeleBirr USSD push:
| Phone number | Outcome |
|---|---|
0911 000 001 | Payment completes immediately |
0911 000 002 | Payment fails — insufficient balance |
0911 000 003 | Payment times out after 30 seconds |
0911 000 004 | User cancels on USSD menu |