API v2 Reference
A versioned REST API for creating payments, tracking status in real time, choosing the healthiest provider and managing webhook delivery.
Base URL
https://fastpayglobal.app
Authentication
x-public-key: pk_live_…
All responses are JSON. Successful reads return a data field; failures return { "error": "message" }. Send Idempotency-Key on payment creation so retries never double-charge. CORS is open, but never ship a secret key to a browser.
The full API v2 surface is published as an OpenAPI 3.1 document. Import it into Postman, Insomnia, Swagger Editor or an SDK generator to get typed clients and a ready-made request collection.
In Postman choose Import → Link and paste https://fastpayglobal.app/api/public/openapi.json. The spec always reflects the host it is served from.
Endpoints
/api/v2/healthLive health score per payment provider. No authentication required.
Rate limit: 60 req / min / IP
curl https://fastpayglobal.app/api/v2/health{
"status": "ok",
"providers": [
{ "provider": "bkash", "health_score": 98, "success_count_1h": 49,
"failure_count_1h": 1, "avg_response_ms_1h": 820, "last_failure_at": null }
]
}/api/v2/paymentsCreates a payment and returns a hosted checkout URL. Send an Idempotency-Key header to safely retry the same request.
Rate limit: 60 req / min / IP
| Field | Type | Description |
|---|---|---|
| amount | number | Amount in major units (e.g. 10.00). |
| currency | string | ISO code, e.g. BDT or USD. Defaults to the brand currency. |
| orderId | string | Your order reference. Must be unique per payment. |
| customer | object | Optional { name, email, phone }. |
| metadata | object | Optional key/value data echoed back in webhooks. |
curl -X POST https://fastpayglobal.app/api/v2/payments \
-H "x-public-key: pk_live_xxx" \
-H "Idempotency-Key: order-123" \
-H "Content-Type: application/json" \
-d '{
"amount": 10.00,
"currency": "BDT",
"orderId": "ORDER-123",
"customer": { "name": "Customer", "email": "a@b.com", "phone": "01700000000" }
}'{
"data": {
"id": "uuid",
"orderId": "ORDER-123",
"amount": 10,
"currency": "BDT",
"status": "pending",
"hostedUrl": "https://fastpayglobal.app/pay/<id>",
"expiresAt": "2026-08-10T10:15:00Z"
}
}/api/v2/payments/:idReturns the current state of a payment. Statuses progress pending → detected → confirming → paid, or expired / failed / refunded.
Rate limit: 120 req / min / IP
curl https://fastpayglobal.app/api/v2/payments/<id> \
-H "x-public-key: pk_live_xxx"{
"data": {
"id": "uuid",
"orderId": "ORDER-123",
"amount": 10,
"currency": "BDT",
"status": "paid",
"method": "bkash",
"trxId": "TRX-XYZ",
"createdAt": "2026-08-10T10:00:00Z",
"expiresAt": "2026-08-10T10:15:00Z",
"paidAt": "2026-08-10T10:04:12Z"
}
}/api/v2/payments/:id/cancelExpires a payment that has not reached a terminal state yet.
Rate limit: 30 req / min / IP
curl -X POST https://fastpayglobal.app/api/v2/payments/<id>/cancel \
-H "x-public-key: pk_live_xxx"{ "ok": true, "status": "expired" }/api/v2/payments/:id/refundFull or partial refund of a paid payment. Omit amount to refund the full value.
Rate limit: 30 req / min / IP
| Field | Type | Description |
|---|---|---|
| amount | number | Optional partial amount in major units. |
| reason | string | Optional reason, max 500 chars. |
curl -X POST https://fastpayglobal.app/api/v2/payments/<id>/refund \
-H "x-public-key: pk_live_xxx" \
-H "Content-Type: application/json" \
-d '{ "amount": 5.00, "reason": "Customer request" }'{ "ok": true, "refundId": "uuid", "amount": 5 }/api/v2/routing/providersYour enabled payment methods ranked by health score and 1-hour success rate. Use recommended to pre-select a method and degraded to hide unreliable ones.
Rate limit: 60 req / min / IP
curl https://fastpayglobal.app/api/v2/routing/providers \
-H "x-public-key: pk_live_xxx"{
"data": [
{ "provider": "bkash", "label": "bKash Personal", "healthScore": 98,
"successRate1h": 98, "avgResponseMs1h": 820,
"degraded": false, "recommended": true },
{ "provider": "nagad", "label": "Nagad", "healthScore": 62,
"successRate1h": 60, "degraded": true, "recommended": false }
]
}/api/v2/webhooks/eventsRecent webhook deliveries for your brand. Filter with ?status=pending|failed|delivered&limit=50.
Rate limit: 60 req / min / IP
curl "https://fastpayglobal.app/api/v2/webhooks/events?status=failed&limit=20" \
-H "x-public-key: pk_live_xxx"{
"data": [
{ "id": "uuid", "eventType": "payment.succeeded", "status": "failed",
"attempts": 3, "nextAttemptAt": "2026-08-10T10:30:00Z",
"createdAt": "2026-08-10T10:00:00Z", "payload": { } }
]
}/api/v2/webhooks/retryRe-queues a pending or failed webhook event for immediate delivery.
Rate limit: 30 req / min / IP
| Field | Type | Description |
|---|---|---|
| eventId | uuid | The webhook event to retry. |
curl -X POST https://fastpayglobal.app/api/v2/webhooks/retry \
-H "x-public-key: pk_live_xxx" \
-H "Content-Type: application/json" \
-d '{ "eventId": "uuid" }'{ "ok": true, "status": "pending" }Errors
| Status | Meaning |
|---|---|
| 400 | Invalid JSON or body failed validation (details included). |
| 401 | Missing or invalid x-public-key. |
| 402 | Plan expired — renew to keep the API live. |
| 403 | Brand disabled, or caller IP not whitelisted. |
| 404 | Resource not found for this brand. |
| 409 | State conflict (already delivered, not refundable, invalid transition). |
| 429 | Rate limited — honour the Retry-After header. |
| 500 | Unexpected server error. |
Webhooks
FastPay Global POSTs signed JSON to your brand webhook URL for payment.succeeded, payment.failed, payment.expired, payment.refunded and invoice.paid. Failed deliveries retry with exponential backoff and can be replayed from the Developer Portal or the retry endpoint.
POST <your webhook url>
x-signature: <hex hmac-sha256 of the raw body>
{
"event": "payment.succeeded",
"paymentId": "uuid",
"orderId": "ORDER-123",
"amount": 10,
"currency": "BDT",
"method": "bkash",
"trxId": "TRX-XYZ",
"paidAt": "2026-08-10T10:04:12Z",
"metadata": {}
}import crypto from "crypto";
const raw = req.rawBody; // exact bytes, not re-serialized JSON
const expected = crypto.createHmac("sha256", process.env.WEBHOOK_SECRET)
.update(raw).digest("hex");
const ok = crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(req.headers["x-signature"]),
);
if (!ok) return res.status(401).end();<?php
$raw = file_get_contents('php://input');
$expected = hash_hmac('sha256', $raw, getenv('WEBHOOK_SECRET'));
if (!hash_equals($expected, $_SERVER['HTTP_X_SIGNATURE'] ?? '')) {
http_response_code(401); exit;
}import hmac, hashlib
raw = request.get_data()
expected = hmac.new(WEBHOOK_SECRET.encode(), raw, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, request.headers.get("X-Signature", "")):
abort(401)Interactive explorer
Rendered live from the OpenAPI document. Add your x-public-key to try requests against your own brand.