AAlphaPay

AlphaPay API documentation

Integrate AlphaPay to collect payments and manage withdrawals directly from your product. All requests and responses use JSON over HTTPS.

By default, every collection requires the customer to verify their mobile money number with a one-time SMS code before the real charge is ever sent to their phone. No request of yours reaches the payment gateway directly — see Verify OTP.

Introduction

The AlphaPay API is organized around REST. It uses predictable, resource-oriented URLs, accepts JSON request bodies, returns JSON responses, and uses standard HTTP response codes. Every account gets a test and a live key — build your integration in test mode, then switch to live keys when you're ready to go live.

Base URL: https://api.edibytes.online/api

Authentication

Authenticate requests by including your secret key in the Authorization header. You can find your keys on the Developers page of your dashboard. Never expose your secret key in client-side code.

Authorization: Bearer sk_test_9d3e7c2a1b5f4d8e6c0a2b7f9e1d4c6a

Whitelist a domain

Every payment you initialize must declare which domain it's for, and that domain must already be whitelisted on your account. This means a leaked secret key can't be used to create collections for a website you never approved. Add domains from the Developers page of your dashboard — self-service, no waiting.

POST/domains
curl https://api.edibytes.online/api/domains/ \
  -H "Authorization: Token <your dashboard session token>" \
  -H "Content-Type: application/json" \
  -d '{ "domain": "mystore.com" }'

Once a domain is whitelisted, pass it as domain on every Initialize a payment request. A request for a domain that isn't whitelisted yet is rejected with a 403.

Initialize a payment

Starts a payment for a customer. Returns a checkout_url you redirect the customer to — a fully AlphaPay-branded checkout page, hosted on your own domain, where they enter their mobile money number, verify it with an SMS code, and only then approve the charge. Hold on to the reference — you'll need it to verify the payment once the customer completes it. domain must already be whitelisted on your account. The hosted checkout page handles the OTP step for you automatically — nothing extra to build if you're redirecting here.

POST/payments/initialize
curl https://api.edibytes.online/api/payments/initialize/ \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 50.00,
    "currency": "GHS",
    "reference": "ORDER-1042",
    "domain": "mystore.com"
  }'

amount is the actual amount in GHS (e.g. 50.00 for GH₵50) — not pesewas or any other minor unit.

Response

{
  "id": "pay_9f3a2b1c",
  "status": "pending",
  "amount": "50.00",
  "currency": "GHS",
  "reference": "ORDER-1042",
  "checkout_url": "https://alphapay.edibytes.online/pay/ORDER-1042"
}

Alternative: you already have the customer's number

If your own checkout form already collects the customer's mobile money number, pass it as phone_number in the same initialize call. This still doesn't talk to BluPay directly — it sends a one-time SMS code to that number and hands you back a checkout_url pointing straight at the OTP-entry step, same as the hosted page above. Redirect the customer there; you never build your own OTP form or handle the code yourself. Optionally include callback_url — once the payment actually succeeds, the customer is sent back there, and a signed webhook is POSTed there too (see Webhooks).

curl https://api.edibytes.online/api/payments/initialize/ \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 50.00,
    "currency": "GHS",
    "reference": "ORDER-1042",
    "domain": "mystore.com",
    "phone_number": "0241234567",
    "callback_url": "https://mystore.com/alphapay-callback"
  }'

Response

{
  "id": "pay_9f3a2b1c",
  "reference": "ORDER-1042",
  "amount": "50.00",
  "currency": "GHS",
  "status": "otp_required",
  "message": "Enter the verification code sent to your phone to complete this payment.",
  "checkout_url": "https://alphapay.edibytes.online/pay/ORDER-1042"
}

Redirect to checkout_url and you're done — the page handles code entry, verification, waiting for the customer to approve on their phone, and the callback/webhook once it settles. If a merchant has OTP verification switched off, this call skips straight to dispatching instead and returns { "status": "pending", "message": "Check your phone to approve the payment." } with no checkout_url — nothing left for you to redirect to.

Verify OTP

Confirms the code an Initialize a payment call sent by SMS, and — only on a correct code — dispatches the real charge in the same request. This is the one step that actually reaches BluPay or BulkClix; nothing before it does. No secret key needed — it's scoped by the unguessable reference, so your own checkout form (or the hosted checkout page, which calls this for you automatically) can call it straight from the browser.

POST/payments/:reference/verify-otp
curl https://api.edibytes.online/api/payments/ORDER-1042/verify-otp/ \
  -H "Content-Type: application/json" \
  -d '{ "code": "1234" }'

Response

{
  "status": "pending",
  "message": "Check your phone to approve the payment."
}

A wrong or expired code returns a 400 with an error.message instead — resend by calling initialize again with the same phone number, which sends a fresh code. Once verified, poll or wait and then verify the payment itself to confirm the final result.

Verify a payment

Confirm the final status of a payment before you fulfil an order. Always verify server-side — never trust a redirect or client-side callback on its own.

GET/payments/verify/:reference
curl https://api.edibytes.online/api/payments/verify/ORDER-1042/ \
  -H "Authorization: Bearer sk_test_..."

Response

{
  "id": "pay_9f3a2b1c",
  "status": "success",
  "amount": "50.00",
  "currency": "GHS",
  "reference": "ORDER-1042",
  "paid_at": "2026-08-09T14:22:00Z",
  "channel": "mobile_money"
}

status is one of pending, success, or failed. Only fulfil the order once it reads success.

Withdrawals

Withdrawals move your available balance to a linked mobile money wallet and are sent for real through your dashboard — they're not part of this API. Add a wallet and request a withdrawal from the Withdraw page of your dashboard; your available balance already accounts for AlphaPay's collection fee.

Webhooks

Pass callback_url when you initialize a payment and, the moment it actually succeeds, AlphaPay POSTs the transaction there — per payment, not a fixed dashboard setting. The same payment's customer is also redirected to callback_url in their browser once they see the confirmation on the hosted checkout page, so plan for both a page load and a server-side POST to hit that URL.

Every request is signed with an X-AlphaPay-Signature header — HMAC-SHA256 over the raw request body, keyed with your own secret key. Recompute it the same way and compare before trusting the payload.

{
  "event": "payment.succeeded",
  "data": {
    "id": 9123,
    "reference": "ORDER-1042",
    "amount": "50.00",
    "currency": "GHS",
    "status": "success",
    "customer_phone": "0241234567",
    "paid_at": "2026-08-09T14:22:00Z"
  }
}

Best-effort delivery, no retries yet — always verify the payment server-side before fulfilling an order rather than trusting the webhook (or the redirect) alone.

Errors

AlphaPay uses conventional HTTP response codes: 2xx for success, 4xx for an error caused by the request (a missing parameter, an invalid key), and 5xx for an error on AlphaPay's side.

{
  "error": {
    "type": "invalid_request",
    "message": "amount must be greater than 0"
  }
}