Webhook events triggered by a payments status update.
Platforms leveraging zero hash’s Fiat products should subscribe to webhooks to know when payments statuses have changed.
We will send you updates for every status change, including External account status updates. To tell them apart, check Webhook Security.
Note: The x-zh-hook-payload-type to subscribe for is payment_status_changed.
Once a platform is set up to receive payment status webhooks, the payload is a JSON object containing the following fields:
| Parameter | Description | Type |
|---|---|---|
| participant_code | The zero hash identifier for the customer requesting an ACH transaction. | string |
| type | Indicates if the payment is a credit or a debit for the end customer. | string |
| transaction_id | The unique identifier generated by zero hash for the transaction. | string |
| payment_status | The current status of the payment. See payment statuses below for more. | string |
| reason_code | The Nacha failure reason code, if the payment_status is returned. | string |
| reason_description | The description matching the reason_code, if the payment_status is returned. | string |
| expected_settlement_date | For payment type of credit, when the funds are expected to settle to the end customer bank account. This is an approximation as receiving banks are ultimately responsible for posting the update. | string; YYYY-MM-DD format |
| reject_reasons | If the payment_status is rejected, this object will share reasons why. Example: "error checking account rules: failed" |
Payments Statuses
| Status | Description |
|---|---|
| submitted | Request received and validated The payment passed the initial checks and was accepted |
| pending | Balance and authorization confirmed and transaction initialized The payment was queued internally and will be processed |
| posted | For bank transfers: Withdrawn from end customer account and successfully submitted to the network For blockchain payments: payment succeeded and was posted to the network, awaiting confirmation from the blockchain |
| settled | For bank transfers: Hold period is over and funds have moved to the bank For blockchain payments: Withdrawal confirmed on-chain |
| cancelled | Transaction was proactively cancelled |
| failed | Transaction failed during the process |
| returned | Transaction was returned(reason listed in the reason_code and reason_description of webhook) |
| rejected | Transaction request blocked for risk mitigation or contractual reasons |
Payment details
The payment_details object is included in webhook payloads for blockchain/crypto withdrawal payments.
| Field | Type | Description |
|---|---|---|
withdrawal_request_id | string | Unique identifier for the withdrawal request. |
trade_id | string | Identifier of the trade associated with this withdrawal. |
on_chain_transaction_id | string | Blockchain transaction hash. Empty until the transaction is broadcast on-chain. |
network_fee_notional | string | Network (gas) fee in USD notional. |
network_fee_quantity | string | Network (gas) fee in the asset's native quantity. |
destination_address | string | Blockchain address the withdrawal was sent to. |
withdrawal_fee_notional | string | Total withdrawal fee amount in USD notional. |
withdrawal_fee_type | string | Fee structure type used for this withdrawal: "flat" or "tiered". |
fee_tier_breakdown | array | Per-tier fee breakdown. Only present when withdrawal_fee_type is "tiered". Each object contains: |
fee_tier_breakdown[].tier | integer | Tier number (starting from 1). |
fee_tier_breakdown[].amount_in_tier | string | USD amount of the withdrawal that fell within this tier's range. |
fee_tier_breakdown[].fee_bps | integer | Fee rate in basis points applied to this tier. |
fee_tier_breakdown[].fee_amount | string | Fee charged for this tier in USD. |
Payloads
To differentiate between payloads and what they mean, you will have to mainly rely on the type field for ACH/RTP updates and the payment_type field for Blockchain payments.
ACH debit
{
"participant_code": "ABC123",
"type": "debit",
"transaction_id": "e8641f4b-2098-4f86-95ba-711151cee6a5",
"payment_status": "settled"
}ACH credit
{
"participant_code": "ABC123",
"type": "credit",
"transaction_id": "e8641f4b-2098-4f86-95ba-711151cee6a9",
"payment_status": "posted",
"expected_settlement_date": "2024-03-01"
}ACH return
{
"participant_code": "ABC123",
"type": "debit",
"transaction_id": "e8641f4b-2098-4f86-95ba-711151cee6a5",
"payment_status": "returned",
"reason_code": "R01",
"reason_description": "Insufficient funds"
}Blockchain Payment
{
"payment_id": "679ee352-7705-4425-ab4a-16a3d18c1d90",
"obo_participant": {
"participant_code": "ABC123",
"account_group": "PLAT01",
"account_label": "general"
},
"payment_details": {
"withdrawal_request_id": "f32a000e-fd71-42b5-ac03-5b23337aa833",
"trade_id": "186b3b03-e625-4e3e-a5b1-80f0c43073ce",
"on_chain_transaction_id": "",
"network_fee_notional": "2.61",
"network_fee_quantity": "0.0009883939413915",
"destination_address": "0x41D9A0Ee3a917Etmn6182C030dC9f15497eCl22V",
"withdrawal_fee_type: "flat"
},
"asset": "USDC",
"network": "ETH",
"payment_type": "payout",
"external_account_id": "2d55c1dd-037d-48d2-9512-13fbea2c85d4",
"participant_code": "ABC456",
"quantity": "0",
"status": "posted",
"created_at": "2024-09-26T13:05:22.657Z",
"updated_at": "2024-09-26T13:05:22.657Z",
"total": "12.34"
}Status changes
During the lifecycle of a transaction, it can change status. The payload is different as well. Use a combination of type and payment_status to tell them apart:
For ACH on Demand, we'll also provide atrade_statusfieldUse this field to check the status of both the ACH and the Trade. Visit this page for more information
Payment status submitted
submitted{
"participant_code": "ABC123",
"type": "credit",
"transaction_id": "e8641f4b-2098-4f86-95ba-711151cee6a5",
"payment_status": "submitted",
"expected_settlement_date": "2024-10-06",
"timestamp": 1633456800000,
"trade_id": "426c739d-c40d-4d18-914b-a79e2a4ea29e",
"trade_status": "completed"
}Payment status failed
failed{
"participant_code": "ABC123",
"type": "credit",
"transaction_id": "e8641f4b-2098-4f86-95ba-711151cee6a5",
"payment_status": "returned",
"reason_code": "R99",
"reason_description": "failed",
"expected_settlement_date": "2024-10-06",
"timestamp": 1633456800000,
"trade_id": "426c739d-c40d-4d18-914b-a79e2a4ea29e",
"trade_status": "completed"
}Payment status returned
returned{
"participant_code": "ABC123",
"type": "credit",
"transaction_id": "e8641f4b-2098-4f86-95ba-711151cee6a5",
"payment_status": "returned",
"reason_code": "R01",
"reason_description": "Insufficient funds",
"expected_settlement_date": "2024-10-06",
"timestamp": 1633456800000,
"trade_id": "426c739d-c40d-4d18-914b-a79e2a4ea29e",
"trade_status": "completed"
}Payment status posted
posted{
"participant_code": "ABC123",
"type": "debit",
"timestamp": 1633456800000,
"transaction_id": "e8641f4b-2098-4f86-95ba-711151cee6a5",
"payment_status": "posted"
}Payment status settled
settled{
"participant_code": "ABC123",
"type": "debit",
"timestamp": 1633456800000,
"transaction_id": "e8641f4b-2098-4f86-95ba-711151cee6a5",
"payment_status": "settled"
}Payment status rejected
rejected{
"participant_code": "ABC123",
"type": "debit",
"timestamp": 1633456800000,
"transaction_id": "e8641f4b-2098-4f86-95ba-711151cee6a5",
"payment_status": "rejected",
"rejected_reason": "rule",
"ach_failure_reason": "insufficient funds"
}Payment status pending_trade
pending_trade{
"participant_code": "ABC123",
"type": "debit",
"transaction_id": "e8641f4b-2098-4f86-95ba-711151cee6a5",
"payment_status": "pending_trade",
"timestamp": 1633456800000,
"trade_id": "e8641f4b-2098-4f86-95ba-711151cee6a2",
"trade_status": "terminated"
}Payment status pending_settlement
pending_settlement{
"participant_code": "ABC123",
"type": "debit",
"transaction_id": "e8641f4b-2098-4f86-95ba-711151cee6a5",
"payment_status": "retried",
"timestamp": 1633456800000,
"trade_id": "e8641f4b-2098-4f86-95ba-711151cee6a2",
"trade_status": "terminated"
}