WinniePay API Reference
V1 · INR 中文English

Getting started

Use the WinniePay API to collect payments (pay-ins) and pay out to bank accounts (payouts) in India, in INR.

Conventions

  • Pay-ins: create an order, the customer pays on the checkout page or by UPI, and we send you a callback when it succeeds.
  • Payouts: pay from your available balance to a beneficiary's Indian bank account; the result arrives by callback.
  • Order numbers: merchant_order_id is yours, platform_order_id is ours. Queries take your order number; quote ours when contacting support.
  • Amounts: INR strings with up to 2 decimals, e.g. "1000.00". Never use floating-point numbers for amounts.
  • Times: ISO 8601 with time zone, e.g. 2026-11-03T12:00:00+05:30.

Before you start

Set these up under API settings in the merchant portal:

  1. Merchant number and API host are shown on the page. Endpoints are API host + /api/v1/….
  2. API key: choose its scopes when you create it. The secret is shown once; keep it on your server, never in a web page or app.
  3. Callback secret: generated when you configure callbacks, used to verify our callbacks. It is not the API secret.
  4. IP allowlist (optional): once set, only these IPs are accepted.
  5. Callback domain: the notify_url domain must be enabled first. Send it to your WinniePay contact.

API key scopes

ScopeAllows
payins:createCreate pay-ins, submit UTRs, claim missed payments
payins:readQuery pay-ins, UTRs, claims and UPI addresses
payouts:createCreate payouts
payouts:readQuery payouts and get receipts
balances:readGet balance

Requests

  • Every endpoint is an HTTPS POST with Content-Type: application/json.
  • The body is a UTF-8 JSON object holding all parameters (no query string), up to 32 KB.
  • The body must include merchant_id and sign, and no undocumented fields.
  • Error messages are in Chinese by default; send Accept-Language: en for English.

Retries and duplicates

  • The merchant order number prevents duplicates: creating again with the same number and content returns the original order; nothing is collected or paid twice.
  • The same order number with different content is rejected.
  • After a timeout or internal error, query the original order first, then retry with the same parameters. Never resubmit under a new order number, or you may create two orders.
  • A PENDING payout is still processing. Wait for the final result; do not pay again.

Signing

An HMAC-SHA256 signature goes in the sign field of the JSON body; no extra authentication headers.

Steps

  1. Take every body field except sign (including merchant_id).
  2. Sort keys (nested objects too) and serialise as compact JSON without spaces. Keep non-ASCII characters as they are, without \u escapes; decimals such as amounts must be strings.
  3. String to sign = POST + newline + endpoint path + newline + the JSON from step 2, with no trailing newline.
  4. HMAC-SHA256 that string with your API secret and put the 64-character lowercase hex result in sign.

A wrong signature, merchant number or revoked key all return the same signature error, without saying which.

Code

Defines the call() used in each endpoint example
# Requires jq and openssl
API_HOST="https://<api-host>"        # API host, see API settings in the merchant portal
API_SECRET="<your API secret>"       # API secret; keep it on your server only
API_PATH="/api/v1/payins/query"
BODY='{"merchant_id":"10001","merchant_order_id":"ORDER-10001"}'

# Drop sign, sort keys, serialise as compact JSON
CANONICAL=$(printf '%s' "$BODY" | jq -cS 'del(.sign)')
SIGN=$(printf 'POST\n%s\n%s' "$API_PATH" "$CANONICAL" \
  | openssl dgst -sha256 -hmac "$API_SECRET" | awk '{print $NF}')

curl -X POST "$API_HOST$API_PATH" \
  -H "Content-Type: application/json" \
  -d "$(printf '%s' "$CANONICAL" | jq -c --arg sign "$SIGN" '. + {sign: $sign}')"

Worked example

Your code should produce the same sign
Sample secretsample_secret_for_docs_only
Path/api/v1/payins/query
Body without sign{"merchant_id": "10001", "merchant_order_id": "ORDER-10001"}
String to sign
POST
/api/v1/payins/query
{"merchant_id":"10001","merchant_order_id":"ORDER-10001"}
sign
5ab9bc491be52b3427b0ccaf9239448874b8212416738493509ffea4bc35d298

Statuses and errors

The HTTP status tells you whether the request was handled; the order status tells you the business result. Check them separately.

Response format

  • Success: HTTP 200, code 200, result in data.
  • Failure: HTTP 500, code 500, data null, reason in message.
  • Every response has an X-Request-ID header. Include it when you report a problem.
{
  "code": 200,
  "message": "success",
  "data": {
    "merchant_order_id": "ORDER-10001",
    "platform_order_id": "PI2026110312000000012345678",
    "amount": "1000.00",
    "paid_amount": "1000.00",
    "status": "SUCCESS",
    "merchant_fee": "40.00",
    "utr": "123456789012",
    "created_at": "2026-11-03T12:00:00+05:30",
    "paid_at": "2026-11-03T12:03:10+05:30",
    "callback_at": "2026-11-03T12:03:12+05:30",
    "test": false
  }
}

Error messages

messageWhat to do
Authentication failed. Check the merchant number, API secret and signing methodCheck the string to sign against Signing; confirm the merchant number and that the key is not revoked.
The request IP is not on your API allowlistAdd your server's outgoing IP to the API allowlist in the merchant portal.
The API key does not have permission for this endpointGrant the needed scope to the key, or use a key that has it.
This product is not enabled for your accountContact us to enable the product.
Your merchant account is not activeContact us about your account status.
A request field is missing, unexpected or invalidCheck field names, required fields and formats against the endpoint's table.
bank_account is incomplete or invalid: beneficiary name, account number, IFSC, bank name, Indian mobile number and email are requiredComplete and check all six bank account fields.
UPI account details are incomplete or invalidCheck that the payee UPI details are complete and valid.
The request body is not valid JSONSend a UTF-8 JSON object without duplicate keys.
Content-Type must be application/jsonSet the header Content-Type: application/json.
The request body exceeds 32 KBMake the body smaller, for example by trimming extra.
Order not found, or the endpoint path is wrongCheck the merchant order number and the endpoint path.
Only POST requests are acceptedUse POST.
Response format not acceptable; accept application/jsonRemove the Accept header or set it to application/json.
This merchant order number was already used with different contentOne order number maps to one request; use a new number for a new order.
The request conflicts with the order's current stateQuery the order's current status before deciding what to do next.
This action is not allowed in the order's current stateQuery the order's current status; a completed order no longer accepts this action.
A UPI is being allocated. Retry with the same merchant order number and parametersRetry later with the same order number and parameters, or query the order.
Allocating a UPI timed out. Retry with the same merchant order number and parametersRetry with the same order number and parameters, or query the order.
No channel is available. Please contact usTry again later; contact us if it persists.
The amount is too small: it can't be less than the fee on this orderRaise the amount and create the order again with a new merchant order number; the amount can't be less than the fee on the order.
Insufficient available balance for this payoutCheck your balance; wait for more pay-ins to be credited, or lower the payout amount.
The recipient is blacklisted and can't receive payoutsThe recipient is blacklisted; payouts to this account are refused.
For test orders, the rupee amount must end in 1 (success) or 0 (failure)During integration testing, end the rupee amount in 1 to test success or 0 to test failure, for example 101.00 or 100.00.
Too many requests. Try again laterSlow down and retry.
The receipt can't be created right now. Try again laterRequest the receipt again later with the same merchant order number.
Internal error. Query the original order before retryingQuery the original order before retrying; if it persists, contact us with the X-Request-ID.

Pay-in statuses

StatusMeaning
ALLOCATINGAllocating a receiving UPI; query again shortly.
PENDINGWaiting for payment. If the payment is confirmed after the payment deadline, the order still becomes successful and you receive the callback.
SUCCESSSucceeded: the customer paid the payable amount; credited at the order amount.
SUCCESS_UNDERPAIDSucceeded (underpaid): less than the payable amount arrived; credited as received.
SUCCESS_OVERPAIDSucceeded (overpaid): more than the payable amount arrived; credited as received.
CREATE_TIMEOUTTimed out allocating payment details; the order cannot be paid.
NO_AVAILABLE_CHANNELNo channel available; the order cannot be paid.
SYSTEM_ERRORSystem error; the order cannot be paid. Please contact support.
CREATE_FAILEDOrder creation failed; the order cannot be paid.

The three statuses starting with SUCCESS are final and the money has arrived; credit the customer with paid_amount.

Payout statuses

StatusMeaning
PENDINGProcessing. Do not pay again while the result is pending.
SUCCESSPaid.
FAILEDFailed; the held amount has been returned to your available balance.
REFUNDA successful payout was reversed; the amount and fee have been returned to your available balance.

SUCCESS, FAILED and REFUND are final; a SUCCESS can later become REFUND.

UTR statuses

StatusMeaning
RECEIVEDPayment received.
AVAILABLE_FOR_SUPPLEMENTPayment received and not linked to an order; you can submit a missed-payment claim.
NOT_FOUNDUTR not found.
PAYMENT_FAILEDThe bank transfer failed.
CLAIMED_BY_OTHER_MERCHANTThe UTR has been claimed by another merchant.
INVALID_FORMATInvalid UTR format.
ERRORUnable to check right now; try again later.

Callbacks

When an order reaches a final result, we send a JSON POST to the notify_url you gave when creating it.

POSTnotify_url
Content-Type: application/jsonUTF-8INR

When we send it

  • Pay-ins: sent when the payment succeeds (SUCCESS, SUCCESS_UNDERPAID, SUCCESS_OVERPAID), with paid_amount. Unpaid orders get no callback; use the query endpoint.
  • Payouts: sent on SUCCESS, FAILED or REFUND.

{ }Callback fields

Body · application/json
FieldTypeDescription
merchant_idstringYour merchant number.
merchant_order_idstringYour order number.
platform_order_idstringPlatform order number: PI for pay-ins, PO for payouts. Quote it when contacting support.
statusstringOrder status. Pay-ins: SUCCESS, SUCCESS_UNDERPAID, SUCCESS_OVERPAID. Payouts: SUCCESS, FAILED, REFUND.
amountstringOrder amount, as submitted at creation.
INR as a string, up to 2 decimals, e.g. "1000.00"
paid_amountstringPay-ins only: amount to credit the customer, as in the query endpoint.
INR as a string, up to 2 decimals, e.g. "1000.00"
merchant_feestringFee for this order; "0.00" for a failed payout.
INR as a string, up to 2 decimals, e.g. "1000.00"
messagestringsuccess when paid; the failure reason for a failed payout; refund for a reversal.
completed_atstring | nullWhen the payment succeeded; null for a failed payout.
ISO 8601 with time zone
utrstring | nullPayouts only: bank transaction reference.
extraobjectPayouts only: the extra you sent at creation, or {}.
testbooleanWhether this is a test order. Orders created with a test key are true; they only use the test channel and never move real money.
signstringCallback signature, computed with your callback secret; see below.

Example

Successful pay-in
JSON
{
  "merchant_id": "10001",
  "merchant_order_id": "ORDER-10001",
  "platform_order_id": "PI2026110312000000012345678",
  "status": "SUCCESS",
  "amount": "1000.00",
  "paid_amount": "1000.00",
  "merchant_fee": "40.00",
  "message": "success",
  "completed_at": "2026-11-03T12:05:00+05:30",
  "sign": "<64 hex>"
}

Verify and reply

  1. Verify sign with your callback secret: steps 1 and 2 of request signing, but sign only the sorted JSON, without POST or a path.
  2. Record the result once verified. The same status may arrive more than once; deduplicate by platform_order_id and status.
  3. Reply HTTP 200, Content-Type: text/plain, body success in lowercase, with no spaces, newlines or JSON. Any other reply counts as not received.
# Requires jq and openssl
# callback.json holds the callback body you received
CALLBACK_SECRET="<your callback secret>"   # Callback secret (not the API secret)

SIGN=$(jq -r '.sign' callback.json)
EXPECTED=$(jq -cjS 'del(.sign)' callback.json \
  | openssl dgst -sha256 -hmac "$CALLBACK_SECRET" | awk '{print $NF}')

[ "$SIGN" = "$EXPECTED" ] && echo valid || echo invalid
text/plain
success

Retries

If we do not receive a valid reply we retry, up to 7 attempts in total: about 1 minute, 5 minutes, 15 minutes, 1 hour, 6 hours and 24 hours after each failure. Each request waits 5 seconds. After the last attempt you can resend from Callbacks in the merchant portal.

Create a pay-in

Creates an INR pay-in and returns the checkout page and payment details. Send the customer to checkout_url, or use upi / deeplink in your own page.

POST/api/v1/payins
Content-Type: application/jsonUTF-8Scope payins:create

A successful response means the order exists. Use the query endpoint or the callback for the payment result.

If the response says a UPI is being allocated, or the request times out, retry with the same merchant order number and the same parameters, or query the order first. Do not resubmit under a new order number.

{ }Request fields

Body · application/json
FieldTypeRequiredDescription
merchant_idstringYesYour merchant number, shown under API settings in the merchant portal.
Decimal digits as a string, e.g. "10001"
signstringYesRequest signature; see Signing.
64 lowercase hex characters
merchant_order_idstringYesYour order number, unique within your account.
1–128 characters: letters, digits and _ : . - /
amountstringYesOrder amount. Limits follow your account configuration.
INR as a string, up to 2 decimals, e.g. "1000.00"
notify_urlstringYesWhere we send the result notification for this order; see Callbacks.
HTTPS, up to 2048 characters, domain enabled by the platform
return_urlstringYesWhere the checkout page sends the customer after a successful payment.
HTTPS, up to 2048 characters
extraobjectNoYour own data, stored as sent.
JSON object, up to 4096 bytes and 5 levels deep

Request example

{
  "merchant_id": "10001",
  "merchant_order_id": "ORDER-10001",
  "amount": "1000.00",
  "notify_url": "https://merchant.example.com/payin/notify",
  "return_url": "https://merchant.example.com/payin/done",
  "sign": "<64 hex>"
}

↳Response example

{
  "code": 200,
  "message": "success",
  "data": {
    "platform_order_id": "PI2026110312000000012345678",
    "merchant_order_id": "ORDER-10001",
    "amount": "1000.00",
    "payable_amount": "1000.00",
    "checkout_url": "https://pay.example.com/c/AbCdEf",
    "upi": "merchant@bank",
    "deeplink": "upi://pay?pa=merchant@bank&am=1000.00"
  }
}

Response fields

data
FieldTypeDescription
platform_order_idstringPlatform order number: PI for pay-ins, PO for payouts. Quote it when contacting support.
merchant_order_idstringYour order number.
amountstringOrder amount, as submitted at creation.
INR as a string, up to 2 decimals, e.g. "1000.00"
payable_amountstring | nullAmount the customer must pay, which may differ from the order amount; show this to the customer. null if not yet known.
INR as a string, up to 2 decimals, e.g. "1000.00"
checkout_urlstring | nullCheckout page URL; null if the order cannot be paid now.
upistring | nullReceiving UPI address; null if not provided.
deeplinkstring | nullUPI payment link or parameters. Use it exactly as returned; do not add or change a prefix. null if not provided.

Query a pay-in

Returns one pay-in by your merchant order number.

POST/api/v1/payins/query
Content-Type: application/jsonUTF-8Scope payins:read

{ }Request fields

Body · application/json
FieldTypeRequiredDescription
merchant_idstringYesYour merchant number, shown under API settings in the merchant portal.
Decimal digits as a string, e.g. "10001"
signstringYesRequest signature; see Signing.
64 lowercase hex characters
merchant_order_idstringYesThe merchant order number you used when creating the order.

Request example

{
  "merchant_id": "10001",
  "merchant_order_id": "ORDER-10001",
  "sign": "<64 hex>"
}

↳Response example

{
  "code": 200,
  "message": "success",
  "data": {
    "merchant_order_id": "ORDER-10001",
    "platform_order_id": "PI2026110312000000012345678",
    "amount": "1000.00",
    "paid_amount": "1000.00",
    "status": "SUCCESS",
    "merchant_fee": "40.00",
    "utr": "123456789012",
    "created_at": "2026-11-03T12:00:00+05:30",
    "paid_at": "2026-11-03T12:03:10+05:30",
    "callback_at": "2026-11-03T12:03:12+05:30",
    "test": false
  }
}

Response fields

data
FieldTypeDescription
merchant_order_idstringYour order number.
platform_order_idstringPlatform order number: PI for pay-ins, PO for payouts. Quote it when contacting support.
amountstringOrder amount, as submitted at creation.
INR as a string, up to 2 decimals, e.g. "1000.00"
paid_amountstring | nullAmount to credit the customer: the order amount if the payable amount was paid exactly, otherwise the amount received; null until paid.
INR as a string, up to 2 decimals, e.g. "1000.00"
statusstringOrder status; see Statuses.
merchant_feestringFee charged for this order; "0.00" until the order succeeds.
INR as a string, up to 2 decimals, e.g. "1000.00"
utrstring | nullBank transaction reference; null until one is confirmed.
created_atstringWhen the order was created.
ISO 8601 with time zone
paid_atstring | nullWhen the payment was confirmed; null if not paid.
ISO 8601 with time zone
callback_atstring | nullWhen a callback was last delivered successfully; null if none yet.
ISO 8601 with time zone
testbooleanWhether this is a test order. Orders created with a test key are true; they only use the test channel and never move real money.

Submit the customer's UTR

If your own payment page collects the customer's UTR, submit it to help us confirm the payment faster. Use the query endpoint or the callback for the payment result.

POST/api/v1/payins/submit-utr
Content-Type: application/jsonUTF-8Scope payins:create

{ }Request fields

Body · application/json
FieldTypeRequiredDescription
merchant_idstringYesYour merchant number, shown under API settings in the merchant portal.
Decimal digits as a string, e.g. "10001"
signstringYesRequest signature; see Signing.
64 lowercase hex characters
merchant_order_idstringYesThe merchant order number you used when creating the order.
utrstringYesThe UTR (bank transaction reference) of the customer's payment.
12 digits; test orders use the test UTR issued by the platform

Request example

{
  "merchant_id": "10001",
  "merchant_order_id": "ORDER-10001",
  "utr": "123456789012",
  "sign": "<64 hex>"
}

↳Response example

{
  "code": 200,
  "message": "success",
  "data": {
    "submitted": true
  }
}

Response fields

data
FieldTypeDescription
submittedbooleantrue when the UTR has been saved.

Look up a UTR

Shows whether a UTR has been received and whether it can be used for a missed-payment claim. Order details are returned only if the UTR belongs to one of your orders.

POST/api/v1/payins/utr-lookup
Content-Type: application/jsonUTF-8Scope payins:read

{ }Request fields

Body · application/json
FieldTypeRequiredDescription
merchant_idstringYesYour merchant number, shown under API settings in the merchant portal.
Decimal digits as a string, e.g. "10001"
signstringYesRequest signature; see Signing.
64 lowercase hex characters
utrstringYesThe UTR (bank transaction reference) of the customer's payment.
12 digits; test orders use the test UTR issued by the platform

Request example

{
  "merchant_id": "10001",
  "utr": "123456789012",
  "sign": "<64 hex>"
}

↳Response example

{
  "code": 200,
  "message": "success",
  "data": {
    "utr": "123456789012",
    "utr_status": "RECEIVED",
    "utr_amount": "1000.00",
    "received": 1,
    "supplemented": 0,
    "merchant_order_id": "ORDER-10001",
    "platform_order_id": "PI2026110312000000012345678",
    "status": "SUCCESS",
    "amount": "1000.00"
  }
}

Response fields

data
FieldTypeDescription
utrstringThe UTR you looked up.
utr_statusstringUTR status; see Statuses.
utr_amountstring | nullAmount confirmed for this UTR; null if unknown.
INR as a string, up to 2 decimals, e.g. "1000.00"
receivedinteger1 if received; 0 if not confirmed yet.
supplementedinteger1 if the payment was credited through a missed-payment claim.
merchant_order_idstring | nullRelated merchant order number; null if not one of your orders.
platform_order_idstring | nullRelated platform order number; null if not one of your orders.
statusstring | nullStatus of the related order; null if not one of your orders.
amountstring | nullAmount of the related order; null if not one of your orders.
INR as a string, up to 2 decimals, e.g. "1000.00"

Claim a missed payment

If the customer paid but the order did not succeed, submit the original merchant order number and the UTR. Once we verify the payment, the order is updated and a callback is sent.

POST/api/v1/payins/supplements
Content-Type: application/jsonUTF-8Scope payins:create

{ }Request fields

Body · application/json
FieldTypeRequiredDescription
merchant_idstringYesYour merchant number, shown under API settings in the merchant portal.
Decimal digits as a string, e.g. "10001"
signstringYesRequest signature; see Signing.
64 lowercase hex characters
merchant_order_idstringYesThe merchant order number you used when creating the order.
utrstringYesThe UTR (bank transaction reference) of the customer's payment.
12 digits; test orders use the test UTR issued by the platform

Request example

{
  "merchant_id": "10001",
  "merchant_order_id": "ORDER-10001",
  "utr": "123456789012",
  "sign": "<64 hex>"
}

↳Response example

{
  "code": 200,
  "message": "success",
  "data": {
    "merchant_order_id": "ORDER-10001",
    "platform_order_id": "PI2026110312000000012345678",
    "status": "PENDING",
    "utr": "123456789012",
    "actual_amount": null
  }
}

Response fields

data
FieldTypeDescription
merchant_order_idstringYour order number.
platform_order_idstringPlatform order number: PI for pay-ins, PO for payouts. Quote it when contacting support.
statusstringCurrent status of the order: PENDING, SUCCESS, SUCCESS_UNDERPAID or SUCCESS_OVERPAID.
utrstringThe UTR you submitted.
actual_amountstring | nullVerified amount received; null until verified.
INR as a string, up to 2 decimals, e.g. "1000.00"

Query a missed-payment claim

Returns the result of a claim by merchant order number and UTR.

POST/api/v1/payins/supplements/query
Content-Type: application/jsonUTF-8Scope payins:read

{ }Request fields

Body · application/json
FieldTypeRequiredDescription
merchant_idstringYesYour merchant number, shown under API settings in the merchant portal.
Decimal digits as a string, e.g. "10001"
signstringYesRequest signature; see Signing.
64 lowercase hex characters
merchant_order_idstringYesThe merchant order number you used when creating the order.
utrstringYesThe UTR (bank transaction reference) of the customer's payment.
12 digits; test orders use the test UTR issued by the platform

Request example

{
  "merchant_id": "10001",
  "merchant_order_id": "ORDER-10001",
  "utr": "123456789012",
  "sign": "<64 hex>"
}

↳Response example

{
  "code": 200,
  "message": "success",
  "data": {
    "merchant_order_id": "ORDER-10001",
    "platform_order_id": "PI2026110312000000012345678",
    "status": "SUCCESS",
    "utr": "123456789012",
    "actual_amount": "1000.00"
  }
}

Response fields

data
FieldTypeDescription
merchant_order_idstringYour order number.
platform_order_idstringPlatform order number: PI for pay-ins, PO for payouts. Quote it when contacting support.
statusstringCurrent status of the order: PENDING, SUCCESS, SUCCESS_UNDERPAID or SUCCESS_OVERPAID.
utrstringThe UTR you submitted.
actual_amountstring | nullVerified amount received; null until verified.
INR as a string, up to 2 decimals, e.g. "1000.00"

List receiving UPI addresses

Returns the UPI addresses that may currently receive your pay-ins, so you can recognise where customers paid. Each order's actual UPI is the one returned when the order is created.

POST/api/v1/upis
Content-Type: application/jsonUTF-8Scope payins:read

{ }Request fields

Body · application/json
FieldTypeRequiredDescription
merchant_idstringYesYour merchant number, shown under API settings in the merchant portal.
Decimal digits as a string, e.g. "10001"
signstringYesRequest signature; see Signing.
64 lowercase hex characters

Request example

{
  "merchant_id": "10001",
  "sign": "<64 hex>"
}

↳Response example

{
  "code": 200,
  "message": "success",
  "data": {
    "upis": [
      "merchant@bank",
      "shop@upi"
    ]
  }
}

Response fields

data
FieldTypeDescription
upisarrayList of UPI addresses (strings).

Look up a UPI address

Shows whether a UPI address is one of our receiving addresses, and its status.

POST/api/v1/upis/lookup
Content-Type: application/jsonUTF-8Scope payins:read

{ }Request fields

Body · application/json
FieldTypeRequiredDescription
merchant_idstringYesYour merchant number, shown under API settings in the merchant portal.
Decimal digits as a string, e.g. "10001"
signstringYesRequest signature; see Signing.
64 lowercase hex characters
upistringYesThe UPI address to look up; case-sensitive.
Up to 193 characters

Request example

{
  "merchant_id": "10001",
  "upi": "merchant@bank",
  "sign": "<64 hex>"
}

↳Response example

{
  "code": 200,
  "message": "success",
  "data": {
    "upi": "merchant@bank",
    "status": "ACTIVE",
    "exists": 1
  }
}

Response fields

data
FieldTypeDescription
upistringThe UPI address you looked up.
statusstring | nullACTIVE in use; INACTIVE retired; FROZEN frozen; CONFLICT ownership under review; null if not on record.
existsinteger1 if on record; 0 if not.

Create a payout

Pays out INR to an Indian bank account. The amount plus fee is held from your available balance at creation, deducted on success and released on failure.

POST/api/v1/payouts
Content-Type: application/jsonUTF-8Scope payouts:create

A successful response means the payout was accepted. Use the query endpoint or the callback for the result.

If the request times out or fails, query the original merchant order number first, then retry with the same parameters if needed. Resubmitting the same order number with the same content never pays twice.

{ }Request fields

Body · application/json
FieldTypeRequiredDescription
merchant_idstringYesYour merchant number, shown under API settings in the merchant portal.
Decimal digits as a string, e.g. "10001"
signstringYesRequest signature; see Signing.
64 lowercase hex characters
merchant_order_idstringYesYour order number, unique within your account.
1–128 characters: letters, digits and _ : . - /
amountstringYesPayout amount. Limits follow your account configuration.
INR as a string, up to 2 decimals, e.g. "1000.00"
bank_accountobjectYesBeneficiary bank account.
bank_account.beneficiary_namestringYesBeneficiary name.
1–100 characters: letters, digits, spaces and . ' & , / ( ) -, with at least one letter
bank_account.account_numberstringYesBank account number.
6–34 digits, not all zeros
bank_account.ifscstringYesIFSC code.
11 characters, e.g. HDFC0001234
bank_account.bank_namestringYesBank name.
1–100 characters: letters, digits, spaces and . ' & , / ( ) -, with at least one letter
bank_account.phonestringYesBeneficiary mobile number.
10-digit Indian mobile starting 6–9, optional +91
bank_account.emailstringYesBeneficiary email.
Up to 200 characters
notify_urlstringYesWhere we send the result notification for this order; see Callbacks.
HTTPS, up to 2048 characters, domain enabled by the platform
upistringNoBeneficiary UPI address as additional information; the payout still goes to the bank account.
extraobjectNoYour own data, returned unchanged in the callback.
JSON object, up to 4096 bytes and 5 levels deep

Request example

{
  "merchant_id": "10001",
  "merchant_order_id": "PAYOUT-20001",
  "amount": "500.00",
  "bank_account": {
    "beneficiary_name": "Ravi Kumar",
    "account_number": "123456789012",
    "ifsc": "HDFC0001234",
    "bank_name": "HDFC Bank",
    "phone": "9876543210",
    "email": "ravi@example.com"
  },
  "notify_url": "https://merchant.example.com/payout/notify",
  "sign": "<64 hex>"
}

↳Response example

{
  "code": 200,
  "message": "success",
  "data": {
    "merchant_order_id": "PAYOUT-20001",
    "platform_order_id": "PO2026110312000000012345678",
    "amount": "500.00"
  }
}

Response fields

data
FieldTypeDescription
merchant_order_idstringYour order number.
platform_order_idstringPlatform order number: PI for pay-ins, PO for payouts. Quote it when contacting support.
amountstringOrder amount, as submitted at creation.
INR as a string, up to 2 decimals, e.g. "1000.00"

Query a payout

Returns one payout by your merchant order number.

POST/api/v1/payouts/query
Content-Type: application/jsonUTF-8Scope payouts:read

{ }Request fields

Body · application/json
FieldTypeRequiredDescription
merchant_idstringYesYour merchant number, shown under API settings in the merchant portal.
Decimal digits as a string, e.g. "10001"
signstringYesRequest signature; see Signing.
64 lowercase hex characters
merchant_order_idstringYesThe merchant order number you used when creating the order.

Request example

{
  "merchant_id": "10001",
  "merchant_order_id": "PAYOUT-20001",
  "sign": "<64 hex>"
}

↳Response example

{
  "code": 200,
  "message": "success",
  "data": {
    "merchant_order_id": "PAYOUT-20001",
    "platform_order_id": "PO2026110312000000012345678",
    "amount": "500.00",
    "status": "SUCCESS",
    "merchant_fee": "10.00",
    "utr": "123456789012",
    "test": false
  }
}

Response fields

data
FieldTypeDescription
merchant_order_idstringYour order number.
platform_order_idstringPlatform order number: PI for pay-ins, PO for payouts. Quote it when contacting support.
amountstringOrder amount, as submitted at creation.
INR as a string, up to 2 decimals, e.g. "1000.00"
statusstringOrder status; see Statuses.
merchant_feestringFee charged for this order; "0.00" until the order succeeds.
INR as a string, up to 2 decimals, e.g. "1000.00"
utrstring | nullBank transaction reference; null until one is confirmed.
testbooleanWhether this is a test order. Orders created with a test key are true; they only use the test channel and never move real money.

List payouts

Returns your payouts page by page. All filters are optional.

POST/api/v1/payouts/list
Content-Type: application/jsonUTF-8Scope payouts:read

{ }Request fields

Body · application/json
FieldTypeRequiredDescription
merchant_idstringYesYour merchant number, shown under API settings in the merchant portal.
Decimal digits as a string, e.g. "10001"
signstringYesRequest signature; see Signing.
64 lowercase hex characters
pageintegerNoPage number, default 1.
page_sizeintegerNoItems per page, 1–100, default 50.
merchant_order_idstringNoMerchant order number.
platform_order_idstringNoPlatform order number.
created_fromstringNoCreated at or after this time.
ISO 8601 with time zone
created_tostringNoCreated before this time.
ISO 8601 with time zone
statusstringNoOrder status.
min_amountstringNoMinimum order amount, inclusive.
INR as a string, up to 2 decimals, e.g. "1000.00"
max_amountstringNoMaximum order amount, inclusive.
INR as a string, up to 2 decimals, e.g. "1000.00"
sortstringNoSort order: created_desc (default), created_asc, amount_desc, amount_asc.
payout_typestringNoPayout method: BANK_IN for bank account. UPI appears only on older orders.

Request example

{
  "merchant_id": "10001",
  "status": "SUCCESS",
  "page": 1,
  "page_size": 50,
  "sign": "<64 hex>"
}

↳Response example

{
  "code": 200,
  "message": "success",
  "data": {
    "count": 1,
    "next": null,
    "previous": null,
    "results": [
      {
        "merchant_order_id": "PAYOUT-20001",
        "platform_order_id": "PO2026110312000000012345678",
        "amount": "500.00",
        "status": "SUCCESS",
        "merchant_fee": "10.00",
        "utr": "123456789012"
      }
    ]
  }
}

Response fields

data
FieldTypeDescription
countintegerTotal number of matching orders.
nextinteger | nullNext page number; null on the last page.
previousinteger | nullPrevious page number; null on the first page.
resultsarrayOrders, each with the same fields as Query a payout.

Get a payout receipt

Creates a web receipt for a successful payout that you can share with the beneficiary. It shows the beneficiary name, full account number and UTR, as the payment stood when the receipt was first requested; it does not change afterwards, and every request for the same order returns the same link. The link works for one year. Anyone who has the link can see these details; do not publish it.

POST/api/v1/payouts/receipt
Content-Type: application/jsonUTF-8Scope payouts:read

{ }Request fields

Body · application/json
FieldTypeRequiredDescription
merchant_idstringYesYour merchant number, shown under API settings in the merchant portal.
Decimal digits as a string, e.g. "10001"
signstringYesRequest signature; see Signing.
64 lowercase hex characters
merchant_order_idstringYesThe merchant order number you used when creating the order.

Request example

{
  "merchant_id": "10001",
  "merchant_order_id": "PAYOUT-20001",
  "sign": "<64 hex>"
}

↳Response example

{
  "code": 200,
  "message": "success",
  "data": {
    "merchant_order_id": "PAYOUT-20001",
    "platform_order_id": "PO2026110312000000012345678",
    "receipt_url": "https://receipt.example.com/r#Zk3VwQ8sT1nYb6Lx0PqRjH2mCeUa9GdXoIf7KtNyB4s"
  }
}

Response fields

data
FieldTypeDescription
merchant_order_idstringYour order number.
platform_order_idstringPlatform order number: PI for pay-ins, PO for payouts. Quote it when contacting support.
receipt_urlstringReceipt link.

Get balance

Returns your current available and frozen balances in INR.

POST/api/v1/balances
Content-Type: application/jsonUTF-8Scope balances:read

{ }Request fields

Body · application/json
FieldTypeRequiredDescription
merchant_idstringYesYour merchant number, shown under API settings in the merchant portal.
Decimal digits as a string, e.g. "10001"
signstringYesRequest signature; see Signing.
64 lowercase hex characters

Request example

{
  "merchant_id": "10001",
  "sign": "<64 hex>"
}

↳Response example

{
  "code": 200,
  "message": "success",
  "data": {
    "available_balance": "125000.00",
    "frozen_balance": "8000.00",
    "order_frozen_balance": "0.00"
  }
}

Response fields

data
FieldTypeDescription
available_balancestringAvailable balance, usable for payouts and settlements. It is your balance minus payouts and settlements in progress and frozen pay-ins. It is negative (for example -380.00) while frozen pay-ins exceed your balance; payouts and settlements are not possible then.
INR as a string, up to 2 decimals, e.g. "1000.00"
frozen_balancestringFrozen amount: amounts held by payouts and settlement requests in progress and by frozen pay-ins. Not usable yet.
INR as a string, up to 2 decimals, e.g. "1000.00"
order_frozen_balancestringPart of the frozen amount held by frozen pay-ins, for example after a payer complaint at the upstream. It returns to the available balance when unfrozen.
INR as a string, up to 2 decimals, e.g. "1000.00"