BankMe Developers Back to bankme.co.in
Payout API v1

Build with the BankMe Payout API

Send money from your BankMe wallet to any bank account (IMPS or NEFT) or UPI ID with one HTTPS call, and get a signed webhook when the payout settles.

Simple JSONHTTPS requests and JSON responses. Two headers for authentication.
IdempotentThe same referenceId never pays twice.
Signed webhooksHMAC-signed results, retried until you acknowledge.
Sandbox firstTest with no real money, then switch the base URL.

How it works

  1. BankMe issues you a sandbox key (pk_... and sk_...). Production keys follow after your integration is approved.
  2. Your server calls Create payout with a unique referenceId.
  3. BankMe debits your wallet and sends the money. The result comes back in the response or as a webhook.
  4. If a call times out, ask for the result with Payout status. Never retry with a new reference.

API access is issued by BankMe. Each key is tied to one wallet and one payout route, with its own per-payout and per-day limits. Contact your BankMe account manager to get your keys.

Environments

Two environments, same paths and same code.

EnvironmentBase URLDoes money move?
Sandboxhttps://sandbox.bankme.co.inNo. Results are simulated and your wallet is never debited.
Productionhttps://api.bankme.co.inYes. Your wallet is debited and the beneficiary is paid.

Keys are not shared between environments. A sandbox key does not work on production, and the other way round. Every response carries an environment field so you can confirm where you are. Use the toggle in the code panels on this page to switch the base URL in every example.

Authentication

Every request carries your key id and secret in two headers.

HeaderRequiredValue
x-api-keyYesYour key id, starts with pk_
x-api-secretYesYour secret, starts with sk_. Shown once when the key is created.
Content-TypeOn POSTapplication/json

Keep the secret on your server. Never put it in a mobile app, a web page or a public repository. If it leaks, ask BankMe to rotate it straight away.

IP allowlist

Production keys only work from the server IP addresses you give BankMe. Calls from any other address are rejected. Call GET /v1/ip from your server to see the address BankMe sees.

Rate limit

120 requests per minute per key.

Writes money

Create payout

POST/v1/payout

Send money to a bank account or UPI ID.

Request body

FieldTypeNotes
referenceIdstringRequired. Your own unique id for this payout. It is the idempotency key.
amountintegerRequired. Whole rupees, minimum 100.
beneficiaryobjectRequired. Bank or UPI, see below.
remarksstringOptional. Up to 60 characters.

Beneficiary: bank account

FieldNotes
type"bank"
nameAccount holder name. Letters, spaces and dots only.
accountNumber9 to 18 digits
ifscValid IFSC code, for example HDFC0001234
mode"IMPS" (default) or "NEFT"

Beneficiary: UPI

FieldNotes
type"upi"
nameBeneficiary name
vpaUPI ID, for example name@bank

Response

FieldMeaning
payoutIdBankMe's id for the payout
referenceIdYour reference, returned unchanged
amount, fee, totalDebitRupees. totalDebit is amount plus fee.
statuspending, processing, success or failed
utrBank reference number, filled when the payout succeeds
reasonWhy a payout failed, empty otherwise
environmentsandbox or production

Idempotency. If you send a referenceId that already exists, you get the original payout back with "duplicate": true. Nothing new is created or debited.

Debit and refund. A live payout debits amount + fee from your wallet immediately. If the payout fails, the full debit is returned to your wallet. A request that fails validation never debits anything.

Payout status

GET/v1/payout/{referenceId}

Fetch a payout by your own reference, plus the delivery state of its webhook.

Use this when a request timed out and you do not know if it arrived, or when you want to confirm a payout without waiting for the webhook. The webhook object shows status, attempts and lastError for the delivery of this payout's result.

If you are unsure whether a create call reached BankMe, call this endpoint first. Do not create a new payout with a new reference.

Wallet balance

GET/v1/balance

The current balance of the wallet your key pays from, in rupees.

Check it before large batches. In the sandbox the balance is virtual and is never debited.

Your IP address

GET/v1/ip

Returns the public IP address BankMe sees for your request. No keys needed.

Run it from your production server, then give that address to BankMe to add to your allowlist.

Limits and fees

ItemValue
Minimum per payoutRs 100
Maximum per payoutUp to Rs 2,00,000. Your key may have a lower limit.
Daily limitRs 5,00,000 by default, set per key. The day resets at midnight IST.
FeeSlab based, from Rs 10 to Rs 100 per payout, GST included. The exact fee is returned in fee.
Rate limit120 requests per minute per key

Status and error codes

Failed requests return a non-2xx status and JSON with "success": false, a code and a readable message.

CodeWhen it happens
AUTH_REQUIREDMissing, wrong or disabled key or secret, or the call came from an IP that is not allowed.
INVALID_AMOUNTAmount is not a whole number, or is below Rs 100.
INVALID_BENEFICIARYA beneficiary field is missing or badly formatted. The message names the field.
LIMIT_PER_TXNAmount is above the per-payout limit.
LIMIT_PER_DAYThe daily limit would be exceeded. The message shows what is left today.
INSUFFICIENT_BALANCEThe wallet cannot cover amount plus fee.
RAIL_UNAVAILABLEThe payout route for your key is not available right now. Try again later.
OWNER_NOT_FOUNDThe wallet owner for the key was not found. Contact BankMe.

A request that fails validation never debits your wallet. For a timeout or a network error, check Payout status before doing anything else.

Webhooks

BankMe posts the result of each payout to the HTTPS URL registered for your key. Use it instead of polling.

Events

EventSent when
payout.successA payout was paid
payout.failedA payout failed and was refunded
webhook.testA test delivery was requested

Headers on every delivery

HeaderValue
x-bankme-eventThe event name
x-bankme-timestampUnix time of the delivery
x-bankme-signaturesha256= followed by the hex HMAC-SHA256 of timestamp + "." + rawBody, keyed with your signing secret (starts with whsec_)

Delivery rules

  • Reply with any 2xx status within a few seconds to acknowledge. Anything else counts as a failure.
  • Failed deliveries are retried automatically, so you can receive the same event more than once. Make your handler idempotent by looking up the payout by referenceId.
  • The webhook URL must be https and use a public domain name. IP addresses, localhost and private networks are rejected.
  • If your firewall limits inbound traffic, allow BankMe's outbound ranges: 74.220.52.0/24 and 74.220.60.0/24.
  • A lost webhook never loses the result. Fetch it any time with Payout status.

Verify a webhook

Always check the signature before you trust a delivery.

  1. Read the raw request body as received. Do not parse and re-encode it first.
  2. Build the string timestamp + "." + rawBody.
  3. Compute HMAC-SHA256 of it with your whsec_ secret and compare with x-bankme-signature in constant time.
  4. Reject deliveries whose timestamp is more than 5 minutes old.
  5. Process the event, then reply 200.

Store your whsec_ secret in server-side configuration, never in code. If it leaks, ask BankMe to rotate it.

Send a test webhook

POST/v1/webhook/test

Sends a signed webhook.test delivery to your registered URL so you can check your handler end to end.

Works in the sandbox and in production. Your endpoint should verify the signature and reply 200 exactly as for a real event.

Sandbox testing

The sandbox behaves like production but never moves money and never debits a wallet.

You wantSend
SuccessAny valid beneficiary, for example account 123456789012
FailureA bank account number ending in 0000, or a UPI ID starting with fail. The result is failed with the reason "Sandbox: simulated failure".
DuplicateSend the same referenceId twice. The second response has "duplicate": true.

Sandbox payouts carry "environment": "sandbox" and a UTR starting with SBX. Webhooks are delivered from the sandbox too and signed the same way.

Go-live checklist

  1. Your integration passes the sandbox tests: success, failure, duplicate and webhook handling.
  2. Your API secret and webhook signing secret are in server-side configuration.
  3. Every payout uses a new, unique referenceId. You reuse one only to retry the same payout.
  4. You called GET /v1/ip from your production server and gave that IP address to BankMe.
  5. Your webhook endpoint verifies the signature and replies with 2xx.
  6. BankMe issues your production key. Change the base URL to https://api.bankme.co.in and use the production key and secret.
  7. Make a first small live payout (Rs 100) and confirm the UTR before going to volume.

Payouts are paid from your own BankMe wallet. Keep it funded before you send live payouts.