Phoenix Pay
Payment Providers

Chapa

Fiat payment processing via Chapa — deposits with multiple channels and withdrawals to bank/mobile money.

Chapa handles fiat payments in Ethiopian Birr (ETB) through Phoenix Pay. It supports multiple deposit channels and outbound withdrawals.

Capabilities

ChannelTypeMethodDescription
checkoutDepositRedirect to Chapa's hosted checkout page
ussd_pushDeposittelebirrUSSD push notification to user's phone
otpDeposittelebirrDirect charge with OTP verification
direct_payoutWithdrawalBank transfer or mobile money payout

Deposits

Checkout (Redirect)

The simplest integration. User is redirected to Chapa's hosted checkout page.

Create checkout deposit
TIMESTAMP=$(date +%s)
BODY='{"reference_id":"order-12345","amount":100000,"currency":"ETB","channel":"checkout"}'

curl -X POST https://pay.phoenixverse.io/api/deposits \
  -H "Content-Type: application/json" \
  -H "X-Key-Id: your-key-id" \
  -H "X-Timestamp: $TIMESTAMP" \
  -H "X-Signature: <signature>" \
  -d "$BODY"
Response
{
  "intent_id": "01912e4b-...",
  "action": "redirect",
  "url": "https://checkout.chapa.co/checkout/payment/abc123xyz"
}

Redirect the user to url. They complete payment on Chapa's page using bank transfer, mobile money, or Telebirr.

USSD Push (Telebirr)

Sends a payment prompt directly to the user's phone. No redirect needed — better mobile UX.

Create USSD push deposit
TIMESTAMP=$(date +%s)
BODY='{"reference_id":"order-12346","amount":100000,"currency":"ETB","channel":"ussd_push","method":"telebirr","fields":{"phone":"+251911234567"}}'

curl -X POST https://pay.phoenixverse.io/api/deposits \
  -H "Content-Type: application/json" \
  -H "X-Key-Id: your-key-id" \
  -H "X-Timestamp: $TIMESTAMP" \
  -H "X-Signature: <signature>" \
  -d "$BODY"
Response
{
  "intent_id": "01912e4c-...",
  "action": "await",
  "message": "Payment request sent"
}
Required FieldDescription
methodMust be "telebirr"
fields.phoneUser's Telebirr phone number (e.g., "+251911234567")

OTP (Telebirr Direct Charge)

Multi-step flow: initial request triggers an OTP, which the user enters to confirm.

Create OTP deposit
TIMESTAMP=$(date +%s)
BODY='{"reference_id":"order-12347","amount":100000,"currency":"ETB","channel":"otp","method":"telebirr","fields":{"phone":"+251911234567"}}'

curl -X POST https://pay.phoenixverse.io/api/deposits \
  -H "Content-Type: application/json" \
  -H "X-Key-Id: your-key-id" \
  -H "X-Timestamp: $TIMESTAMP" \
  -H "X-Signature: <signature>" \
  -d "$BODY"
Response — Step 1: Collect OTP
{
  "intent_id": "01912e4d-...",
  "action": "collect",
  "attempt_id": "01912e4e-...",
  "collect": {
    "type": "otp",
    "hint": "Enter the OTP sent to your phone"
  }
}

Submit the OTP via the step endpoint:

Submit OTP
TIMESTAMP=$(date +%s)
BODY='{"input":{"otp":"123456"}}'

curl -X POST https://pay.phoenixverse.io/api/attempts/01912e4e-.../step \
  -H "Content-Type: application/json" \
  -H "X-Key-Id: your-key-id" \
  -H "X-Timestamp: $TIMESTAMP" \
  -H "X-Signature: <signature>" \
  -d "$BODY"
Response — Step 2: Processing
{
  "intent_id": "01912e4d-...",
  "action": "await",
  "message": "Payment is being processed"
}

Withdrawals

Chapa withdrawals send funds to a recipient's bank account or mobile money number via the direct_payout channel.

Payout to bank account
TIMESTAMP=$(date +%s)
BODY='{"reference_id":"payout-78901","amount":500000,"currency":"ETB","channel":"direct_payout","fields":{"account_number":"1000123456789","account_name":"Abebe Kebede"}}'

curl -X POST https://pay.phoenixverse.io/api/payouts \
  -H "Content-Type: application/json" \
  -H "X-Key-Id: your-key-id" \
  -H "X-Timestamp: $TIMESTAMP" \
  -H "X-Signature: <signature>" \
  -d "$BODY"

Supported banks:

BankCode
Commercial Bank of Ethiopiacbe
Awash Bankawash
Dashen Bankdashen
Bank of Abyssiniaabyssinia
Abay Bankabay
Cooperative Bank of Oromiacoop
Payout to Telebirr
TIMESTAMP=$(date +%s)
BODY='{"reference_id":"payout-78902","amount":250000,"currency":"ETB","channel":"direct_payout","method":"telebirr","fields":{"account_number":"+251911234567","account_name":"Abebe Kebede"}}'

curl -X POST https://pay.phoenixverse.io/api/payouts \
  -H "Content-Type: application/json" \
  -H "X-Key-Id: your-key-id" \
  -H "X-Timestamp: $TIMESTAMP" \
  -H "X-Signature: <signature>" \
  -d "$BODY"

Supported providers:

ProviderCode
Telebirrtelebirr
M-Pesampesa
Amoleamole

Withdrawal Fields

FieldRequiredDescription
fields.account_numberYesBank account number or phone number
fields.account_nameYesAccount holder's name

Configuration

Credentials are entered in the Phoenix Pay admin panel under Payment Providers > Chapa:

FieldRequiredDescription
credentials.secret_keyYesSecret key from the Chapa dashboard under Settings > API
webhook_secretYesWebhook verification secret from Settings > Webhooks. Phoenix Pay stores this separately and uses it to verify Chapa webhooks
credentials.base_urlNoOverride Chapa API base URL if you need a non-default endpoint

All credentials are encrypted at rest using AES-256. They are never exposed through the API — only configurable via the admin panel.

Phoenix Pay generates the Chapa callback URL for your tenant automatically. You do not need to add it manually to the credentials JSON.

Setup Steps

Create a Chapa Account

Sign up at chapa.co and complete business verification.

Generate API Credentials

In the Chapa dashboard:

  1. Go to Settings > API and copy your secret key
  2. Go to Settings > Webhooks and copy the webhook verification secret

Configure in Admin Panel

Enter the secret key and webhook secret in the Phoenix Pay admin panel. Enable the channels you need (checkout, USSD push, OTP, and/or direct payout).

Test with Sandbox

Enable sandbox mode first. Use Chapa's test credentials to verify deposits and payouts before going live.

Sandbox Testing

When sandbox mode is enabled:

  • Use Chapa's test API keys (prefixed with CHAPUBK_TEST-)
  • Deposits complete instantly
  • Payouts simulate success/failure based on test account numbers
  • Sandbox mode is per-tenant and does not affect other tenants