All products
Gateway

One API for every payment rail in Djibouti.

Stop maintaining five SDKs, five sandbox setups, and five reconciliation scripts. MerasPay Gateway gives you one unified interface that orchestrates Waafipay, CAC, SabaPay, D-Money, and East Africa Bank — with a single ledger, a single webhook signature, and a single dashboard.

By the numbers

Live rails
5
API resources
40+
Settled p50 latency
< 1.2s
Webhook retry window
72h

Every Djiboutian rail, abstracted

The gateway ships a provider adapter for every rail that processes money in Djibouti today. Each adapter normalises its native quirks — OTP confirmation, RSA-PSS signing, JWT renewal, address-name binding — into a single set of orchestrator methods.

Waafipay

Djibouti Telecom mobile wallet. Customer pays by entering an OTP into their handset; we surface it through a requires_action → confirm step.

CAC International Bank

Retail and corporate account pull. JWT auth with automatic 401-retry and credentials cached per merchant.

SabaPay (Saba African Bank)

PayMe wallet and fund-transfer rails. Per-merchant address-name / PIN / machine binding handled by the orchestrator.

D-Money

Djibouti Telecom RSA-PSS-signed channel with per-merchant keypair management and sign+verify round-trip on every request.

East Africa Bank

Direct bank pull and push with merchant-level username/password credentials encrypted at rest under HKDF-derived keys.

Mock (sandbox)

A full provider replica used automatically when the merchant is in sandbox mode. Wired to the simulator so you can choose the response.

How a payment flows through the gateway

Four steps, the same shape every time — regardless of which rail you chose.

  1. 1

    Create a PaymentIntent

    POST /v1/payment_intents with the amount, currency, and chosen provider. Gateway looks up the merchant, resolves the adapter, and writes a pending intent.

  2. 2

    Provider initiates

    Adapter calls the rail (Waafipay PreAuthorize, CAC create, SabaPay PayMe, etc.). The merchant receives an intent in requires_action or requires_payment_method.

  3. 3

    Customer confirms

    OTP entry, popup, or in-app confirm. Merchant calls POST /v1/payment_intents/:id/confirm. The orchestrator finalises with the adapter and posts ledger entries.

  4. 4

    Webhook fires

    payment_intent.succeeded fan-outs to every registered endpoint via the webhook-dispatcher worker with HMAC signing and retry.

Built for the rails you actually have

Familiar API shapes mean your team can ship in a day, not a quarter. The grown-up parts — idempotency, versioning, signed webhooks, ledger-first design — come standard rather than as an upsell.

Idempotency, not optional

Every money-moving call requires an Idempotency-Key. Repeats inside 24h return the same response — your retries are free.

Familiar resource model

PaymentIntents, Customers, Refunds, Payouts, Transfers, Disputes — clean, separable resources that map directly to the lifecycle of every payment.

HMAC-signed webhooks

Outbound webhooks are signed HMAC-SHA256 over {timestamp}.{event_id}.{body} with exponential retry and full delivery history.

Per-merchant key vault

Provider credentials are stored AES-256-GCM-encrypted with merchant-specific data keys derived from a hardware-backed master via HKDF.

Built-in ledger

Every payment posts double-entry rows into the ledger before it touches a provider. Settlements reconcile against the ledger, not the provider report.

Versioned API

MerasPay-Version: 2026-MM-DD pinned per API key. We never break old pins — your old integrations keep working forever.

See it in code

A complete C2B PaymentIntent against the Waafipay rail. The Idempotency-Key makes retries safe; the API-version header pins you to a known surface forever.

curl
curl -X POST https://api.meraspay.io/v1/payment_intents \
  -u sk_live_xxx: \
  -H "Idempotency-Key: 9b1d4f0c-7b6f-4e72-a3c2-8aef9d12c0ed" \
  -H "MerasPay-Version: 2026-05-01" \
  -d amount=15000 \
  -d currency=DJF \
  -d "payment_method[provider]=waafi" \
  -d "payment_method[msisdn]=+25377123456" \
  -d description="Order #1024"

# Response
{
  "id": "pi_01HZF8AYJX3D8M7QK0E5V4WJ9K",
  "object": "payment_intent",
  "amount": 15000,
  "currency": "DJF",
  "status": "requires_action",
  "next_action": { "type": "otp_required", "msisdn": "+25377123456" },
  "client_secret": "pi_..._secret_..."
}

Frequently asked

Which rails are live today?

Waafipay, CAC International Bank, SabaPay (Saba African Bank), D-Money (Djibouti Telecom), and East Africa Bank are production-ready. Cybersource card-not-present and SantimPay (Ethiopia outbound) come online as their respective sandbox credentials clear vendor onboarding.

Do I need a separate integration per rail?

No. You set payment_method.provider on the PaymentIntent and we route to the right adapter. Switching rails is a one-line change. The PaymentIntent shape stays identical.

How are settlement files produced?

The reconciler worker runs nightly, pulls each provider settlement report, and matches it against ledger entries. Discrepancies surface in the admin portal as reconciliation_breaks before any money lands on the merchant balance.

What happens if a provider is down?

The orchestrator returns ErrProviderUnavailable to you and emits a provider.unavailable webhook. We do not silently retry to another rail — provider choice is the merchant&apos;s, and silent rerouting hides cost and FX surprises.

Ready to integrate?

Get a sandbox account in minutes. Production goes live after a brief KYB review.