Skip to Content
Version 1.1 · A Coming soon badge is a backward-compatible change still rolling out.
Callbacks

Callbacks

When a deposit or withdrawal reaches COMPLETED or FAILED, InsPay POSTs JSON to the callbackUrl you sent on the create call.

callback.json
{ "transaction_id": "4598b99d-0e13-4536-926b-a662bb34ac42", "provider_order_id": "routing-ref", "reference_id": "TXN-20261011-001", "status": "COMPLETED", "type": "DEPOSIT", "amount": 50000, "actual_amount": 47750, "currency": "JPY", "method": "BANK_TRANSFER" }

Field names are snake_case.

FieldNotes
transaction_idInsPay transaction id. Make your handler idempotent on this value.
provider_order_idInternal routing reference. Coming soonRemoved from callbacks.
reference_idYour order id
statusCOMPLETED or FAILED
typeDEPOSIT or WITHDRAW
amountInteger for JPY. Decimal string for other currencies.
actual_amountSame types as amount. null when the transaction failed. Deposit: amount − fee. Withdrawal: amount + fee.
currencyFor example JPY
methodFor example BANK_TRANSFER

routing-ref above stands in for the routing reference. Do not parse a fixed value.

Acknowledge

Reply HTTP 200 with the body SUCCESS. That is either plain text:

SUCCESS

or a JSON string:

"SUCCESS"

A JSON object is not the documented reply.

Today a callback is sent once. If you miss it, poll POST /transactions. Coming soonInsPay retries with exponential back-off until you reply SUCCESS. Handle a repeated transaction_id as the same event, so a retry cannot credit the player twice.

Verify the signature

Coming soonCallbacks carry an x-signature header. It is HMAC-SHA256 over the callback body with your secret key, using the same canonical form as requests. Compare it before you move money.

Null fields are dropped. On a failure, actual_amount is null and is not part of the hashed string.

The digest below is for the JSON in the example, secret YOUR_SECRET_KEY, after provider_order_id is included:

75a7fc34c512f934f59e3a58c74dcf2891d14ed6fddc8691e091cc234894487d
verify-callback.sh
SECRET_KEY="YOUR_SECRET_KEY" # Header value InsPay will send. Coming soon. HEADER_SIG="75a7fc34c512f934f59e3a58c74dcf2891d14ed6fddc8691e091cc234894487d" CANONICAL='{"actual_amount":"47750","amount":"50000","currency":"JPY","method":"BANK_TRANSFER","provider_order_id":"routing-ref","reference_id":"TXN-20261011-001","status":"COMPLETED","transaction_id":"4598b99d-0e13-4536-926b-a662bb34ac42","type":"DEPOSIT"}' SIG=$(printf '%s' "$CANONICAL" | openssl dgst -sha256 -hmac "$SECRET_KEY" -hex | awk '{print $NF}') if [ "$SIG" = "$HEADER_SIG" ]; then echo "signature ok" else echo "reject callback" >&2 exit 1 fi

Credit a deposit, or treat a withdrawal as paid, only when status is COMPLETED and, once the header is present, the signature matches.

KYC callback

If you set callbackUrl on POST /kyc-register, InsPay posts the final KYC status there:

kyc-callback.json
{ "event": "kyc.status", "player_id": "player_abc123", "gateway": "YOUR_KYC_CHANNEL", "status": "REGISTERED", "provider_status": "APPROVED", "currency": "JPY" }

Today player_id is prefixed with your merchant number, for example 31_player_abc123. Coming soonThe value becomes your own id, with no prefix. Strip a leading run of digits and an underscore so both forms resolve to the same player:

player_id.py
import re player_id = re.sub(r"^\d+_", "", body["player_id"])
player-id.mjs
const playerId = body.player_id.replace(/^\d+_/, "")

Coming soongateway and provider_status become neutral InsPay values. Branch on status (PENDING, REGISTERED, FAILED, EXPIRED), not on the current provider_status text.

Last updated on