Skip to navigation

Webhook Events & Liquidation Warnings

Merchant Webhook event types, idempotency identities, liquidation warning fields, and funds result examples.
View as Markdown

This page follows Agent Java SDK WEBHOOKS.md at commit fa6c7b6. This is a documentation-only update; no new SDK artifact containing warning helper methods was released.

All four event types use the merchant’s single configured callback URL (agents.webhook_url). Dispatch on the body event; no separate warning URL is required. The examples show payload structure and must not be used to inject data into a test environment.

Events and idempotency

eventMeaningtargetStatus / deduplication key
transfer.completedTransfer terminal state, including an update to the original order after reversal; not necessarily successfulSUCCESS / FAILED / REVERSED; orderType:orderId:targetStatus
reverse.completedReversal order terminal stateSUCCESS / FAILED; orderType:orderId:targetStatus
transfer.deadThe final funds order state remains unconfirmed after retries and needs manual reconciliation; not a confirmed failureDEAD; orderType:orderId:targetStatus
liquidation.warningLiquidation risk warning, without order terminal-state fieldsliquidation.warning:notificationId

The merchant warning event is liquidation.warning; user WebSocket data.event remains LIQUIDATION_WARNING. Keep the two channels distinct.

Historical merchant notifications used LIQUIDATION_WARNING. Frozen payloads retain their original body on retries, so receivers must recognize both names. If existing business records use an uppercase warning-key prefix, retain the original key or check both keys during migration to avoid processing the notification again.

The current WebhookVerifier.idempotencyKey only extracts orderType:orderId:targetStatus for funds events and returns an empty string for warning payloads. No new SDK artifact containing warning helper methods was released with this documentation update. Continue using the existing verify method to verify the raw warning body. After signature and ownership checks, merchant business code must recognize both event names, validate that notificationId is a positive decimal-integer string, and construct liquidation.warning:<notificationId>. Never use an empty deduplication key or require warnings to contain funds order fields.

Persist deduplication within the merchant and environment scope and commit it atomically with business processing. FIRST / UPGRADE / REMINDER notifications with different notificationId values are independent; do not discard them by grouping on user, episode, or eventType. An empty key means a valid identity could not be extracted. The SDK only returns a helper key; it does not persist records or perform business processing. Record the same identity with a different body as a conflict; do not overwrite the processed body.

Liquidation warning fields and example

FieldType / description
notificationIdPositive decimal-integer string; unique notification ID. Do not convert it to a floating-point number.
eventTypeFIRST: first warning in the current episode; UPGRADE: normal risk upgraded to high risk in this episode; REMINDER: another reminder of ongoing risk.
severityNORMAL / HIGH. FIRST may already be HIGH; UPGRADE is HIGH; REMINDER may be NORMAL or HIGH.
occurredAtJSON number; Unix milliseconds when the warning was triggered, not when HTTP delivery arrived.
objecttype=CROSS: cross-margin account, with empty strings for symbol, side, and positionId. ISOLATED: isolated-margin position, carrying the corresponding contract, side, and position ID.
episodeString; current warning episode. FIRST does not mean the user’s first-ever warning.
stateVersion / configVersionStrings; upstream state / configuration version. Do not independently discard notifications based on these fields.
riskRatio / minLargePositionValue / liquidationHighRiskThresholdDecimal strings for the risk ratio, normal warning threshold, and high-risk threshold. Preserve precision; upstream calculates the threshold rules.
environmentPRODUCTION / SIMULATED; isolate by the configured funds environment, not a server name.
agentId / agentCode / agentUserIdStrings; agent ID, agent code, and merchant-side user ID.
platformUserIdString; public platform user ID matching the binding result, not the service’s internal user_id.
{
"event": "liquidation.warning",
"notificationId": "68460336",
"eventType": "FIRST",
"severity": "NORMAL",
"occurredAt": 1791875870804,
"object": {
"type": "CROSS",
"symbol": "",
"side": "",
"positionId": ""
},
"episode": "3",
"stateVersion": "9",
"riskRatio": "0.29133109",
"minLargePositionValue": "0.20000000",
"liquidationHighRiskThreshold": "0.40000000",
"configVersion": "8",
"environment": "PRODUCTION",
"agentId": "16",
"agentCode": "DEMO",
"agentUserId": "merchant-user-001",
"platformUserId": "6054354872"
}

Transfer result example

Funds callbacks retain their existing types: orderId and agentId are JSON numbers; amount and platformUserId are strings. Do not apply the warning’s string agentId convention to funds callbacks. Read large integers without precision loss using integer / decimal types. completedAt is UTC RFC3339; ts is Unix seconds.

{
"environment": "PRODUCTION",
"event": "transfer.completed",
"orderType": "transfer",
"orderId": 10001,
"orderNo": "merchant-order-001",
"targetStatus": "SUCCESS",
"agentId": 16,
"agentCode": "DEMO",
"currency": "USDT",
"amount": "10.00",
"direction": "IN",
"transferMode": "FIXED_AMOUNT",
"agentUserId": "merchant-user-001",
"platformUserId": "6054354872",
"rejectCode": 0,
"rejectMessage": "",
"failReason": "",
"completedAt": "2026-10-13T07:17:50Z",
"ts": 1791875870
}

Reversal result example

{
"environment": "PRODUCTION",
"event": "reverse.completed",
"orderType": "transfer",
"orderId": 10002,
"orderNo": "merchant-reverse-001",
"targetStatus": "SUCCESS",
"agentId": 16,
"agentCode": "DEMO",
"currency": "USDT",
"amount": "10.00",
"direction": "IN",
"transferMode": "FIXED_AMOUNT",
"agentUserId": "merchant-user-001",
"platformUserId": "6054354872",
"rejectCode": 0,
"rejectMessage": "",
"failReason": "",
"completedAt": "2026-10-13T07:17:50Z",
"ts": 1791875870
}

Funds order dead-state example

{
"environment": "PRODUCTION",
"event": "transfer.dead",
"orderType": "transfer",
"orderId": 10003,
"orderNo": "merchant-order-002",
"targetStatus": "DEAD",
"agentId": 16,
"agentCode": "DEMO",
"currency": "USDT",
"amount": "10.00",
"direction": "IN",
"transferMode": "FIXED_AMOUNT",
"agentUserId": "merchant-user-001",
"platformUserId": "6054354872",
"rejectCode": 0,
"rejectMessage": "",
"failReason": "order dead",
"completedAt": "2026-10-13T07:17:50Z",
"ts": 1791875870
}

These examples show the protocol only. For FAILED, rejectCode, rejectMessage, and failReason reflect the actual rejection. The event name alone does not prove funds were credited.

Signature verification, responses, and retries