Merchant API Reference

EriPay Merchant API

Accept wallet, gateway, and hosted checkout payments with environment-aware credentials, merchant-level currency control, and dashboard-managed payment gateway rules.

Production ready
POST /api/v1/initiate-payment
GET /api/v1/verify-payment/{trxId}
Sandbox Multi-currency Signed API Gateway lock
Latest Merchant Flow Gateways are now configured after API generation from the merchant API Config page. Checkout only shows gateways that match the merchant currency and the active receiver wallet.

Fast Hosted Checkout

Create a payment session, redirect the customer, then verify or receive IPN updates when the transaction completes.

Wallet-aware Currency

The requested currency must be enabled for the merchant and backed by an active merchant wallet.

Configurable Gateways

Merchants can choose eligible payment gateways from API Config without regenerating API credentials.

Authentication

EriPay API uses API keys to authenticate requests. You can obtain your credentials from your merchant dashboard.

Environment-Aware API Integration

EriPay API supports both sandbox (testing) and production environments. Always test in sandbox first before going live.

Environment Configuration
Sandbox Mode

Use for: Development, testing, integration

X-Environment: sandbox

Credentials: Use test_* prefixed API keys

Production Mode

Use for: Live payments, real money

X-Environment: production

Credentials: Use production API keys (no prefix)

Gateway Configuration Payment gateway selection is dashboard-managed. After generating API credentials, open Merchant -> Config -> Payment Gateway Controls to choose eligible gateways without changing your integration keys.
Signed requests Every API call must include X-Timestamp and X-Signature unless merchant API signatures are disabled by admin configuration.
Replay protection The timestamp must be fresh. Default tolerance is 300 seconds, configurable by admin.
Rate limit Merchant API calls are rate limited per merchant and IP. Default limit is 120 requests per minute.

Required Credentials

Credential Header Description Location
Merchant ID X-Merchant-Key Your unique merchant identifier Dashboard → Merchant → Config
API Key X-API-Key API authentication key Dashboard → Merchant → Config
Request Timestamp X-Timestamp Unix timestamp in seconds used for replay protection Generated by your server for each API request
API Signature X-Signature HMAC-SHA256 signature for the request Generated using your Client Secret
Client Secret - Used for API request signing and webhook signature verification Dashboard → Merchant → CONFIG
Production API Key X-API-Key Production API key (no prefix) Merchant Dashboard > API Config > Production Mode
Production Merchant Key X-Merchant-Key Production merchant identifier (no prefix) Merchant Dashboard > API Config > Production Mode
Security Notice Never expose your Client Secret in client-side code. Store all credentials securely on your server.
Signature Payload

When API signatures are required, sign this exact payload with your Client Secret:

timestamp.HTTP_METHOD.path_with_query.raw_body

Quick Start

Use this flow for a production-safe integration. Credentials identify the merchant, while currency and gateway availability are controlled from the merchant dashboard.

01

Generate API Keys

Open Dashboard -> Merchant -> Config and copy the Merchant Key, API Key, and Client Secret for sandbox or production.

02

Confirm Currencies

Make sure the merchant supports the checkout currency and the merchant owner has an active wallet for that currency.

03

Select Gateways

From API Config, enable the payment gateways that should appear on hosted checkout for each eligible currency.

04

Sign & Create Payment

POST to /api/v1/initiate-payment with X-Timestamp and X-Signature, redirect the customer to payment_url, then verify or listen for IPN.

API Config Currency + Wallet Gateway Filter Hosted Checkout
Open Testing Console

Use sandbox credentials first, then switch to production when your checkout and IPN are verified.

Latest Merchant Update API Config controls checkout after keys are generated

Merchant Setup & API Config

The merchant API is no longer a single-currency, fixed-gateway flow. A merchant can now support multiple currency rails, keep separate sandbox and production credentials, and choose eligible gateways from the API Config page without regenerating API keys.

Merchant Dashboard

One integration, dashboard-controlled checkout

Your code sends amount, currency, redirects, IPN URL, and optional gateway keywords. The dashboard decides which currency rails, wallets, and payment gateways are actually available for that merchant.

Sandbox keys Production keys Wallet rails Gateway controls
Default mode Sandbox
Live access Requires approval
Gateway source API Config

Merchant Review Status

Pending merchants can test in sandbox. Production API access and live checkout are available only after admin approval.

Currency Rails

Each request currency_code must exist in the merchant-supported currency list. Unsupported currencies are rejected before checkout opens.

Receiver Wallet Match

The merchant owner must have an active wallet for the requested currency, otherwise the API returns a wallet availability error.

Payment Gateway Controls

Only active automatic gateways that match the requested currency and merchant selection can appear on hosted checkout.

Runtime Decision Order

  1. 01
    Authenticate the environment

    X-Environment decides which merchant key, API key, and API secret are used.

  2. 02
    Check merchant availability

    Rejected or disabled merchants are blocked. Production also requires approved merchant status.

  3. 03
    Validate requested currency

    currency_code must match a merchant-supported rail such as USD, EUR, or BDT.

  4. 04
    Confirm receiver wallet

    The merchant owner needs an active wallet for that same currency.

  5. 05
    Resolve configured gateways

    Merchant API Config selections restrict checkout to the chosen eligible gateways. If none are selected, the safe fallback is all active automatic gateways for that currency.

  6. 06
    Apply optional API filter

    allow_payment_methods can narrow the available gateway list, but it cannot expose an unconfigured or wrong-currency gateway.

Real Cases & Results

Case API Result Fix
Merchant supports USD and EUR, but only USD wallet exists. 422 Receiver wallet for this currency is not available. Create/activate the EUR merchant wallet before accepting EUR checkout.
Stripe USD is selected, but the request sends currency_code EUR. Stripe USD will not appear on checkout. Select an active EUR gateway or send USD.
Merchant has not selected any gateway yet. Checkout falls back to all active automatic gateways that match the requested currency. Use API Config to lock checkout to preferred gateways.
allow_payment_methods=["paypal"] but PayPal is not configured for the merchant. PayPal remains hidden. Enable PayPal from Payment Gateway Controls if its currency matches.
Pending merchant calls production API. 403 Merchant Pending Approval Use sandbox until admin approval is complete.
No cross-currency gateways

A gateway configured for USD cannot process EUR checkout unless a separate EUR gateway exists.

Secrets stay server-side

API Secret is used only to sign server-to-server API requests and verify IPN signatures.

Signed checkout URL expires

The returned payment_url is time-limited. Create a new payment session for expired checkout links.

Verify is merchant scoped

A merchant can verify only its own transaction and only in the matching sandbox or production environment.

Currency & Gateway Rules

Merchant API checkout is controlled by three layers: merchant-supported currency, active receiver wallet, and configured payment gateways. This keeps checkout options accurate after API credentials are generated.

Gateway Match Matrix

A gateway appears on hosted checkout only when every rule below is true. If the merchant has selected gateways, those selected gateways become the allowed set for checkout.

Dashboard Source Merchant -> Config -> Payment Gateway Controls
Currency enabled for merchant The request currency_code must exist in the merchant-supported currency list.
Active merchant wallet exists The merchant owner must have an active wallet for the requested currency.
Gateway currency matches Only active automatic deposit methods for that exact currency are eligible.
Merchant gateway selection passes When gateways are selected in API Config, checkout is restricted to those selected methods.

How allow_payment_methods Works Now

Layer Who controls it Effect
currency_code API request Must match a merchant-supported currency with an active receiver wallet.
Payment Gateway Controls Merchant dashboard Defines the gateway set available to hosted checkout for each eligible currency.
allow_payment_methods API request Optional name/code keyword filter applied after merchant gateway rules. It cannot expose a gateway the merchant did not configure.
Safe Default If a merchant has not selected any gateways, checkout falls back to all active automatic gateways that match the requested currency. Once the merchant selects gateways, checkout uses only that configured list.
POST

Initiate Payment

Create a hosted checkout session for a merchant-supported currency. The returned payment_url should be opened by the customer.

https://eripays.com/api/v1/initiate-payment
API key required HMAC signature required Sandbox + production Currency wallet checked
Gateway Selection Hosted checkout first applies merchant currency and wallet rules, then the gateways selected on Merchant API Config. allow_payment_methods is only an optional extra filter.

Request Headers

Header Value Required Description
Content-Type application/json Yes Request content type
Accept application/json Yes Expected response type
X-Environment sandbox | production Yes Use sandbox for testing and production for live payments
X-Merchant-Key {merchant_key} Yes Merchant identifier from the API Config page
X-API-Key {api_key} Yes API key for the selected environment
X-Timestamp {unix_timestamp} Yes Current Unix timestamp in seconds. Requests outside the allowed tolerance are rejected.
X-Signature sha256={hmac} Yes HMAC-SHA256 of timestamp.METHOD.path_with_query.raw_body using the API Secret for the selected environment.

Request Parameters

Parameter Type Required Description
payment_amount number Yes Payment amount. Minimum value is 1.00.
currency_code string Yes 3-letter currency code. Must be enabled for the merchant and backed by an active merchant wallet.
ref_trx string Yes Your unique order or transaction reference. Max 60 characters.
success_redirect url Yes Customer is redirected here after a successful hosted checkout.
cancel_redirect url Yes Customer is redirected here when checkout is canceled or cannot continue.
ipn_url url Yes Server-to-server webhook URL for payment status updates. Must be a public HTTPS address (sandbox also accepts public HTTP); private and local addresses are refused.
description string No Payment description visible in merchant transaction context.
customer_name string No Customer name. Max 100 characters.
customer_email email No Customer email address. Max 100 characters.
allow_payment_methods string | array No Optional keyword filter applied after merchant gateway rules. Example: "stripe,paypal" or ["stripe","paypal"].

Gateway Availability Response Fields

Field Type Meaning
info.merchant_payment_methods_restricted boolean true when the merchant has selected specific gateways in API Config.
info.merchant_payment_method_ids array Eligible deposit method IDs for the requested currency.
info.merchant_payment_method_codes array Eligible method codes that can appear on hosted checkout.

Code Examples

curl -X POST "https://eripays.com/api/v1/initiate-payment" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "X-Environment: sandbox" \
  -H "X-Merchant-Key: test_merchant_key" \
  -H "X-API-Key: test_api_key" \
  -H "X-Timestamp: 1778650000" \
  -H "X-Signature: sha256=generated_hmac_signature" \
  -d '{
    "payment_amount": 250.00,
    "currency_code": "USD",
    "ref_trx": "ORDER_12345",
    "description": "Premium Subscription",
    "success_redirect": "https://merchant.example/payments/success",
    "cancel_redirect": "https://merchant.example/payments/cancel",
    "ipn_url": "https://merchant.example/webhooks/eripay",
    "customer_name": "John Doe",
    "customer_email": "john@example.com",
    "allow_payment_methods": ["stripe", "paypal"]
  }'
<?php

use Illuminate\Support\Facades\Http;

$payload = [
    'payment_amount' => 250.00,
    'currency_code' => 'USD',
    'ref_trx' => 'ORDER_12345',
    'description' => 'Premium Subscription',
    'success_redirect' => route('payments.success'),
    'cancel_redirect' => route('payments.cancel'),
    'ipn_url' => route('webhooks.eripay'),
    'customer_name' => 'John Doe',
    'customer_email' => 'john@example.com',
    'allow_payment_methods' => ['stripe', 'paypal'],
];

$body = json_encode($payload, JSON_THROW_ON_ERROR);
$timestamp = (string) time();
$path = '/api/v1/initiate-payment';
$signature = hash_hmac(
    'sha256',
    $timestamp.'.POST.'.$path.'.'.$body,
    config('services.eripay.api_secret')
);

$response = Http::withHeaders([
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'X-Environment' => 'sandbox',
    'X-Merchant-Key' => config('services.eripay.merchant_key'),
    'X-API-Key' => config('services.eripay.api_key'),
    'X-Timestamp' => $timestamp,
    'X-Signature' => 'sha256='.$signature,
])->withBody($body, 'application/json')
    ->post('https://eripays.com/api/v1/initiate-payment')
    ->throw()
    ->json();

return redirect()->away($response['payment_url']);
const crypto = require('crypto');

const payload = {
  payment_amount: 250.00,
  currency_code: 'USD',
  ref_trx: 'ORDER_12345',
  description: 'Premium Subscription',
  success_redirect: 'https://merchant.example/payments/success',
  cancel_redirect: 'https://merchant.example/payments/cancel',
  ipn_url: 'https://merchant.example/webhooks/eripay',
  customer_name: 'John Doe',
  customer_email: 'john@example.com',
  allow_payment_methods: ['stripe', 'paypal']
};

const body = JSON.stringify(payload);
const timestamp = Math.floor(Date.now() / 1000).toString();
const path = '/api/v1/initiate-payment';
const signature = crypto
  .createHmac('sha256', process.env.ERIPAY_API_SECRET)
  .update(`${timestamp}.POST.${path}.${body}`)
  .digest('hex');

const response = await fetch('https://eripays.com/api/v1/initiate-payment', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'X-Environment': 'sandbox',
    'X-Merchant-Key': process.env.ERIPAY_MERCHANT_KEY,
    'X-API-Key': process.env.ERIPAY_API_KEY,
    'X-Timestamp': timestamp,
    'X-Signature': `sha256=${signature}`
  },
  body
});

const data = await response.json();

if (!response.ok) {
  throw new Error(data.error || 'Payment initiation failed');
}

window.location.href = data.payment_url;

Success Response

200 OK Payment session created
{
  "payment_url": "https://eripays.com/payment/checkout?expires=1791290858&token=encrypted&signature=signed",
  "trx_id": "TXN7148PS8GPQKN",
  "ref_trx": "ORDER_12345",
  "expires_at": "2026-10-07T07:00:00+03:00",
  "info": {
    "ref_trx": "ORDER_12345",
    "description": "Premium Subscription",
    "ipn_url": "https://merchant.example/webhooks/eripay",
    "cancel_redirect": "https://merchant.example/payments/cancel",
    "success_redirect": "https://merchant.example/payments/success",
    "customer_name": "John Doe",
    "customer_email": "john@example.com",
    "merchant_id": 1,
    "merchant_name": "Demo Store",
    "amount": 250,
    "currency_code": "USD",
    "environment": "sandbox",
    "is_sandbox": true,
    "allow_payment_methods": ["stripe", "paypal"],
    "merchant_payment_methods_restricted": true,
    "merchant_payment_method_ids": [7],
    "merchant_payment_method_codes": ["stripe-usd"]
  }
}

Common Error Responses

422 Currency is not enabled for this merchant.

The requested currency_code is not in the merchant-supported currency list.

422 Receiver wallet for this currency is not available.

The merchant owner does not have an active wallet for the requested currency.

401 Invalid API credentials.

Check X-Environment, X-Merchant-Key, and X-API-Key for the same environment.

409 This ref_trx has already been paid.

Creating a payment is idempotent on ref_trx: the same order returns the same pending checkout, a paid order returns 409 with its trx_id, and a different amount or currency for the same ref_trx returns 409.

422 ipn_url must be a public HTTPS address.

Webhooks are only delivered to public addresses.

429 Too many requests.

Over the per-minute rate limit, or more than 20 failed authentication attempts a minute from one address. Wait for Retry-After seconds.

GET

Verify Payment

Fetch the latest status for a hosted checkout transaction. Always verify server-side before fulfilling an order.

https://eripays.com/api/v1/verify-payment/{trxId}
Use after redirect or IPN Merchant scoped

Request Headers

Header Value Required Description
Accept application/json Yes Expected response type
X-Environment sandbox | production Yes Must match the environment used to initiate the payment
X-Merchant-Key {merchant_key} Yes Merchant identifier from API Config
X-API-Key {api_key} Yes API key for the selected environment
X-Timestamp {unix_timestamp} Yes Use the same timestamp format as payment initiation.
X-Signature sha256={hmac} Yes Sign timestamp.GET./api/v1/verify-payment/{trxId}. using the matching API Secret. The raw body is empty for GET requests.

Path Parameter

Parameter Type Required Description
trxId string Yes The trx_id returned when you created the payment (or sent in the IPN), or your own ref_trx for that order.

cURL Example

curl -X GET "https://eripays.com/api/v1/verify-payment/TXNQ5V8K2L9N3XM1" \
  -H "Accept: application/json" \
  -H "X-Environment: sandbox" \
  -H "X-Merchant-Key: test_merchant_key" \
  -H "X-API-Key: test_api_key" \
  -H "X-Timestamp: 1778650000" \
  -H "X-Signature: sha256=generated_hmac_signature"

Success Response

200 OK Completed payment
{
  "status": "success",
  "trx_id": "TXNQ5V8K2L9N3XM1",
  "amount": 237.5,
  "fee": 12.5,
  "currency": "USD",
  "net_amount": 237.5,
  "customer": {
    "name": "John Doe",
    "email": "john@example.com"
  },
  "description": "Premium Subscription",
  "created_at": "2026-05-13T10:30:00.000000Z",
  "updated_at": "2026-05-13T10:35:45.000000Z"
}

Payment Status Values

Status Description Recommended Action
pending Payment is still processing. Wait for IPN or verify again later.
success Payment completed successfully. Fulfill the order after idempotency checks.
failed Payment failed or was canceled. Do not fulfill; show retry or cancel state.
Idempotency Use your ref_trx and the returned trx_id to make fulfillment idempotent. A webhook and a verify request may arrive close together.
GET

Site Info

Fetch gateway branding, environment labels, and customer-facing checkout metadata for a merchant-authenticated integration.

https://eripays.com/api/v1/site-info
Merchant auth required Checkout branding Environment labels

cURL Example

curl -X GET "https://eripays.com/api/v1/site-info" \
  -H "Accept: application/json" \
  -H "X-Environment: sandbox" \
  -H "X-Merchant-Key: test_merchant_key" \
  -H "X-API-Key: test_api_key" \
  -H "X-Timestamp: 1778650000" \
  -H "X-Signature: sha256=generated_hmac_signature"

Success Response

200 OK Gateway metadata
{
  "site_name": "EriPay",
  "site_logo": "https://eripays.com/storage/images/2026/09/18/20260918_181848_ic_launcher_I86m.png",
  "site_url": "https://eripays.com",
  "gateway_name": "EriPay Payment Gateway",
  "gateway_description": "Secure payment powered by EriPay",
  "features": {
    "ssl_secured": "SSL Secured",
    "instant_processing": "Instant",
    "global_support": "Global",
    "mobile_ready": "Mobile Ready"
  },
  "environments": {
    "production": "Production Mode - Live payment processing is active",
    "sandbox": "Test Mode - This is a test transaction. No real money will be charged"
  },
  "api_version": "1.0",
  "status": "active"
}
POST

Refund Payment

Refund all or part of a completed payment back to the customer. Partial refunds add up and can never exceed what the customer paid.

https://eripays.com/api/v1/refund-payment
Full or partial Merchant scoped Idempotency-Key supported

Where the money goes

Customer paid withRefundrefund_status
Wallet ID + PIN or logged-in wallet Credited to the customer's wallet immediately. completed
Mobile Money Sent to the number that paid. Your wallet is debited the amount plus the mobile money payout fee; if the provider fails it, both return to your wallet. processing → webhook
Sandbox payments Recorded only; no money moves. completed

Your wallet must hold the refund amount. The original processing fee is not returned. Payments made through other gateways cannot be refunded through the API.

Request Headers

The same headers and HMAC signature as Initiate Payment: sign timestamp.POST./api/v1/refund-payment.{raw body} with the API Secret for the environment. Send an Idempotency-Key (a UUID) so a retried request replays the first answer, marked Idempotent-Replayed: true, instead of refunding twice. Reusing a key with different parameters returns 409.

Request Parameters

ParameterTypeRequiredDescription
trx_idstring Yes The trx_id of the completed payment
amountnumber No Amount to refund. Omit to refund everything not yet refunded. Mobile money refunds must be at least 500 UGX.
reasonstring No Stored with the refund (max 255 characters)
ref_refundstring No Your own refund reference. The same reference never refunds twice for a payment.

cURL Example

curl -X POST "https://eripays.com/api/v1/refund-payment" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "X-Environment: production" \
  -H "X-Merchant-Key: your_merchant_key" \
  -H "X-API-Key: your_api_key" \
  -H "X-Timestamp: 1759650000" \
  -H "X-Signature: sha256=generated_hmac_signature" \
  -H "Idempotency-Key: 63632250-3170-421f-8021-9d0a730e90aa" \
  -d '{"trx_id": "TXNQ5V8K2L9N3XM1", "amount": 10000, "reason": "Customer returned item", "ref_refund": "RFD-10231"}'

Success Response

200 OK Refund recorded
{
  "status": "success",
  "message": "Refund is being sent to the customer's mobile money number.",
  "refund_trx_id": "TXNZ9YX87WV65AB",
  "original_trx_id": "TXNQ5V8K2L9N3XM1",
  "ref_refund": "RFD-10231",
  "refund_status": "processing",
  "method": "mobile_money",
  "refunded_amount": 10000,
  "total_refunded": 10000,
  "remaining_refund": 40000,
  "fully_refunded": false,
  "currency": "UGX"
}

Refund Webhook

When a refund completes (or a mobile money refund fails), the payment's ipn_url receives a signed POST. Verify X-Signature (HMAC-SHA256 of the raw body with your API Secret). Refund webhooks are only sent to public HTTPS URLs.

{
  "event": "payment.refunded",
  "status": "refunded",
  "data": {
    "refund_trx_id": "TXNZ9YX87WV65AB",
    "original_trx_id": "TXNQ5V8K2L9N3XM1",
    "ref_trx": "ORDER-10231",
    "ref_refund": "RFD-10231",
    "refund_status": "completed",
    "method": "mobile_money",
    "refunded_amount": 10000,
    "total_refunded": 10000,
    "remaining_refund": 40000,
    "fully_refunded": false,
    "currency": "UGX"
  },
  "message": "Payment refunded.",
  "timestamp": 1759650000
}

A failed mobile money refund sends event payment.refund_failed with status refund_failed; the amount is back in your wallet and can be refunded again.

Common Errors

  • 404 Transaction not found (not yours, or a different environment).
  • 422 Only completed payments can be refunded · Refund amount exceeds the refundable balance · Insufficient merchant wallet balance · This payment method cannot be refunded through the API.
  • 409 Idempotency-Key reused with different parameters, or the first request is still running (honour Retry-After).
API

Recurring Payments (Subscriptions)

Bill a customer daily, weekly, monthly, half-yearly or yearly. Each period is a hosted invoice the customer pays with their wallet or mobile money; the subscription becomes active, and moves to the next period, only when a payment completes.

https://eripays.com/api/v1/subscriptions
Customer approves every payment Merchant and environment scoped Idempotency-Key supported

EriPay stores no card or mobile money mandate: nothing is ever charged without the customer approving it. When a period ends, EriPay creates the next invoice, marks the subscription past_due and sends you a webhook with the invoice payment_url to share with the customer (by SMS, email or in your app).

Endpoints

MethodEndpointPurpose
POST/api/v1/subscriptionsCreate a subscription and its first invoice (or schedule a future start). Returns 201.
GET/api/v1/subscriptions?status=List your subscriptions (20 per page; filter by pending, active, past_due or canceled).
GET/api/v1/subscriptions/{id}Current status and the latest 20 invoices.
POST/api/v1/subscriptions/{id}/cancelCancel at period end (default), or now with at_period_end=false. Canceling now voids the open invoice.
POST/api/v1/subscriptions/{id}/renewGet a payable invoice for the unpaid period: the open one with a fresh link, or a new one if the last payment failed. Active subscriptions cannot renew early (409).

All endpoints use the same headers and HMAC signature as Initiate Payment. Send an Idempotency-Key on every POST: retrying the identical request within 24 hours returns the original response with Idempotent-Replayed: true; reusing the key with different parameters returns 409.

Create Subscription Fields

FieldRequiredRules
external_referenceYesYour ID; unique per merchant and environment (max 100). Sent back as ref_trx on invoice payment IPNs.
billing_cycleYesdaily, weekly, monthly, half_yearly, yearly
payment_amountYesAmount per period (mobile money payments start at 500 UGX)
currency_codeYesA currency enabled for your merchant account
customer_emailYesValid email (max 150)
success_redirect, cancel_redirectYesAbsolute URLs
ipn_urlYesHTTPS URL on a public network; private and internal addresses are rejected
customer_name, descriptionNoShown on the hosted invoice
starts_atNoISO 8601 date-time in the future; the first invoice is created then
allow_payment_methodsNoLimit checkout methods, as with Initiate Payment
metadataNoJSON object (max 50 entries). Never store secrets.

Status Lifecycle

StatusMeaning
pendingFirst invoice unpaid, or starts_at not reached.
activePaid through current_period_end. The first period starts when the customer pays.
past_dueThe period ended and the renewal invoice is unpaid. Paying it restores active; periods stay back-to-back.
canceledNo further invoices.

Create Example

curl -X POST "https://eripays.com/api/v1/subscriptions" \
  -H "Content-Type: application/json" -H "Accept: application/json" \
  -H "X-Environment: production" -H "X-Merchant-Key: your_merchant_key" -H "X-API-Key: your_api_key" \
  -H "X-Timestamp: 1759650000" -H "X-Signature: sha256=generated_hmac_signature" \
  -H "Idempotency-Key: 0b9c2f2e-7d1c-4b8e-9a41-5f3e2c1d0a77" \
  -d '{"external_reference": "SCHOOL-FEES-42", "billing_cycle": "monthly", "payment_amount": 150000,
       "currency_code": "UGX", "customer_email": "parent@example.com", "customer_name": "A Parent",
       "success_redirect": "https://school.example/paid", "cancel_redirect": "https://school.example/cancel",
       "ipn_url": "https://school.example/eripay/ipn"}'

Response

201 Created Subscription
{
  "status": "success",
  "data": {
    "id": "sub_k2v9q4x7m1c8z5r3t6w0y2ab",
    "external_reference": "SCHOOL-FEES-42",
    "status": "pending",
    "environment": "production",
    "billing_cycle": "monthly",
    "payment_amount": 150000,
    "currency_code": "UGX",
    "current_period_start": null,
    "current_period_end": null,
    "next_billing_at": null,
    "cancel_at_period_end": false,
    "latest_invoice": {
      "trx_id": "TXNQ5V8K2L9N3XM1",
      "sequence": 1,
      "status": "pending",
      "amount": 150000,
      "payment_url": "https://eripays.com/payment/checkout?token=...&signature=..."
    }
  }
}

Webhooks

Signed like payment IPNs (verify X-Signature, HMAC-SHA256 of the raw body with your API Secret) and sent to the subscription ipn_url. data is the subscription object above.

eventWhen
subscription.activatedThe first invoice was paid
subscription.renewedA renewal invoice was paid
subscription.past_dueA period ended; data.latest_invoice.payment_url is the renewal checkout to send the customer
subscription.canceledCanceled now, or at the end of the period

Each invoice payment also sends the normal payment IPN (data.ref_trx is your external_reference, plus data.subscription_id). Grant access only on a completed payment, and make fulfilment idempotent using the trx_id.

POST

OAuth 2.0 Authentication (Token)

Authenticate using OAuth 2.0 client credentials flow to obtain a secure Bearer access token for Mobile Money API operations.

https://eripays.com/connect/token
Client Credentials Flow High Entropy Bearer Token 3600s Expiry Production & Sandbox
Getting Your API Credentials You can find your Client ID (Merchant Key) and Client Secret (API Secret) in your Merchant Dashboard under Config -> API Credentials. Both test and live keys are supported.

Request Headers

Header Value Required Description
Content-Type application/x-www-form-urlencoded | application/json Yes Request body format
Accept application/json Yes Expected response format

Request Body Parameters

Parameter Type Required Description
client_id string Yes Your unique Client ID or Merchant Key
client_secret string Yes Your secret API Key / Secret
grant_type string Yes Must be set to "client_credentials"

Code Examples

curl --request POST \
  --url "https://eripays.com/connect/token" \
  --header "Content-Type: application/x-www-form-urlencoded" \
  --header "Accept: application/json" \
  --data "client_id=your_client_id" \
  --data "client_secret=your_client_secret" \
  --data "grant_type=client_credentials"
<?php

use Illuminate\Support\Facades\Http;

$response = Http::asForm()->post('https://eripays.com/connect/token', [
    'client_id'     => 'your_client_id',
    'client_secret' => 'your_client_secret',
    'grant_type'    => 'client_credentials',
]);

$tokenData = $response->json();
$accessToken = $tokenData['access_token'];
const response = await fetch('https://eripays.com/connect/token', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    'Accept': 'application/json'
  },
  body: new URLSearchParams({
    client_id: 'your_client_id',
    client_secret: 'your_client_secret',
    grant_type: 'client_credentials'
  })
});

const data = await response.json();
const accessToken = data.access_token;

Success Response

200 OK OAuth 2.0 Access Token Issued
{
  "access_token": "a1b2c3d4e5f60718293a4b5c6d7e8f90...",
  "expires_in": 3600,
  "token_type": "Bearer",
  "scope": "profile email"
}

Sandbox Test Mobile Numbers

Use the following designated phone numbers in Sandbox mode to simulate various network outcomes:

Number Pattern Outcome Description Example
011177777(0-9) Success Simulates immediate payment authorization and success 0111777771
011177799(0-9) Failed Simulates payer decline or insufficient funds 0111777991
011177778(0-9) Pending Simulates awaiting user PIN entry on mobile handset 0111777781
011177779(0-9) SentToVendor Simulates network provider queueing (e.g. MTN / Airtel) 0111777791
GET

Wallet Balance

Retrieve the current total and available balance of a specified payment gateway wallet.

https://eripays.com/api/wallet-balance/{walletId}
Bearer Token Required Wallet Scoped

Request Headers

Header Value Required Description
Authorization Bearer {access_token} Yes OAuth 2.0 Bearer token from /connect/token
Accept application/json Yes Expected response format

Path Parameters

Parameter Type Required Description
walletId string (UUID) Yes The unique UUID of the merchant wallet

cURL Example

curl --request GET \
  --url "https://eripays.com/api/wallet-balance/5e83b187-801e-410e-b76e-f491928547e0" \
  --header "Authorization: Bearer your_access_token" \
  --header "Accept: application/json"

Success Response

200 OK Wallet Balance Details
{
  "id": "5e83b187-801e-410e-b76e-f491928547e0",
  "currency": "UGX",
  "partnerId": "1",
  "name": "UGX Wallet",
  "actualBalance": 250000.00,
  "availableBalance": 250000.00,
  "collectionCallBackUrl": "https://yourdomain.com/webhooks/collection",
  "disbursementCallBackUrl": "https://yourdomain.com/webhooks/disbursement"
}
POST

Initiate Mobile Money Collection

Request a mobile money payment prompt on the payer’s mobile handset into your payment gateway wallet.

https://eripays.com/api/collections/collect
Bearer Token Required Instant Push Prompt Idempotent with externalId

Request Body Parameters

Parameter Type Required Description
amount number Yes Amount to be collected from the payer
payer string Yes Mobile money number of payer (e.g. 256770000001 or sandbox test number)
currency string No Currency code (default: UGX)
walletId string No Target wallet UUID. Defaults to active merchant wallet for the currency.
externalId string No Your unique transaction tracking ID for reconciliation and duplicate prevention.
payerNote string No Note shown to the payer on their device.
payeeNote string No Note for internal merchant reference.

cURL Example

curl --request POST \
  --url "https://eripays.com/api/collections/collect" \
  --header "Authorization: Bearer your_access_token" \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --data '{
    "category": "MobileMoney",
    "currency": "UGX",
    "externalId": "ORDER-1002",
    "payer": "0111777771",
    "payerName": "Jane Doe",
    "amount": 5000,
    "payerNote": "Payment for Order #1002",
    "payeeNote": "Invoice 1002"
  }'

Success Response

200 OK CollectionViewModel
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "createdAt": "2026-09-19T17:30:00.000Z",
  "category": "MobileMoney",
  "status": "Success",
  "paymentChannel": "MobileMoney",
  "statusCode": "success",
  "statusMessage": "The transaction is successful.",
  "externalId": "ORDER-1002",
  "walletId": "5e83b187-801e-410e-b76e-f491928547e0",
  "partnerId": "1",
  "amount": 5000,
  "currency": "UGX",
  "payer": "0111777771",
  "payerName": "Jane Doe",
  "payerNote": "Payment for Order #1002",
  "payeeNote": "Invoice 1002",
  "wallet": {
    "id": "5e83b187-801e-410e-b76e-f491928547e0",
    "text": "UGX Wallet"
  },
  "chargeModel": "Standard",
  "transactionCharge": 0,
  "vendorCharge": 0,
  "totalTransactionCharge": 0,
  "vendor": "MTN",
  "vendorTransactionId": "TRX_ABC12345",
  "lastUpdated": "2026-09-19T17:30:00.000Z",
  "transactions": []
}
GET

Get Collection Status

Check the real-time status of a mobile money collection using either the system request ID or your externalId.

https://eripays.com/api/collections/status/{requestId}
https://eripays.com/api/collections/external-id/{externalId}

cURL Examples

# Check by Request ID
curl --request GET \
  --url "https://eripays.com/api/collections/status/3fa85f64-5717-4562-b3fc-2c963f66afa6" \
  --header "Authorization: Bearer your_access_token"

# Check by your External ID
curl --request GET \
  --url "https://eripays.com/api/collections/external-id/ORDER-1002" \
  --header "Authorization: Bearer your_access_token"
POST

Initiate Payment Disbursement

Withdraw funds from your wallet and disburse directly to a recipient’s mobile money phone number or bank account.

The recipient receives exactly the amount you send. Your wallet is debited that amount plus the EriPay payout fee, returned as fee in the response. Both are refunded if the payout fails.

https://eripays.com/api/disbursements/disburse
Bearer Token Required Atomic Balance Lock Zero Double-Payout Guarantee

Request Body Parameters

Parameter Type Required Description
amount number Yes Amount to be disbursed to the recipient. Your wallet must also cover the payout fee.
payee string Yes Recipient mobile money phone number
currency string No Currency code (default: UGX)
walletId string No Source wallet UUID
externalId string No Your unique tracking reference. Prevents duplicate payouts if request is retried.
payeeName string No Name of the recipient.

cURL Example

curl --request POST \
  --url "https://eripays.com/api/disbursements/disburse" \
  --header "Authorization: Bearer your_access_token" \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --data '{
    "category": "MobileMoney",
    "currency": "UGX",
    "externalId": "PAYOUT-5001",
    "payee": "0111777771",
    "payeeName": "Alex Vendor",
    "amount": 2500,
    "payerNote": "Commission Payout",
    "payeeNote": "Payment for August sales"
  }'

Success Response

200 OK DisbursementViewModel
{
  "id": "7ca85f64-5717-4562-b3fc-2c963f66afa7",
  "createdAt": "2026-09-19T17:35:00.000Z",
  "category": "MobileMoney",
  "status": "Success",
  "paymentChannel": "MobileMoney",
  "statusCode": "success",
  "statusMessage": "The transaction is successful.",
  "externalId": "PAYOUT-5001",
  "walletId": "5e83b187-801e-410e-b76e-f491928547e0",
  "partnerId": "1",
  "amount": 2500,
  "fee": 500,
  "currency": "UGX",
  "payee": "0111777771",
  "payeeName": "Alex Vendor",
  "payeeUploadName": "Alex Vendor",
  "payeeNameStatus": "Verified",
  "approvalDecision": true,
  "lastUpdated": "2026-09-19T17:35:00.000Z"
}
GET

Disbursement Status & History

Check disbursement progress by transaction ID, externalId, or query paginated disbursement history.

https://eripays.com/api/disbursements/status/{transactionId}
https://eripays.com/api/disbursements/external-id/{externalId}
https://eripays.com/api/disbursements/paged-history?page=1&pageSize=20
https://eripays.com/api/disbursements/bank-list

Webhooks (IPN)

EriPay sends real-time notifications to your specified IPN URL when payment status changes. This ensures you're immediately notified of payment completions, failures, and other status updates. Webhooks work identically in both sandbox and production environments.

Environment-Aware Webhooks

Use the same webhook URL for both sandbox and production. EriPay will include environment context in webhook payloads to help you differentiate between test and live transactions.

Reliable Delivery EriPay retries timeout webhook deliveries up to 3 attempts. Your endpoint should return a 2xx response as soon as the payload is safely queued or processed.

Webhook Headers

Header Description Example
Content-Type Always application/json application/json
X-Signature Raw HMAC-SHA256 signature for verification a8b9c2d1e5f3...
X-Environment Webhook environment context sandbox | production

Webhook Payload

All webhook payloads include environment information to help you differentiate between sandbox and production transactions:

Environment Context: The X-Environment header and data.environment are sandbox for test transactions or production for live ones. Sandbox webhooks are signed with your sandbox API secret, live ones with your live API secret.
{
    "event": "payment.completed",
    "trx_id": "TXN7148PS8GPQKN",
    "ref_trx": "ORDER_12345",
    "amount": 200,
    "fee": 5,
    "net_amount": 195,
    "currency": "USD",
    "attempt": 1,
    "data": {
        "ref_trx": "ORDER_12345",
        "description": "Order #1234",
        "ipn_url": "https://webhook.site/5711b7d5-917a-4d94-bbb3-c28f4a37bea5",
        "cancel_redirect": "https://merchant.com/cancel",
        "success_redirect": "https://merchant.com/success",
        "customer_name": "John Doe",
        "customer_email": "john@example.com",
        "merchant_name": "Xanthus Wiggins",
        "amount": 200,
        "currency_code": "USD",
        "environment": "production",
        "is_sandbox": false
    },
    "message": "Payment Completed",
    "status": "completed",
    "timestamp": 1705747245
}

Delivery and Retries

  • event is payment.completed or payment.failed (refunds and subscriptions send their own events). amount is what the customer paid; net_amount is what reaches your wallet after the fee.
  • Reply with any 2xx status within 10 seconds. Redirects are not followed.
  • If your endpoint is down or replies with an error, the webhook is sent again after about 1 minute, 5 minutes, 15 minutes, 1 hour, 3 hours and 12 hours (attempt shows which try it is).
  • The same event can arrive more than once: use trx_id to process each payment only once, and confirm with Verify Payment before fulfilling.

Signature Verification

Always verify webhook signatures to ensure authenticity and prevent unauthorized requests. Use your API secret (environment-specific) to verify signatures:

Environment-Specific Secrets: Use test_webhook_secret for sandbox and webhook_secret for production environments.
<?php
// Laravel Webhook Handler
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use App\Enums\EnvironmentMode;

class EriPayWebhookController extends Controller
{
    public function handle(Request $request)
    {
        // Get webhook headers
        $environment = $request->header('X-Environment', 'production');
        $signature = $request->header('X-Signature');
        
        // Get appropriate secret based on environment
        $secret = $this->getSecretForEnvironment($environment);
        
        // Verify signature
        if (!$this->verifySignature($request->getContent(), $signature, $secret)) {
            Log::warning('EriPay webhook signature verification failed', [
                'environment' => $environment
            ]);
            
            return response()->json(['error' => 'Invalid signature'], 401);
        }
        
        $payload = $request->json()->all();
        
        // Handle based on environment
        if ($environment === EnvironmentMode::SANDBOX->value) {
            return $this->handleSandboxWebhook($payload);
        } else {
            return $this->handleProductionWebhook($payload);
        }
    }
    
    private function getSecretForEnvironment(string $environment): string
    {
        // Return test secret for sandbox, live secret for production
        return $environment === 'sandbox' 
            ? config('eripay.test_webhook_secret')
            : config('eripay.webhook_secret');
    }
    
    private function verifySignature(string $payload, string $signature, string $secret): bool
    {
        $expectedSignature = hash_hmac('sha256', $payload, $secret);
        $providedSignature = str_starts_with($signature, 'sha256=') ? substr($signature, 7) : $signature;

        return hash_equals($expectedSignature, $providedSignature);
    }
    
    private function handleSandboxWebhook(array $payload): JsonResponse
    {
        Log::info('Processing sandbox webhook', $payload);
        
        // Your sandbox-specific logic here
        // Don't fulfill orders, don't send emails to real customers, etc.
        
        return response()->json(['status' => 'sandbox_processed']);
    }
    
    private function handleProductionWebhook(array $payload): JsonResponse
    {
        Log::info('Processing production webhook', $payload);
        
        // Your production logic here
        // Fulfill orders, send confirmation emails, etc.
        
        return response()->json(['status' => 'processed']);
    }
}
const crypto = require('crypto');
const express = require('express');

const EnvironmentMode = {
    SANDBOX: 'sandbox',
    PRODUCTION: 'production'
};

// Webhook handler
app.post('/api/webhooks/eripay', async (req, res) => {
    const environment = req.headers['x-environment'] || 'production';
    const signature = req.headers['x-signature'];
    
    # Get appropriate secret based on environment
    const secret = getSecretForEnvironment(environment);
    
    # Verify signature
    if (!verifySignature(JSON.stringify(req.body), signature, secret)) {
        console.warn('EriPay webhook signature verification failed', {
            environment: environment
        });
        
        return res.status(401).json({ error: 'Invalid signature' });
    }
    
    const payload = req.body;
    
    try {
        # Handle based on environment
        if (environment === EnvironmentMode.SANDBOX) {
            await handleSandboxWebhook(payload);
        } else {
            await handleProductionWebhook(payload);
        }
        
        res.json({ status: 'processed' });
    } catch (error) {
        console.error('Webhook processing error:', error);
        res.status(500).json({ error: 'Processing failed' });
    }
});

function getSecretForEnvironment(environment) {
    # Return test secret for sandbox, live secret for production
    return environment === 'sandbox' 
        ? process.env.ERIPAY_TEST_WEBHOOK_SECRET
        : process.env.ERIPAY_WEBHOOK_SECRET;
}

function verifySignature(payload, signature, secret) {
    if (!signature) {
        return false;
    }
    
    const expectedSignature = crypto
        .createHmac('sha256', secret)
        .update(payload)
        .digest('hex');
    const providedSignature = signature.startsWith('sha256=') ? signature.slice(7) : signature;
    
    return crypto.timingSafeEqual(
        Buffer.from(expectedSignature),
        Buffer.from(providedSignature)
    );
}

async function handleSandboxWebhook(payload) {
    console.log('Processing sandbox webhook:', payload);
    
    # Your sandbox-specific logic here
    # Don't fulfill orders, don't send emails to real customers, etc.
}

async function handleProductionWebhook(payload) {
    console.log('Processing production webhook:', payload);
    
    # Your production logic here
    # Fulfill orders, send confirmation emails, etc.
}
import hmac
import hashlib
import json
import logging
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods

logger = logging.getLogger(__name__)

ENVIRONMENT_MODE = {
    'SANDBOX': 'sandbox',
    'PRODUCTION': 'production'
}

@csrf_exempt
@require_http_methods(["POST"])
def eripay_webhook(request):
    environment = request.headers.get('X-Environment', 'production')
    signature = request.headers.get('X-Signature', '')
    
    # Get appropriate secret based on environment
    secret = get_secret_for_environment(environment)
    
    # Verify signature
    if not verify_signature(request.body, signature, secret):
        logger.warning('EriPay webhook signature verification failed', extra={
            'environment': environment
        })
        
        return JsonResponse({'error': 'Invalid signature'}, status=401)
    
    try:
        payload = json.loads(request.body)
        
        # Handle based on environment
        if environment == ENVIRONMENT_MODE['SANDBOX']:
            handle_sandbox_webhook(payload)
        else:
            handle_production_webhook(payload)
        
        return JsonResponse({'status': 'processed'})
    
    except Exception as e:
        logger.error(f'Webhook processing error:{str(e)}')
        return JsonResponse({'error': 'Processing failed'}, status=500)

def get_secret_for_environment(environment):
    from django.conf import settings
    
    # Return test secret for sandbox, live secret for production
    return (settings.ERIPAY_TEST_WEBHOOK_SECRET 
            if environment == 'sandbox' 
            else settings.ERIPAY_WEBHOOK_SECRET)

def verify_signature(payload, signature, secret):
    if not signature:
        return False
    
    expected_signature = hmac.new(
        secret.encode('utf-8'),
        payload,
        hashlib.sha256
    ).hexdigest()
    provided_signature = signature[7:] if signature.startswith('sha256=') else signature
    
    return hmac.compare_digest(expected_signature, provided_signature)

def handle_sandbox_webhook(payload):
    logger.info('Processing sandbox webhook', extra=payload)
    
    # Your sandbox-specific logic here
    # Don't fulfill orders, don't send emails to real customers, etc.

def handle_production_webhook(payload):
    logger.info('Processing production webhook', extra=payload)
    
    # Your production logic here
    # Fulfill orders, send confirmation emails, etc.

Environment-Specific Best Practices

Sandbox Webhooks
  • Use for testing webhook integration
  • No real money transactions
  • Don't fulfill actual orders
  • Don't send emails to real customers
  • Use test webhook secret for verification
Production Webhooks
  • Process real customer orders
  • Send confirmation emails
  • Update inventory systems
  • Trigger fulfillment processes
  • Use production webhook secret for verification

Integration Examples

Production-oriented integration examples for popular platforms and frameworks. Keep gateway selection in Merchant API Config, then sign each API request from your server.

Environment Configuration: Replace {environment} with sandbox or production, and use corresponding credentials - test_ prefix for sandbox, no prefix for production in your configuration files.
Latest Checkout Rules The requested currency must match the merchant setup and active wallet. Gateway visibility is controlled from Merchant API Config; allow_payment_methods only narrows the already eligible gateway list.
Signature Required Examples should include X-Timestamp and X-Signature generated with the API Secret for the selected sandbox or production environment. See Authentication for the exact signature payload.
<?php
// Laravel Integration Service
namespace App\Services;

use Illuminate\Support\Facades\Http;
use Exception;

class EriPayService
{
    private string $baseUrl;
    private string $merchantKey;
    private string $apiKey;
    private string $environment;

    public function __construct()
    {
        $this->baseUrl = config('eripay.base_url');
        $this->merchantKey = config('eripay.merchant_key');
        $this->apiKey = config('eripay.api_key');
        $this->environment = config('eripay.environment'); // 'sandbox' or 'production'
    }

    public function initiatePayment(array $paymentData): array
    {
        try {
            $response = Http::withHeaders([
                'Content-Type' => 'application/json',
                'X-Environment' => $this->environment,
                'X-Merchant-Key' => $this->merchantKey,
                'X-API-Key' => $this->apiKey,
            ])->post("{$this->baseUrl}/api/v1/initiate-payment", $paymentData);

            if ($response->successful()) {
                return $response->json();
            }

            throw new Exception('EriPay API Error: Payment initiation failed');
        } catch (Exception $e) {
            throw new Exception('EriPay API Error: ' . $e->getMessage());
        }
    }

    public function verifyPayment(string $transactionId): array
    {
        try {
            $response = Http::withHeaders([
                'Accept' => 'application/json',
                'X-Environment' => $this->environment,
                'X-Merchant-Key' => $this->merchantKey,
                'X-API-Key' => $this->apiKey,
            ])->get("{$this->baseUrl}/api/v1/verify-payment/{$transactionId}");

            if ($response->successful()) {
                return $response->json();
            }

            throw new Exception('EriPay API Error: Payment verification failed');
        } catch (Exception $e) {
            throw new Exception('EriPay API Error: ' . $e->getMessage());
        }
    }
}

// Configuration (config/eripay.php)
return [
    'base_url' => env('ERIPAY_BASE_URL', 'https://eripays.com'),
    'environment' => env('ERIPAY_ENVIRONMENT', 'sandbox'), // sandbox or production
    'merchant_key' => env('ERIPAY_MERCHANT_KEY'), // Use appropriate prefix
    'api_key' => env('ERIPAY_API_KEY'), // Use appropriate prefix
];

// Usage in Controller
class PaymentController extends Controller
{
    public function initiatePayment(Request $request, EriPayService $eripay)
    {
        $paymentData = [
            'payment_amount' => $request->amount,
            'currency_code' => 'USD',
            'ref_trx' => 'ORDER_' . time(),
            'description' => $request->description,
            'success_redirect' => route('payment.success'),
            'cancel_redirect' => route('payment.cancelled'),
            'ipn_url' => route('webhooks.eripay'),
            'allow_payment_methods' => ['stripe', 'paypal'],
        ];

        try {
            $result = $eripay->initiatePayment($paymentData);
            return redirect($result['payment_url']);
        } catch (Exception $e) {
            return back()->withErrors(['error' => $e->getMessage()]);
        }
    }
}
// Node.js Integration Service
const axios = require('axios');

class EriPayService {
    constructor() {
        this.baseUrl = process.env.ERIPAY_BASE_URL || 'https://eripays.com';
        this.environment = process.env.ERIPAY_ENVIRONMENT || 'sandbox'; // sandbox or production
        this.merchantKey = process.env.ERIPAY_MERCHANT_KEY; // Use appropriate prefix
        this.apiKey = process.env.ERIPAY_API_KEY; // Use appropriate prefix
    }

    async initiatePayment(paymentData) {
        try {
            const response = await axios.post(`${this.baseUrl}/api/v1/initiate-payment`, paymentData, {
                headers: {
                    'Content-Type': 'application/json',
                    'X-Environment': this.environment,
                    'X-Merchant-Key': this.merchantKey,
                    'X-API-Key': this.apiKey
                }
            });

            return response.data;
        } catch (error) {
            throw new Error(`EriPay API Error: ${error.message}`);
        }
    }

    async verifyPayment(transactionId) {
        try {
            const response = await axios.get(`${this.baseUrl}/api/v1/verify-payment/${transactionId}`, {
                headers: {
                    'Accept': 'application/json',
                    'X-Environment': this.environment,
                    'X-Merchant-Key': this.merchantKey,
                    'X-API-Key': this.apiKey
                }
            });

            return response.data;
        } catch (error) {
            throw new Error(`EriPay API Error: ${error.message}`);
        }
    }
}

// Express.js Route Example
const express = require('express');
const app = express();
const eripay = new EriPayService();

app.post('/initiate-payment', async (req, res) => {
    const paymentData = {
        payment_amount: req.body.amount,
        currency_code: 'USD',
        ref_trx: `ORDER_${Date.now()}`,
        description: req.body.description,
        success_redirect: `${req.protocol}://${req.get('host')}/payment/success`,
        cancel_redirect: `${req.protocol}://${req.get('host')}/payment/cancelled`,
        ipn_url: `${req.protocol}://${req.get('host')}/webhooks/eripay`,
        allow_payment_methods: ['stripe', 'paypal'],
    };

    try {
        const result = await eripay.initiatePayment(paymentData);
        res.redirect(result.payment_url);
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
});

module.exports = EriPayService;
# Python/Django Integration Service
import os
import requests
from django.conf import settings

class EriPayService:
    def __init__(self):
        self.base_url = getattr(settings, 'ERIPAY_BASE_URL', 'https://eripays.com')
        self.environment = getattr(settings, 'ERIPAY_ENVIRONMENT', 'sandbox')  # sandbox or production
        self.merchant_key = getattr(settings, 'ERIPAY_MERCHANT_KEY')  # Use appropriate prefix
        self.api_key = getattr(settings, 'ERIPAY_API_KEY')  # Use appropriate prefix

    def initiate_payment(self, payment_data):
        try:
            headers = {
                'Content-Type': 'application/json',
                'X-Environment': self.environment,
                'X-Merchant-Key': self.merchant_key,
                'X-API-Key': self.api_key
            }

            response = requests.post(
                f"{self.base_url}/api/v1/initiate-payment",
                headers=headers,
                json=payment_data,
                timeout=30
            )

            response.raise_for_status()
            return response.json()

        except requests.RequestException as e:
            raise Exception(f'EriPay API Error: {str(e)}')

    def verify_payment(self, transaction_id):
        try:
            headers = {
                'Accept': 'application/json',
                'X-Environment': self.environment,
                'X-Merchant-Key': self.merchant_key,
                'X-API-Key': self.api_key
            }

            response = requests.get(
                f"{self.base_url}/api/v1/verify-payment/{transaction_id}",
                headers=headers,
                timeout=30
            )

            response.raise_for_status()
            return response.json()

        except requests.RequestException as e:
            raise Exception(f'EriPay API Error: {str(e)}')

# Django Settings Configuration
ERIPAY_BASE_URL = 'https://eripays.com'
ERIPAY_ENVIRONMENT = 'sandbox'  # Change to 'production' for live
ERIPAY_MERCHANT_KEY = os.environ.get('ERIPAY_MERCHANT_KEY')  # Use appropriate prefix
ERIPAY_API_KEY = os.environ.get('ERIPAY_API_KEY')  # Use appropriate prefix

# Django View Example
from django.shortcuts import redirect
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
import json

eripay = EriPayService()

@csrf_exempt
def initiate_payment(request):
    if request.method == 'POST':
        data = json.loads(request.body)
        
        payment_data = {
            'payment_amount': data['amount'],
            'currency_code': 'USD',
            'ref_trx': f'ORDER_{int(time.time())}',
            'description': data['description'],
            'success_redirect': request.build_absolute_uri('/payment/success/'),
            'cancel_redirect': request.build_absolute_uri('/payment/cancelled/'),
            'ipn_url': request.build_absolute_uri('/webhooks/eripay/'),
            'allow_payment_methods': ['stripe', 'paypal'],
        }

        try:
            result = eripay.initiate_payment(payment_data)
            return redirect(result['payment_url'])
        except Exception as e:
            return JsonResponse({'error': str(e)}, status=500)
# Environment Variables Setup
export ERIPAY_ENVIRONMENT="sandbox"  # or "production"
export ERIPAY_MERCHANT_KEY="test_merchant_your_key"  # or "merchant_your_key" for production
export ERIPAY_API_KEY="test_your_api_key"  # or "your_api_key" for production

# Initiate Payment
curl -X POST "https://eripays.com/api/v1/initiate-payment" \
  -H "Content-Type: application/json" \
  -H "X-Environment: $ERIPAY_ENVIRONMENT" \
  -H "X-Merchant-Key: $ERIPAY_MERCHANT_KEY" \
  -H "X-API-Key: $ERIPAY_API_KEY" \
  -d '{
    "payment_amount": 250.00,
    "currency_code": "USD",
    "ref_trx": "ORDER_12345",
    "description": "Premium Subscription",
    "success_redirect": "https://yoursite.com/payment/success",
    "cancel_redirect": "https://yoursite.com/payment/cancelled",
    "ipn_url": "https://yoursite.com/api/webhooks/eripay",
    "allow_payment_methods": ["stripe", "paypal"]
  }'

# Verify Payment
curl -X GET "https://eripays.com/api/v1/verify-payment/TXNQ5V8K2L9N3XM1" \
  -H "Accept: application/json" \
  -H "X-Environment: $ERIPAY_ENVIRONMENT" \
  -H "X-Merchant-Key: $ERIPAY_MERCHANT_KEY" \
  -H "X-API-Key: $ERIPAY_API_KEY"

# Environment-specific credential examples:
# Sandbox: test_merchant_xxxxx, test_api_key_xxxxx
# Production: merchant_xxxxx, api_key_xxxxx

WooCommerce Integration

Advanced EriPay payment gateway with modern WooCommerce Blocks support, dynamic branding, and enterprise-grade security features.

Advanced WooCommerce Integration

Production-ready payment gateway with WooCommerce Blocks (Gutenberg) support, dynamic branding, and secure webhook processing.

3 Minutes Setup
99.9% Uptime
24/7 Webhook Support
Latest Plugin Download

Enterprise-grade WooCommerce payment gateway with modern Blocks support and dynamic branding.

Plugin Size: 45.2 KB
Version: 2.8.0
Last Updated: Nov 04, 2026
System Requirements
  • WordPress 5.8+
  • WooCommerce 6.0+
  • PHP 8.1+ (8.2+ Recommended)
  • SSL Certificate (Required)
  • EriPay Merchant Account
  • WooCommerce Blocks Support
Production Ready

Advanced Features

Enterprise-grade payment processing with modern architecture

WooCommerce Blocks

Full Gutenberg checkout compatibility with React-based UI

Dynamic Branding

Auto-fetch logo, colors, and branding from EriPay API

Secure Webhooks

HMAC-SHA256 signature verification for payment callbacks

Compact Mobile UI

Space-efficient, responsive design for all devices

Advanced Security

Multi-header authentication with environment isolation

Test/Live Mode

Seamless sandbox testing with production deployment

Quick Installation Guide

Get started with EriPay WooCommerce integration in minutes

1
Download Latest Plugin

Download EriPay WooCommerce Gateway v2.8.0 from the download section above. This includes all latest features and security updates.

2
Install via WordPress Admin

Navigate to Plugins → Add New → Upload Plugin and select the downloaded ZIP file. The plugin will auto-extract and install.

3
Activate & Configure

Activate the plugin and go to WooCommerce → Settings → Payments → EriPay. Enter your API credentials and webhook secret.

4
Test Integration

Enable Test Mode, process a sandbox transaction to verify Blocks checkout, webhook delivery, and order completion.

5
Go Live

Disable test mode, ensure production API keys are configured, and start accepting real payments with full webhook processing.

API Configuration

Essential API settings for secure payment processing

API Base URL

https://eripays.com

Auto-configured
Merchant ID & API Key

Your unique merchant credentials from EriPay dashboard

Required
Webhook Secret

HMAC-SHA256 signature verification for secure callbacks

Recommended
Authentication Headers

Required headers for all EriPay API requests:

X-Environment: sandbox|production
X-Merchant-Key: your_merchant_id
X-API-Key: your_api_key
Content-Type: application/json

Webhook Configuration

Real-time payment status updates and order processing

Webhook Endpoint
https://yoursite.com/wc-api/eripay_webhook

Configure this URL in your EriPay merchant dashboard for automatic order updates.

Supported Events
  • Payment Success
  • Payment Failed
  • Payment Cancelled
  • Payment Pending
  • Refund Processed
  • Payment Timeout

WooCommerce Blocks Integration

Modern Gutenberg checkout with React-based payment UI

Responsive Design

Compact, mobile-optimized payment interface that adapts to any screen size.

Dynamic Branding

Automatically fetches and displays your EriPay branding and logos.

Security Indicators

Clear SSL and security badges to build customer trust during checkout.

Test Mode Support

Clear sandbox indicators for testing without affecting live transactions.

Production Deployment Checklist

Ensure everything is configured correctly before going live

Technical Requirements
API Configuration
Final Verification

Troubleshooting

Common issues and solutions for EriPay WooCommerce integration

Payment method not showing in checkout

Solutions:

  • Verify plugin is activated and enabled in WooCommerce → Settings → Payments
  • Clear browser cache and WooCommerce cache
  • Check if API credentials are correctly configured
  • Ensure SSL certificate is properly installed
401 Unauthorized API errors

Solutions:

  • Verify Merchant ID and API Key are correct
  • Ensure environment (sandbox/production) matches your credentials
  • Check that all required headers are being sent
  • Contact EriPay support to verify account status
Orders not updating after payment

Solutions:

  • Verify webhook URL is configured in EriPay dashboard
  • Check webhook secret key matches plugin configuration
  • Review WordPress error logs for webhook processing errors
  • Test webhook delivery using EriPay dashboard tools
Release Readiness Sandbox first, production after approval

Sandbox & Go Live Checklist

Use this checklist before moving from test payments to live checkout. The same API routes work in both modes; only the environment header and credential set change.

Sandbox

Use test credentials and X-Environment: sandbox. Transactions are marked as sandbox and do not represent real money movement.

  • Generate or copy test Merchant ID, API Key, and API Secret.
  • Send signed API requests with the sandbox secret.
  • Test success, cancel, pending, failed, webhook, and verify flows.

Production

Use live credentials and X-Environment: production only after admin approval, wallet readiness, and gateway configuration are complete.

  • Merchant status must be approved.
  • Every live currency must have an active merchant wallet.
  • Payment Gateway Controls should contain only gateways you want customers to see.
Production Launch Checks Required before live traffic
Review Config
Approved merchant Production API returns 403 until admin approval is complete.
Server-side signing Each request includes X-Timestamp and X-Signature generated with the matching API secret.
Wallet coverage Each merchant currency has an active receiver wallet.
Gateway coverage Selected gateways match the currencies customers will use.
Redirect URLs success_redirect and cancel_redirect are HTTPS and handle repeated visits safely.
IPN verification Webhook signature is verified before fulfillment or wallet-side order updates.
Important Never switch only the X-Environment header. Always switch the Merchant ID, API Key, and API Secret together so the environment and credential set match.

Interactive API Testing

Test EriPay API endpoints directly from this documentation. Use the demo credentials below for sandbox testing.

Demo Payment Information SANDBOX MODE

Use these demo credentials to test all payment methods in sandbox environment:

Demo Wallet
Wallet ID: 123456789 Wallet PIN: 123456
Auto-approved in sandbox
Demo Voucher
Voucher Code: TESTVOUCHER
Instant redemption
Gateway Payment
Behavior: Auto Success
No external redirection
Testing Guidelines
  • Environment Header: Always include X-ENVIRONMENT: sandbox in your API requests
  • Demo Credentials: Use the provided demo wallet/voucher codes for testing payment flows
  • Sandbox Behavior: All payments auto-complete successfully without real money processing
  • Gateway Controls: Hosted checkout respects the gateways configured from Merchant API Config for the selected currency.
  • Transaction Status: Sandbox transactions are marked with "SANDBOX_TRANSACTION" in remarks
  • IPN Notifications: Webhook notifications work normally in sandbox mode
Environment Setup: Use sandbox for testing and production for live transactions. Only sandbox credentials use test_ prefix, production credentials have no prefix.
API Testing Console
Authentication Headers
Sandbox: test_*, Production: no prefix
Sandbox: test_*, Production: no prefix
Used locally to generate X-Signature. Prefer sandbox secrets in the browser console.
Request Parameters
Currency code must be uppercase (e.g. USD, EUR, BDT). You must use the currency that matches your merchant shop setup.
Limit checkout methods by name. Accepts CSV string or JSON array. Case-insensitive.
Sandbox Environment

Base URL: https://eripays.com

Environment Header: X-Environment: sandbox

Credentials: Use test_ prefixed keys

Purpose: Safe testing without real money

Production Environment

Base URL: https://eripays.com

Environment Header: X-Environment: production

Credentials: No prefix for production keys

Purpose: Live transactions with real money

Error Codes

EriPay API uses conventional HTTP response codes to indicate the success or failure of API requests.

HTTP Status Codes

Code Status Description
200 OK Request succeeded
400 Bad Request Invalid request parameters
401 Unauthorized Invalid or missing API credentials
403 Forbidden Insufficient permissions
404 Not Found Resource not found
429 Too Many Requests Rate limit exceeded
500 Internal Server Error Server error occurred

API Error Codes

Error Code Description Solution
INVALID_CREDENTIALS Invalid API credentials provided Check your Merchant ID and API Key
INSUFFICIENT_FUNDS Customer has insufficient funds Customer needs to add funds to their wallet
PAYMENT_DECLINED Payment was declined by payment processor Customer should try a different payment method
INVALID_AMOUNT Payment amount is invalid Check minimum and maximum amount limits
INVALID_CURRENCY Unsupported currency code Use a supported currency code (USD, EUR, etc.)
DUPLICATE_REFERENCE Transaction reference already exists Use a unique transaction reference
EXPIRED_SESSION Payment session has expired Create a new payment request
MERCHANT_SUSPENDED Merchant account is suspended Contact EriPay support

Error Response Format

{
  "success": false,
  "message": "Validation failed",
  "error_code": "INVALID_AMOUNT",
  "errors": {
    "payment_amount": [
      "The payment amount must be at least 1.00"
    ]
  },
  "timestamp": "2024-01-20T10:30:00Z"
}
Error Handling Always check the success field in API responses and handle errors appropriately in your application.

Support

Technical Support

Need assistance with EriPay API integration? Our technical team provides comprehensive support.

Support Hours: 24/7 for critical issues