Build
API reference
The complete charge → verify → refund lifecycle with brand-scoped keys, request fields, response shapes, rate limits and error codes.
12 min read
Base URL
Every endpoint is relative to the domain that serves your checkout — the cloud address for hosted workspaces, or your own domain when self-hosted. Requests and responses are JSON over HTTPS, and errors use the matching HTTP status code.
Three endpoints do the work: POST /api/charge, POST /api/verify-payment and POST /api/refund-payment. Webhooks are delivered to the URL you configure, and the device bridge uses POST /api/device/ingest with a device token instead of an API key.
POST /api/charge create an invoice and payment URL
POST /api/verify-payment check the final state of an invoice
POST /api/refund-payment record a full or partial refund
POST /api/device/ingest forward an SMS (device token, not API key)Authentication
Every request uses a brand-scoped API key. Create keys in Developers → API keys; each key can be revoked independently and records when it was last used.
The header is RT-TAKAFLOW-API-KEY. For convenience the API also accepts x-api-key or Authorization: Bearer <key>.
RT-TAKAFLOW-API-KEY: tf_live_xxxxxxxxxxxxxxxx
Content-Type: application/jsonRate limits
- Create charge — 60 requests per minute per key.
- Verify payment — 120 requests per minute per key.
- Refund — 30 requests per minute per key.
- Device ingest — 120 messages per minute per device.
- Exceeding a limit returns 429 with Retry-After and X-RateLimit-Limit / X-RateLimit-Remaining headers. Back off and retry; do not loop.
Create a charge
- amount — required, in BDT, minimum 1. Decimals are accepted.
- full_name — customer name shown on the checkout.
- email, phone — optional customer details for the receipt and CRM record.
- description — what the customer is paying for.
- expires_in — minutes until the payment link closes (10–1440, default 60).
- metadata — object of strings or numbers, echoed on the invoice and webhook.
- redirect_url, cancel_url — where the customer lands after success or abandonment.
- webhook_url — per-invoice override for the brand webhook endpoint.
curl -X POST https://your-domain.com/api/charge \
-H "RT-TAKAFLOW-API-KEY: tf_live_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"full_name": "Nusrat Jahan",
"email": "nusrat@example.com",
"phone": "01712345678",
"amount": 1250,
"description": "Annual hosting renewal",
"expires_in": 60,
"metadata": { "order_id": "ORD-1042", "plan": "annual" },
"redirect_url": "https://shop.example.com/thanks",
"cancel_url": "https://shop.example.com/cart",
"webhook_url": "https://shop.example.com/api/takaflow"
}'Charge response
{
"status": true,
"message": "Charge created.",
"invoice_id": 128,
"invoice_number": "TF-202610-4821",
"token": "6d1c...",
"amount": "1250.00",
"payment_url": "https://your-domain.com/checkout/6d1c...",
"expires_at": "2026-10-29T20:20:11.000Z"
}Redirect the customer to payment_url, or render it as a button. invoice_id is the numeric internal id; invoice_number and token are also accepted by the verify and refund endpoints.
Verify a payment
Send invoice_id (number or number string), invoice_number or token — one value is enough. Call this from your success page and before fulfilling an order; never trust the redirect parameters on their own.
curl -X POST https://your-domain.com/api/verify-payment \
-H "RT-TAKAFLOW-API-KEY: tf_live_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "invoice_id": "TF-202610-4821" }'Verify response
- payment_status is COMPLETED, PENDING, UNPAID, REFUNDED or CANCELLED.
- Treat only COMPLETED as paid. PENDING means a TrxID was submitted but no SMS has matched yet.
- payment_id is what the refund endpoint expects; it is null when the invoice has no payment yet.
- Match metadata.order_id against your own order before fulfilling — this protects against a customer reusing another invoice's URL.
{
"status": true,
"payment_status": "COMPLETED",
"invoice_id": 128,
"invoice_number": "TF-202610-4821",
"payment_id": 910,
"transaction_id": "9F2K7D1QAX",
"sender_number": "01712345678",
"payment_method": "bkash",
"amount": "1250.00",
"fee": "0.00",
"charged_amount": "1250.00",
"metadata": { "order_id": "ORD-1042" },
"paid_at": "2026-10-29T14:20:11.000Z"
}Refund a payment
payment_id is the numeric id returned by verify-payment. amount is optional and defaults to the full remaining balance; partial and repeated refunds are supported. NaklaPay records the refund and fires payment.refunded. Because funds live in your MFS account, the actual money movement is yours to perform; the record keeps the audit trail complete.
curl -X POST https://your-domain.com/api/refund-payment \
-H "RT-TAKAFLOW-API-KEY: tf_live_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "payment_id": 910, "amount": 1250 }'Errors
- 401 — missing, invalid or revoked API key.
- 404 — invoice or payment not found on this brand.
- 409 — payment is not in a refundable state.
- 422 — validation failure; the message names the problem.
- 429 — rate limit exceeded; retry after the Retry-After delay.
- 400 — malformed JSON or a refund rejected by the balance rules.
- Errors return { "status": false, "message": "…" } with the matching HTTP code.
Testing without money
Open the public demo checkout to run the full verify loop with seeded data: submit the demo TrxID and the invoice completes through the same matching engine production uses. When you register a workspace, it also ships with sample payments, SMS records and invoices that you can clear in Settings.
Keep sandbox experiments on sample invoices. A real charge moves through your own MFS account, so test with a small amount from a second phone when you connect your first gateway.
Open the live demo