Appearance
Voucher Issuance
Use this endpoint to issue a voucher for a recipient.
Flow
Endpoint
POST /vouchers/issue
Headers
| Header | Required | Description |
|---|---|---|
X-API-Key | Yes | Partner API key. |
X-Timestamp | Yes | ISO timestamp used in signature verification. |
X-Signature | Yes | Base64 Ed25519 signature for the request. |
Idempotency-Key | Yes | Unique retry-safe operation key. |
User-Agent | No | Optional client identifier. |
Request Body
| Field | Type | Required | Rules |
|---|---|---|---|
denominationId | number | Yes | Minimum 1. |
merchantId | number | Yes | Minimum 1. |
recipientPhone | string | Yes | Max 32 chars. |
recipientName | string | No | Max 255 chars; nullable. |
isRestricted | boolean | Yes | Restricts redemption to the originating merchant when true. |
originatingCountry | string | Yes | Sender country (code or name), max 255 chars. Example: US. |
foreignCurrencyAmount | number | Yes | Sending amount in USD, must be greater than 0. |
exchangeRate | number | Yes | USD to ETB exchange rate, must be greater than 0. |
Voucher Code Format
Partner issuance returns two identifiers:
| Field | Format | Purpose |
|---|---|---|
voucherCode | Exactly 16 decimal digits (0–9), no separators | Bearer credential the recipient uses for merchant redemption. Generated with cryptographically secure randomness (~53 bits of entropy). |
serialNumber | VCH-YYYYMMDD- plus 16 uppercase hex characters | Platform audit/support reference. Not a redemption code. |
Rules for voucherCode:
- Always 16 characters, numeric only, stored and returned without dashes or spaces.
- Partners may display the code to recipients grouped for readability (for example
9876-5432-1098-7654), but the API value is the plain 16-digit string. - Merchant redemption accepts the plain 16-digit code; hyphen separators in user input are stripped before validation.
Example Request
bash
curl -X POST "$API_BASE_URL/vouchers/issue" \
-H "Content-Type: application/json" \
-H "X-API-Key: $PARTNER_API_KEY" \
-H "X-Timestamp: 2026-04-29T12:00:00.000Z" \
-H "X-Signature: $PARTNER_SIGNATURE" \
-H "Idempotency-Key: a3f0f55a-80f4-44d1-93dd-61035d4e6b72" \
-d '{
"denominationId": 4,
"merchantId": 12,
"recipientPhone": "+251911234567",
"recipientName": "Abebe Kebede",
"isRestricted": true,
"originatingCountry": "US",
"foreignCurrencyAmount": 8.85,
"exchangeRate": 56.5
}'json
{
"denominationId": 4,
"merchantId": 12,
"recipientPhone": "+251911234567",
"recipientName": "Abebe Kebede",
"isRestricted": true,
"originatingCountry": "US",
"foreignCurrencyAmount": 8.85,
"exchangeRate": 56.5
}Example Response
json
{
"voucherCode": "9876543210987654",
"denominationAmountEtb": 500,
"expirationDate": "2026-07-27T23:59:59.000Z",
"serialNumber": "VCH-20260427-A1B2C3D4E5F67890",
"merchantName": "Abyssinia Market",
"isRestricted": true
}Response Codes
| Code | Meaning |
|---|---|
200 | Voucher issuance request processed. |
400 | Invalid request or missing idempotency key. |
401 | Missing or invalid API key, timestamp, or signature. |
403 | Access is forbidden. |
404 | Referenced resource not found (for example merchant or denomination). |
409 | Idempotency conflict or insufficient partner wallet balance. |
422 | Business-rule rejection, such as partner limit checks. |
500 | Unexpected processing error. |
Integration Notes
- Store both
voucherCodeandserialNumber. UsevoucherCodefor redemption andserialNumberfor support/audit workflows. - Reuse the same
Idempotency-Keyonly for retries of the same request payload. - Treat
voucherCodeas a secret bearer credential and avoid exposing it in logs.