API Reference
Status Codes
Complete reference for HTTP status codes, payment statuses, and error responses.
| Status | Name | When Used |
|---|
200 OK | Success | GET requests, step submissions |
201 Created | Resource Created | POST requests that create a new deposit or withdrawal |
| Status | Name | Description |
|---|
400 Bad Request | Invalid Request | Missing or invalid parameters. The error field describes what's wrong. |
401 Unauthorized | Authentication Failed | Missing headers, invalid signature, unknown key ID, or stale timestamp (> 5 minutes). |
403 Forbidden | Insufficient Permissions | Valid signature but the API key doesn't have permission for this operation. |
404 Not Found | Resource Not Found | The resource doesn't exist or belongs to a different tenant. Phoenix Pay doesn't distinguish these to prevent information leakage. |
409 Conflict | Duplicate Reference | The reference_id already exists for your tenant. The response includes the existing intent_id. |
422 Unprocessable Entity | Processing Error | The PSP rejected the request. Response includes error code and message. |
429 Too Many Requests | Rate Limited | Wait for the Retry-After header duration before retrying. |
| Status | Name | Description |
|---|
500 Internal Server Error | Server Error | Unexpected error. Response: {"error": "internal_error"}. |
Standard errors:
{
"error": "missing required parameter: channel"
}
Duplicate reference (includes the existing intent for idempotent handling):
{
"error": "duplicate_reference",
"intent_id": "01912e4a-7b3c-7def-8a90-1234567890ab"
}
PSP errors (includes a human-readable message):
{
"error": "insufficient_liquidity",
"message": "PSP does not support this currency in your region"
}
| Error | Cause | Resolution |
|---|
"unauthorized" | Missing X-Key-Id, X-Timestamp, or X-Signature header | Include all three headers |
"unauthorized" | Invalid signature | Verify signing payload format: "{timestamp}.{body}" |
"unauthorized" | Stale timestamp | Ensure X-Timestamp is within 5 minutes of server time |
"unauthorized" | Unrecognized key ID | Use a valid key ID from the admin dashboard |
| Error | Cause |
|---|
"missing required parameter: reference_id" | The reference_id field is missing or empty |
"missing required parameter: amount" | The amount field is missing or empty |
"missing required parameter: currency" | The currency field is missing or empty |
"missing required parameter: channel" | The channel field is missing or empty |
| Error | Cause |
|---|
"attempt_not_awaiting_input" | Tried to submit a step for an attempt that isn't waiting for input |
These are the possible values for the status field on intents (payments):
| Status | Description | Terminal? |
|---|
created | Intent recorded, first attempt may be in progress | No |
pending | At least one attempt active with PSP | No |
completed | Payment successful | Yes |
failed | Payment failed or rejected | Yes |
expired | Payment window expired | Yes |
Terminal means no further status changes are possible. All subsequent update attempts are silently ignored.
These appear in the timeline and represent individual PSP interaction states:
| Status | Description |
|---|
initiated | Attempt created, PSP request in progress |
awaiting_input | Waiting for user input (e.g., OTP) |
pending | PSP accepted, awaiting confirmation |
completed | PSP confirmed success |
failed | PSP reported failure |
expired | Payment window expired |
| Value | Description | API Route |
|---|
deposit | Inbound payment (customer pays you) | /api/deposits |
withdrawal | Outbound payment (you pay a recipient) | /api/payouts |
The API route is /api/payouts but the type field in responses is "withdrawal".
| Value | PSP | Capabilities |
|---|
nowpayments | NOWPayments | Crypto deposits (crypto_address) |
chapa | Chapa | Fiat deposits (checkout, ussd_push, otp) + withdrawals (direct_payout) |
| Channel | Type | PSP | Description |
|---|
crypto_address | Deposit | NOWPayments | Send crypto to generated address |
checkout | Deposit | Chapa | Redirect to hosted checkout page |
ussd_push | Deposit | Chapa | USSD push to mobile phone (Telebirr) |
otp | Deposit | Chapa | Direct charge with OTP verification (Telebirr) |
direct_payout | Withdrawal | Chapa | Bank transfer or mobile money payout |