Webhook overview
OSL Pay uses a unified webhook to asynchronously notify merchants of important updates. When a user account status or order status changes, OSL Pay will call the webhook URL provided by the merchant and push the current status information of the user or order to the merchant’s system.
Webhook signature verification
When OSL Pay sends a webhook, the request headers follow the same format as OpenAPI, including appId
, timestamp
, and signature
. You can verify the signature
using the public key provided to you when integrating with OSL Pay.
Request parameters / Request body (header) | |||
---|---|---|---|
Parameter | Type | Required | Description |
appId | String | Yes | The appId assigned to the merchant when integrating with OSL Pay |
timestamp | Long | Yes | Timestamp of the request in milliseconds |
signature | String | Yes | The signature of the request. Example body for signing: "appId=me114702259781634×tamp=1756802303227". Use the public key provided by OSL Pay to verify the signature. See encryption & signature verification guide for sample code. |
Webhook common parameters
All Webhooks are pushed using the following standard structure. The content of the data
field varies depending on the scenario.
Webhook body | |||
---|---|---|---|
Parameter | Type | Required | Description |
type | String | Yes | Webhook typekyc_status_change: Asynchronous notification of a user KYC/account opening resultdefi_account_bind_status: Notification of DEFI-type merchant account binding resultdefi_account_auth_status: Notification of DEFI-type merchant authentication resultorder_status_change: Notification of order status change |
data | object | Yes | Detailed data |
User account opening information push (kyc_status_change)
When a merchant uses Sumsub Token Share for account opening, a Webhook is sent whenever the account status changes. The data
field in the Webhook will follow the format below:
Data parameter | |||
---|---|---|---|
Parameter | Type | Required | Description |
merchantUserId | String | No | User ID on the merchant side |
userId | String | Yes | User ID on the OSL Pay side |
kycShareFailedReason | String | No | Reason for failure (KYC failed reason) |
merchantCode | String | Yes | Merchant code |
kycStatus | String | Yes | KYC status: PASS for approvedREJECT for rejected |
previousUserId | Long | No | If KYC is a duplicate, this is the previously bound OSL Pay user ID |
previousMerchantUserId | String | No | If KYC is a duplicate, this is the previously bound merchant-side user ID |
Request body example:
{
"data": "{\"merchantCode\":\"MER10000021\",\"kycStatus\":\"REJECT\",\"kycShareFailedReason\":\"user already exists\",\"merchantUserId\":\"88813320250090207\",\"userId\":\"100824841806683\"}",
"id": "f17d8acc92c44040b2309939e797eb8c",
"type": "kyc_status_change",
"version": "1.0.0"
}
Success response example
Parameter | Type | Required | Description |
---|---|---|---|
code | String | Yes | Response code. "00000" indicates success. (You must return this code to OSL Pay; otherwise, the Webhook will be retried up to 5 times.) |
msg | String | Yes | Response message/description |
{
"code": "00000",
"msg": "success"
}
Web3 user account opening (defi_account_bind_status)
When a Web3-type user account status changes, a Webhook is sent. The data
field in the Webhook will follow the format below:
Data parameter | |||
---|---|---|---|
Parameter | Type | Required | Description |
merchantUserId | String | No | User ID on the merchant side |
userId | String | Yes | User ID on OSL Pay side |
String | No | User email. Only pushed when type = defi_account_bind_statusRefer to decryption guide for details | |
kycShareFailedReason | String | No | Failure reason (KYC Failed Reason) |
merchantCode | String | Yes | Merchant code |
kycStatus | String | Yes | KYC status: PASS – passedREJECT – rejected |
Request body example:
{
"data": "{\"merchantCode\":\"MER10000021\",\"email\":\"XXX\",\"kycStatus\":\"REJECT\",\"kycShareFailedReason\":\"user already exists\",\"merchantUserId\":\"88813320250090207\",\"userId\":\"100824841806683\"}",
"id": "f17d8acc92c44040b2309939e797eb8c",
"type": "defi_account_bind_status",
"version": "1.0.0"
}
Success response example
Parameter | Type | Required | Description |
---|---|---|---|
code | String | Yes | Response code. "00000" indicates success. (You must return this code to OSL Pay; otherwise, the Webhook will be retried up to 5 times.) |
msg | String | Yes | Response message/description |
{
"code": "00000",
"msg": "success"
}
DEFI user authentication (defi_account_auth_status)
When a DEFI user authentication status changes, a Webhook is sent. The data
field in the Webhook will follow the format below:
Data parameter | |||
---|---|---|---|
Parameter | Type | Required | Description |
reqNo | String | Yes | Serial number of the authentication request |
checkStatus | String | Yes | Authentication status: FAIL – failed, SUCCESS – successful |
Request body example:
{
"data": "{\"reqNo\":\"REQ1000001\",\"checkStatus\":\"FAIL\"}",
"id": "f17d8acc92c44040b2309939e797eb8c",
"type": "defi_account_auth_status",
"version": "1.0.0"
}
Success response example
Parameter | Type | Required | Description |
---|---|---|---|
code | String | Yes | Response code. "00000" indicates success. (You must return this code to OSL Pay; otherwise, the Webhook will be retried up to 5 times.) |
msg | String | Yes | Response message/description |
{
"code": "00000",
"msg": "success"
}
Order status change push (order_status_change)
当When a merchant subscribes to order status changes, a Webhook is sent whenever an order status changes. The data
field in the Webhook will follow the format below:
Data parameter | |||
---|---|---|---|
Parameter | Type | Required | Description |
orderId | String | Yes | OSL Pay order ID |
merchantOrder | String | No | Merchant-side order ID |
userId | String | Yes | OSL Pay user ID |
fiatCurrency | String | Yes | Fiat currency |
cryptoCurrency | String | Yes | Cryptocurrency |
fiatAmount | String | Yes | Fiat amount |
cryptoAmount | String | Yes | Cryptocurrency amount |
orderFee | String | No | Fee |
price | String | No | Cryptocurrency price |
payWayCode | String | Yes | Payment method CARD GOOGLEPAY APPLE PAY |
state | String | Yes | Order status CREATEED (created), PROCESSING (3DS link generated), CONVERSION_FAILED (hedge failed), CHAIN_WITHDRAW_WAIT (on-chain transfer), SUCCESSED (fiat paid successfully, awaiting transfer), COMPLETED (order completed), FAILED (order failed) |
subState | String | No | Order sub-status (only when state = COMPLETED): WITHDRAWAL_SUCCESS (transfer successful), WITHDRAWAL_FAILED (transfer failed) |
errorCode | String | No | Error code |
errorMessage | String | No | Error message |
completedTime | Date | No | Order completion time |
createTime | Date | Yes | Order creation time |
updateTime | Date | Yes | Order update time |
network | String | Yes | Blockchain network |
tag | String | No | Blockchain tag |
address | String | Yes | Withdrawal address |
txId | String | No | On-chain transaction ID |
networkFee | String | No | On-chain gas fee |
chainArrivalTime | Date | No | On-chain arrival time |
orderCallbackUrl | String | Yes | Merchant Webhook callback URL |
merchantUser | String | No | Merchant-side user ID |
threeDsRedirectUrl | String | No | 3DS redirect URL |
actualReceivedAmount | String | Yes | Actual received amount |
qrcodeUrl | String | No | QR code payment link, returned when payWayCode = QRCODE |
Request body example:
{
"data": {
"orderId": "202509040001",
"merchantOrder": "MCH20250904001",
"userId": "U123456789",
"fiatCurrency": "USD",
"cryptoCurrency": "USDT",
"fiatAmount": "100.00",
"cryptoAmount": "99.50",
"orderFee": "0.50",
"price": "1.00",
"payWayCode": "VISA",
"state": "COMPLETED",
"subState": "WITHDRAWAL_FAILED",
"errorCode": "",
"errorMessage": "",
"completedTime": "2025-09-04T16:15:30Z",
"createTime": "2025-09-04T16:10:00Z",
"updateTime": "2025-09-04T16:15:30Z",
"network": "ERC20",
"tag": "",
"address": "0x9fBDa871d559710256a2502A2517b794B482Db40",
"txId": "0xabc123def4567890abcdef1234567890abcdef1234567890abcdef1234567890",
"networkFee": "5.00",
"chainArrivalTime": "2025-09-04T16:16:00Z",
"orderCallbackUrl": "https://merchant.com/callback/order",
"privateSecret": "************",
"merchantCallbackUrl": "https://merchant.com/callback",
"appid": "MCH_APP_1001",
"merchantUser": "merchantUser001",
"threeDsRedirectUrl": "https://paymentgateway.com/3ds/redirect?sessionId=abc123",
"actualReceivedAmount": "99.50"
"id": "1756974300000",
"type": "order_status_change",
"version": "1.0.0"
}
Success response example
Parameter | Type | Required | Description |
---|---|---|---|
code | String | Yes | Response code. "00000" indicates success. (You must return this code to OSL Pay; otherwise, the Webhook will be retried up to 5 times.) |
msg | String | Yes | Response message/description |
{
"code": "00000",
"msg": "success"
}
Updated 3 days ago