A
AakashPayDeveloper Documentation
Production API v1.0

AakashPay API Docs

Create payment orders, open hosted bKash/Nagad/Upay checkout, verify Transaction IDs, and connect SMS Reader devices through one production-ready API.

Base URL: akashpay-api.axura.workers.devJSON APIBackend-first security
Live environment: All examples in this guide target https://akashpay-api.axura.workers.dev. Keep API keys and device credentials on trusted backend infrastructure.

At a glance

Environment Base URL
Production https://akashpay-api.axura.workers.dev
Capability Method Endpoint Authentication
Service health GET /v1/health None
Configured gateways GET /v1/gateways X-API-Key
Create payment POST /v1/payment/create X-API-Key
Check payment GET /v1/payment/{orderId} X-API-Key
Public checkout status GET /v1/public/payment/{orderId} Order ID bearer
Customer Transaction ID verification POST /v1/public/payment/{orderId}/verify Order ID bearer
Device registration POST /v1/public/devices/register None on initial registration
SMS logs GET /v1/public/logs/{clientId} X-Device-ID
Gateway numbers GET/PATCH /v1/public/settings/{clientId}/numbers X-Device-ID
API-key management GET/POST /v1/public/settings/{clientId}/apikey… X-Device-ID
Owner monitoring GET /admin/overview X-Admin-Token

AakashPay currently supports the gateway identifiers bkash, nagad, and upay. An order remains valid for 15 minutes after creation. The payment system first attempts automatic verification from the configured SMS Reader scope; the hosted checkout can later accept a customer-supplied Transaction ID as a fallback.

Overview

AakashPay is designed for applications that collect payments through Bangladeshi mobile-finance gateways. The integrator creates an order from a trusted backend, receives a hosted portalUrl, and gives that URL to the customer. The customer completes payment using the displayed gateway number and follows the branded checkout instructions. The integrator then checks the authenticated order status and fulfils the order only after status becomes paid.

The customer-facing portal is separate from the backend API. It displays only customer-safe information and never exposes internal SMS-processing terminology.

Core payment flow

Step Action Result
1 Configure a client gateway number. bKash, Nagad, or Upay becomes available.
2 Create an order from your backend. A pending order and hosted portalUrl are returned.
3 Redirect or send the customer to portalUrl. The customer sees the mobile checkout.
4 Customer pays to the displayed number. SMS Reader captures the payment record.
5 Poll the authenticated order endpoint. Automatic matching can change the order to paid.
6 If required, customer submits a Transaction ID. The fallback matcher checks the order payment record.
7 Fulfil only after paid. Duplicate fulfilment is prevented by your application.

Quick Start

1. Store your API key securely

Every backend request to the client payment API must include the API key in the X-API-Key header. Keep it in an environment variable and never place it in browser JavaScript, a public mobile bundle, or a customer checkout page.

export AAKASHPAY_API_KEY='ak_live_REPLACE_WITH_YOUR_KEY'

2. Create an order

curl -X POST 'https://akashpay-api.axura.workers.dev/v1/payment/create' \
  -H 'Content-Type: application/json' \
  -H "X-API-Key: $AAKASHPAY_API_KEY" \
  -d '{
    "amount": 100,
    "userId": "member_42",
    "gateway": "bkash"
  }'
{
  "ok": true,
  "orderId": "ord_abc123",
  "gateway": "bkash",
  "number": "017XXXXXXXX",
  "amount": 100,
  "status": "pending",
  "expiresAt": 1776700900000,
  "portalUrl": "https://akashpay-api.axura.workers.dev/pay/ord_abc123"
}

3. Send the checkout URL to the customer

Use the returned portalUrl as the payment link. Do not construct the portal URL yourself when the API has already returned it.

4. Confirm payment from your backend

curl -sS \
  -H "X-API-Key: $AAKASHPAY_API_KEY" \
  'https://akashpay-api.axura.workers.dev/v1/payment/ord_abc123'

Treat the order as paid only when the returned status is exactly paid.

Authentication

Client API authentication

Use the following header for /v1/gateways, /v1/payment/create, /v1/payment/{orderId}, and /v1/balance/{userId}:

X-API-Key: ak_live_REPLACE_WITH_YOUR_KEY

A missing key returns 401 missing_api_key. An invalid key returns 401 invalid_api_key. A locked key returns 403 client_suspended. If a daily usage limit is configured and reached, the API returns 429 usage_limit_reached.

SMS Reader device authentication

The Android SMS Reader app uses:

X-Device-ID: android-device-123

This header is required for device-scoped settings, logs, and API-key management after registration.

Owner and internal authentication

Owner administration endpoints use X-Admin-Token. Internal matching uses X-System-Key. These credentials must remain on trusted server infrastructure.

API response format

Success responses use ok: true:

{ "ok": true, "data": {} }

Errors use a stable code suitable for application logic:

{
  "ok": false,
  "error": "Missing X-API-Key header",
  "code": "missing_api_key"
}

Create Payment

POST /v1/payment/create

Create a pending payment order and receive its hosted checkout URL.

Authentication: X-API-Key
Success status: 201 Created

Request fields

Field Type Required Rules
amount number Yes Must be greater than zero.
userId string Yes Your customer, member, or invoice reference.
gateway string Yes bkash, nagad, or upay.

Request

{
  "amount": 1200,
  "userId": "customer_9001",
  "gateway": "nagad"
}

Response

{
  "ok": true,
  "orderId": "ord_msvo0rrw37a069d4fd38",
  "gateway": "nagad",
  "number": "018XXXXXXXX",
  "amount": 1200,
  "status": "pending",
  "expiresAt": 1776700900000,
  "portalUrl": "https://akashpay-api.axura.workers.dev/pay/ord_msvo0rrw37a069d4fd38"
}

Possible errors

Status Code Meaning
400 invalid_amount Amount is missing, non-numeric, or not positive.
400 invalid_user_id userId is missing or not a string.
400 invalid_gateway Gateway is not supported.
403 device_blocked The client device has been blocked.
409 gateway_not_configured The selected gateway has no configured number.

Check Payment

GET /v1/payment/{orderId}

Return the authenticated client’s order status. The API attempts automatic matching before returning the order.

Authentication: X-API-Key

curl -sS \
  -H 'X-API-Key: ak_live_REPLACE_WITH_YOUR_KEY' \
  'https://akashpay-api.axura.workers.dev/v1/payment/ord_abc123'

Response fields

Field Type Description
orderId string AakashPay order identifier.
gateway string Gateway used by the order.
amount number Required payment amount.
number string Configured receiving number.
status string pending, paid, expired, or cancelled.
trxId string/null Matched Transaction ID, if available.
createdAt number Creation time in epoch milliseconds.
expiresAt number Expiration time in epoch milliseconds.
verifiedAt number/null Verification time, if paid.
userId string Returned only to authenticated client calls.

Status values

Status Meaning Recommended action
pending Payment is not yet verified. Continue polling until expiration.
paid Payment has been verified. Fulfil once and stop polling.
expired The 15-minute order window has ended. Do not fulfil; create a new order if necessary.
cancelled Order was cancelled operationally. Do not fulfil.

Verify Payment

AakashPay has two public endpoints used by the hosted checkout.

Public status

GET /v1/public/payment/{orderId}

This endpoint requires no API key. The orderId itself acts as the bearer token, so treat a checkout URL as sensitive. The response omits the private userId field.

curl -sS \
  'https://akashpay-api.axura.workers.dev/v1/public/payment/ord_abc123'

Manual Transaction ID verification

POST /v1/public/payment/{orderId}/verify

Submit a Transaction ID when the customer reaches the manual verification step in the checkout.

curl -X POST \
  -H 'Content-Type: application/json' \
  -d '{"trxId":"DHG6IB84FK"}' \
  'https://akashpay-api.axura.workers.dev/v1/public/payment/ord_abc123/verify'

The endpoint accepts a plain ID or a labelled value such as TrxID: DHG6IB84FK. The ID must contain 6–81 permitted alphanumeric or punctuation characters after normalization.

A successful match returns the public paid-order object. If the ID is valid but is not yet available or does not match the order, the endpoint returns:

{
  "ok": false,
  "error": "Transaction ID is not available in the AakashPay system yet, or does not match this order",
  "code": "transaction_not_verified"
}

The verification decision is based on the payment record scoped to the client’s configured SMS Reader architecture and the order’s payment details. Customer-facing screens do not reveal internal SMS-processing terminology.

Admin manual verification

POST /admin/orders/{orderId}/manual-verify

Authentication: X-Admin-Token.

{ "trxId": "DHG6IB84FK" }

This endpoint is for owner operations and returns whether the submitted ID matched the order.

Poll the authenticated status endpoint every 3–5 seconds. Stop when the status becomes terminal. Do not fulfil on the basis of a browser redirect, a customer screenshot, or a pending response.

async function waitForPaid(orderId, apiKey) {
  const base = 'https://akashpay-api.axura.workers.dev';

  while (true) {
    const response = await fetch(`${base}/v1/payment/${encodeURIComponent(orderId)}`, {
      headers: { 'X-API-Key': apiKey }
    });
    const result = await response.json();

    if (!response.ok) {
      throw new Error(`${result.code}: ${result.error}`);
    }
    if (['paid', 'expired', 'cancelled'].includes(result.status)) {
      return result;
    }
    await new Promise(resolve => setTimeout(resolve, 5000));
  }
}

SMS Reader Device API

Register a device

POST /v1/public/devices/register

Register an Android SMS Reader device. Supplying an existing server-issued clientId binds the device to that client. Legacy installs can omit clientId and receive a generated client identifier.

{
  "deviceId": "android-device-123",
  "deviceName": "Payment Reader Phone",
  "clientId": "client_a1b2c3"
}

Example response:

{
  "ok": true,
  "clientId": "client_a1b2c3",
  "created": true,
  "apiCreated": true,
  "apiKey": "ak_live_NEW_SECRET"
}

Store a newly returned API key immediately. It is not safe to publish it in the WebView frontend.

Get or update gateway numbers

GET /v1/public/settings/{clientId}/numbers

Authentication: X-Device-ID.

{ "ok": true, "numbers": { "bkash": "017XXXXXXXX", "nagad": "018XXXXXXXX" } }

PATCH /v1/public/settings/{clientId}/numbers

{
  "numbers": {
    "bkash": "017XXXXXXXX",
    "nagad": "018XXXXXXXX",
    "upay": "013XXXXXXXX"
  }
}

Bangladeshi mobile numbers are validated against the 01[3-9]XXXXXXXX format.

Read and clear SMS logs

GET /v1/public/logs/{clientId}

Returns logs scoped to the authenticated device. The response also identifies whether logs came directly from the client scope or from the compatibility nested-log scan.

{ "ok": true, "logs": [], "source": "client" }

DELETE /v1/public/logs/{clientId}

{ "ok": true, "cleared": true }

Manage the linked API key

Method Endpoint Purpose
GET /v1/public/settings/{clientId}/apikey Read current key metadata.
POST /v1/public/settings/{clientId}/apikey/lock Suspend the key.
POST /v1/public/settings/{clientId}/apikey/unlock Reactivate the key.
POST /v1/public/settings/{clientId}/apikey/revoke Generate a replacement key.

All four endpoints require X-Device-ID. A revoke operation invalidates the previous key.

Gateways and checkout assets

GET /v1/gateways

Returns only the active gateway numbers configured for the authenticated client.

{
  "ok": true,
  "gateways": [
    { "id": "bkash", "name": "bKash", "number": "017XXXXXXXX" },
    { "id": "nagad", "name": "Nagad", "number": "018XXXXXXXX" }
  ]
}

The hosted portal and self-hosted assets are available at:

Resource URL
Checkout portal https://akashpay-api.axura.workers.dev/pay/{orderId}
bKash instructions https://akashpay-api.axura.workers.dev/assets/bkash-personal.jpg
Nagad instructions https://akashpay-api.axura.workers.dev/assets/nagad-personal.jpg
Nagad logo https://akashpay-api.axura.workers.dev/assets/nagad-logo.png

Merchant and Owner APIs

These routes power the merchant dashboard and owner admin panel. They must not be called directly from untrusted customer code.

Merchant authentication

Method Endpoint Purpose
POST /auth/request-link Request a merchant magic link.
GET /auth/verify Verify a magic-link token.
GET /merchant/me Read the authenticated merchant profile.
POST /merchant/link-client Link a merchant account to a client.
POST /merchant/regenerate-key Regenerate a merchant-linked key.
POST /merchant/plan Change a merchant plan.

Owner operations

Method Endpoint Purpose
GET /admin/overview Read clients, orders, logs, and verification overview.
PATCH /admin/orders/{orderId} Edit status, trxId, or note.
DELETE /admin/orders/{orderId} Delete an order.
POST /admin/orders/{orderId}/manual-verify Match an order using an admin-supplied Transaction ID.
POST /admin/orders/bulk-delete Delete up to 200 orders.
PATCH /admin/logs/{clientId}/{logId} Edit selected SMS-log fields.
DELETE /admin/logs/{clientId}/{logId} Delete one SMS log.
POST /admin/logs/bulk-delete Delete up to 200 SMS logs.
POST /admin/devices/{clientId}/status Reject or restore a device.

Client management

Method Endpoint Purpose
GET/POST /admin/clients List or create clients.
PATCH/DELETE /admin/clients/{clientId} Update or delete a client.
POST /admin/clients/link Link an app client.
POST /admin/clients/{clientId}/status Change client status.
POST /admin/clients/{clientId}/regenerate-key Regenerate a client API key.
GET /admin/clients/{clientId}/orders Read client orders.
GET /admin/clients/{clientId}/profile Read the client profile.
POST/PATCH/DELETE /admin/clients/{clientId}/projects… Manage projects.
POST/PATCH/DELETE /admin/clients/{clientId}/teams… Manage teams.

Code Examples

JavaScript / Node.js

const BASE = 'https://akashpay-api.axura.workers.dev';
const API_KEY = process.env.AAKASHPAY_API_KEY;

const response = await fetch(`${BASE}/v1/payment/create`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': API_KEY
  },
  body: JSON.stringify({
    amount: 100,
    userId: 'member_42',
    gateway: 'bkash'
  })
});

const data = await response.json();
if (!response.ok) throw new Error(`${data.code}: ${data.error}`);
console.log(data.portalUrl);

PHP

<?php
$base = 'https://akashpay-api.axura.workers.dev';
$apiKey = getenv('AAKASHPAY_API_KEY');

$ch = curl_init($base . '/v1/payment/create');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'X-API-Key: ' . $apiKey,
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'amount' => 100,
        'userId' => 'member_42',
        'gateway' => 'nagad',
    ]),
]);

$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$data = json_decode($body, true);
if ($status < 200 || $status >= 300) {
    throw new RuntimeException(($data['code'] ?? 'api_error') . ': ' . ($data['error'] ?? 'Request failed'));
}

echo $data['portalUrl'];

Python

import os
import requests

BASE = "https://akashpay-api.axura.workers.dev"
response = requests.post(
    f"{BASE}/v1/payment/create",
    headers={
        "Content-Type": "application/json",
        "X-API-Key": os.environ["AAKASHPAY_API_KEY"],
    },
    json={"amount": 100, "userId": "member_42", "gateway": "nagad"},
    timeout=20,
)

payload = response.json()
response.raise_for_status()
print(payload["portalUrl"])

Webhook Flow

A webhook-style flow is a common pattern in payment documentation, but the current AakashPay Worker does not yet expose an active outbound webhook dispatcher. A webhookUrl field exists in client API settings for dashboard compatibility; setting that field alone does not deliver callbacks.

Until a versioned webhook endpoint is introduced, use this production flow:

Step Backend action
1 Create the order.
2 Save orderId, amount, gateway, and your own reference.
3 Send the returned portalUrl to the customer.
4 Poll GET /v1/payment/{orderId} every 3–5 seconds.
5 If the customer submits a Transaction ID, allow the hosted portal to call the public verification endpoint.
6 Fulfil only after authenticated status returns paid.
7 Stop polling on paid, expired, or cancelled.

Errors

HTTP Code Meaning
400 invalid_amount Amount is missing, invalid, or not positive.
400 invalid_user_id userId is missing or invalid.
400 invalid_gateway Unsupported gateway identifier.
400 invalid_trx_id Invalid Transaction ID format.
401 missing_api_key X-API-Key is missing.
401 invalid_api_key API key is not recognized.
401 unauthorized Admin/system credential is invalid.
403 client_suspended API key is locked.
403 device_rejected Device was rejected by the owner.
403 device_blocked Device is blocked from creating orders.
404 order_not_found Order does not exist in the client scope.
409 gateway_not_configured Gateway number is not configured.
409 transaction_not_verified Transaction ID is not available or does not match.
409 device_binding_conflict Client is bound to another device.
429 usage_limit_reached Daily API limit reached.
500 internal_error Unexpected server failure.

Production Checklist

Before going live, confirm the following items:

Check Requirement
API key is stored in an environment variable or server secret store.
Payment creation occurs on a trusted backend, not in public frontend code.
The returned portalUrl is sent to the customer without exposing the API key.
Your system stores orderId, amount, gateway, and your own customer reference.
Your fulfilment code accepts payment only when authenticated status is paid.
Polling stops at terminal statuses and does not create duplicate fulfilment.
Device registration and SMS log APIs use X-Device-ID securely.
Admin and system credentials are never shipped in an app or WebView.
Invalid API responses are handled using the stable code field.
You do not assume outbound webhooks are active in the current deployment.

API Limitations and implementation notes

The hosted portal’s public endpoints use the order ID as a bearer token. Anyone who obtains a complete public order URL may view that order’s customer-safe payment fields and submit a Transaction ID for that order. Keep payment links private and avoid posting them in public logs.

The current order lifetime is 15 minutes. The customer-facing manual Transaction ID fallback is part of the hosted checkout flow; client backends should still trust the authenticated order-status endpoint as the final fulfilment authority.

The API key has a daily usage check when a non-zero usage limit is configured. A missing or zero limit is treated as unlimited by the current Worker implementation.

Support and source references

This document is aligned with the deployed Worker route table and implementation rather than with a hypothetical future webhook contract.