Reference
Quick answers for things you'll see across all endpoints.
Response format
Success:
{
"status": "success",
"message": "Gift card created successfully",
"data": { }
}Error:
{
"status": "error",
"message": "Gift card not found. No gift card for this card number and business",
"error": "No gift card for this card number and business"
}The error field may be a string (as above) or an object for validation failures:
{
"status": "error",
"message": "Validation error",
"error": {
"amount": "Amount must be greater than or equal to 1"
}
}Some errors also include a request_id you can share with Chapa support when debugging.
Base URL
https://api.chapa.linkAmounts
- Send amounts in cent —
100means 1 ETB in cents. - Minimum amount is
100which is 1 ETB.
Currencies
You can create gift cards in: ETB, USD, DJF, UGX.
Payments and payouts use the card's currency automatically.
Gift card status
status | Meaning |
|---|---|
1 | Active — can receive payments and payouts |
3 | Disabled by you (via the API) |
| Other values | Disabled or not yet active |
Payment / payout status
When you check status or list history, status is one of:
pending— still processingsuccess— donefailed— did not complete
Live and test mode
Your API key determines the environment. Test keys read and write test data; live keys use production data. The same base URL is used for both.
List endpoints include mode on each item (live or test) so you can tell which environment a record belongs to when building dashboards or exports.
Pagination
GET /card/payments and GET /card/payouts return paginated history for your business.
| Query | Default | Max | Description |
|---|---|---|---|
page | 1 | — | Page number (1-based) |
limit | 15 | 100 | Records per page |
offset | — | — | Optional alternative to page (0-based skip) |
Use page and limit for most integrations. If you send offset in the query string, it is used instead of page.
Response shape:
{
"items": [ ],
"total": 42,
"page": 1,
"limit": 15,
"pages": 3
}Results are ordered newest first.
Service fee
service_fee appears on payment and payout list items and on payment/payout status checks. It is calculated from the transaction amount. Today this is typically 0 unless Chapa configures a fee for your account.
On B2B, bank, and card-to-card payouts you can choose who pays the fee with charge_payer:
| Payout type | Allowed values | Default | Meaning |
|---|---|---|---|
Business (merchant_id) | business, customer | business | business: debit amount, merchant gets less; customer: debit amount + fee, merchant gets full amount |
| Bank | business, customer | business | Same as business payout |
| Card-to-card | sender, receiver | sender | sender: debit amount + fee, destination gets full amount; receiver: debit amount, destination gets less |
When business (B2B/bank) or receiver (card-to-card) pays, the source is debited amount and the destination receives amount - service_fee. When customer (B2B/bank) or sender (card-to-card) pays, the source is debited amount + service_fee and the destination receives the full amount.
References worth saving
| Field | Where you get it | Use it to |
|---|---|---|
card_number | Create gift card | Pay in and pay out |
link_reference | Start a payment | Check payment status |
merchant_reference | You send it (optional) | Match to your own order ID |
chapa_reference | Bank or business payout | Check payout status |
initiator_reference | Card-to-card payout | Check payout status, list history |
List response fields
Payments (GET /card/payments)
| Field | Description |
|---|---|
link_reference | Same as link_reference from POST /card/payments |
merchant_reference | Your order ID, if you sent one |
chapa_reference | Chapa processor reference, when available |
status | pending, success, or failed |
currency | Card currency |
amount | Amount in minor units |
service_fee | Fee charged on the transaction |
payment_method | Wallet slug, e.g. telebirr (direct charge) |
card_number | Gift card that was credited |
mode | live or test |
created_at | ISO 8601 timestamp |
updated_at | ISO 8601 timestamp |
Payouts (GET /card/payouts)
| Field | Description |
|---|---|
payout_type | card_to_card, bank, or b2b |
status | pending, success, or failed |
currency | Card currency |
amount | Amount in minor units |
service_fee | Fee charged on the transaction |
initiator_reference | Card-to-card reference (when payout_type is card_to_card) |
chapa_reference | Bank or B2B reference (when payout_type is bank or b2b) |
source_card_number | Card debited |
destination_card_number | Card credited (card-to-card only) |
merchant_id | Destination merchant (B2B only) |
mode | live or test |
created_at | ISO 8601 timestamp |
updated_at | ISO 8601 timestamp |
If you send merchant_reference on a payment, it must be unique. Sending the same one twice returns an error.
Common errors
| Status | Message | What to do |
|---|---|---|
400 | Validation error | Check required fields and value formats in the request body |
400 | Invalid phone number | Use international format, e.g. +251... |
400 | Insufficient balance | Top up the card before paying out |
400 | Invalid payout request | Send only one destination type per payout |
400 | Invalid charge payer | Use business/customer for B2B and bank, or sender/receiver for card-to-card |
400 | Same card | Use different source and destination cards |
400 | Currency mismatch | Card-to-card payouts require the same currency |
400 | Gift card disabled | Re-enable the card or use an active card |
401 | Unauthorized | Check your API key |
403 | Cannot enable | Only the actor that disabled the card can re-enable it |
404 | Gift card not found | Check the card_number and that it belongs to your account |
404 | User not found | Provide first_name when creating a card for a new phone number |
404 | Payment not found | Check the link_reference and your business scope |
404 | Payout not found | Check the payout reference and your business scope |
409 | Gift card already exists | One card per customer + currency — use the existing card |
409 | Duplicate merchant reference | Use a new merchant_reference |
409 | Already disabled | Card is already in the requested disabled state |
502 | Failed to initiate payout | Upstream payout provider error — retry or contact support |