Overview
Virtual accounts emit one of two webhook payload types depending on what's changing. Changes to the account resource itself emit x-zh-hook-payload-type header value of virtual_account.status_changed, while activity on deposits landing in that account emit virtual_account_deposit.status_changed. Both events track their respective resource as it moves through its lifecycle - the account through creation, closure, blocking, and suspension; the deposit through receipt, screening, and payouts - but each uses its own set of status values reflecting its distinct pipeline. The table below consolidates the possible statuses across both event types and which type each status applies to.
Virtual Account Events
Subscribe to this event by setting the x-zh-hook-payload-type header value to virtual_account.status_changed.
A virtual_account.status_changed webhook is emitted every time a virtual account transitions between states - for example, when the account is first opened and becomes active, when zerohash blocks it, or when it's closed or suspended.
Virtual Account Statuses
The status field communicates the current state of the virtual account. Values are returned in lowercase.
| Status | Description |
|---|---|
active | Virtual account has been successfully created and can receive deposits. |
closed | Virtual account has been closed. Terminal. |
blocked | zerohash has blocked the account; it can no longer receive deposits. |
failed | zerohash could not open or had to reject the account. Terminal. |
Virtual Account Payload Schema
| Field | Type | Description |
|---|---|---|
virtual_account_id | string | Unique identifier for the virtual account. |
participant_code | string | Participant code of the end customer that owns the account. |
platform_code | string | Platform the account belongs to. |
provider_type | string | Banking provider backing the account. Currently only CRB. |
status | string | Current account status. See Virtual Account Statuses for possible values. |
bank_details | object | The account's bank details. Present only when status is created. |
bank_details.account_number | string | The account's account number. |
bank_details.routing_number | string | The account's routing number. |
bank_details.provider_account_id | string | The banking provider's internal identifier for the account. |
status_detail | object | Additional context on why the account entered its current status. Present only for blocked, failed, or suspended. |
status_detail.code | string | Stable, machine-readable reason code. |
status_detail.message | Human-readable description of the code. Do not parse - may be reworded. | |
status_detail.at | string (ISO 8601) | Timestamp the status detail was recorded. |
created_at | timestamp | Timestamp the account was created. |
updated_at | timestamp | Timestamp the account was last updated. |
virtual_account.status_changed Payload Examples
virtual_account.status_changed Payload ExamplesActive
{
"virtual_account_id": "47d7dfe4-fcae-45fe-9242-7e14795f449c",
"participant_code": "CUST01",
"platform_code": "PLAT01",
"provider_type": "CRB",
"status": "active",
"bank_details": {
"account_number": "1234567890",
"routing_number": "021000021",
"provider_account_id": "crb_ac_9f13e2"
},
"created_at": "2026-08-20T14:32:01Z",
"updated_at": "2026-08-20T14:32:01Z"
}Closed
{
"virtual_account_id": "47d7dfe4-fcae-45fe-9242-7e14795f449c",
"participant_code": "CUST01",
"platform_code": "PLAT01",
"provider_type": "CRB",
"status": "closed",
"created_at": "2026-08-20T14:32:01Z",
"updated_at": "2026-08-25T09:10:44Z"
}Blocked
{
"virtual_account_id": "47d7dfe4-fcae-45fe-9242-7e14795f449c",
"participant_code": "CUST01",
"platform_code": "PLAT01",
"provider_type": "CRB",
"status": "blocked",
"status_detail": {
"code": "VA_BLOCKED",
"message": "zerohash has blocked this virtual account and it can no longer receive deposits. Contact zerohash support for next steps.",
"at": "2026-08-25T09:10:44Z"
},
"created_at": "2026-08-20T14:32:01Z",
"updated_at": "2026-08-25T09:10:44Z"
}Failed - Creation declined
{
"virtual_account_id": "47d7dfe4-fcae-45fe-9242-7e14795f449c",
"participant_code": "CUST01",
"platform_code": "PLAT01",
"provider_type": "CRB",
"status": "failed",
"status_detail": {
"code": "VA_CREATION_DECLINED",
"message": "zerohash could not open this virtual account for the account holder. Contact zerohash support for next steps.",
"at": "2026-08-20T14:32:01Z"
},
"created_at": "2026-08-20T14:32:01Z",
"updated_at": "2026-08-20T14:32:01Z"
}Failed - Creation failed
{
"virtual_account_id": "47d7dfe4-fcae-45fe-9242-7e14795f449c",
"participant_code": "CUST01",
"platform_code": "PLAT01",
"provider_type": "CRB",
"status": "failed",
"status_detail": {
"code": "VA_CREATION_FAILED",
"message": "zerohash was unable to open this virtual account. Contact zerohash support to request a new account.",
"at": "2026-08-20T14:32:01Z"
},Virtual Account Deposit Events
Subscribe to this event by setting the x-zh-hook-payload-type header value to virtual_account_deposit.status_changed.
A virtual_account_deposit.status_changed webhook is emitted every time a deposit into a virtual account transitions between states - for example, when funds are received, when a deposit is held for review, or when a payout to the configured external account or wallet completes.
Virtual Account Deposit Statuses
The status field communicates the current stage of the deposit.
| Status | Description |
|---|---|
deposit_received | Funds landed at partner bank, but have not been credit yet. |
deposit_pending | Deposit is pending further processing or review before it can be cleared. |
deposit_cleared | Review cleared and the deposit was credited to the participant. |
deposit_rejected | Deposit was rejected and will be returned to the originator. Terminal. |
deposit_blocked | Confirmed sanctions match; funds quarantined. Terminal. |
payout_initiated | Conversion and payout to the configured external account or wallet has begun (only for AUTO_CONVERT_AND_WITHDRAW policy). |
payout_completed | Conversion and payout completed successfully (only for AUTO_CONVERT_AND_WITHDRAW policy). Terminal. |
payout_failed | The conversion or payout leg failed (only for AUTO_CONVERT_AND_WITHDRAW policy). Terminal. |
Virtual Account Deposit Payload Schema
| Field | Type | Description |
|---|---|---|
virtual_account_id | string | zerohash-generated unique identifier for the virtual account |
participant_code | string | End customer's participant code |
platform_code | string | The Participant code associated with the Platform |
provider_type | string | The banking provider backing the virtual account. Currently only CRB is supported. |
status | string | The current status of the virtual account. One of ACTIVE, CLOSED, BLOCKED, FAILED. |
bank_details | string | The virtual account's bank details. |
bank_details.account_number | string | The virtual account's account number |
bank_details.routing_number | string | The virtual account's routing number |
bank_details.provider_account_id | string | The banking provider's internal identifier for the account |
status_detail | string | Additional context on why the account entered its current status |
status_detail.code | string | Stable, machine-readable code describing the reason. One of VA_BLOCKED, VA_CREATION_DECLINED, VA_CREATION_FAILED, or an unclassified fallback code. |
status_detail.message | string | Human-readable description of the code |
status_detail.at | timestamp | Timestamp the status detail was recorded |
created_at | timestamp | Timestamp the virtual account was created |
updated_at | timestamp | Timestamp the virtual account was last updated |
virtual_account_deposit.status_changed Payload Examples
virtual_account_deposit.status_changed Payload ExamplesDeposit Received
Fires when a deposit lands at bank partner and is pending screening before being credited to customer.
{
"virtual_account_id": "47d7dfe4-fcae-45fe-9242-7e14795f449c",
"participant_code": "CUST01",
"platform_code": "PLAT01",
"transaction_id": "vat_3d9f6b2c1a8e4f7d",
"type": "DEPOSIT",
"status": "deposit_received",
"amount": "2500.00",
"currency": "USD",
"originator_name": "Leslie Barbara Knope",
"rail": "wire",
"reference": "INV-10432",
"created_at": "2026-08-25T09:10:44Z"
}
Note:For Virtual Accounts with the
HOLDsettlement policy, you will also want to subscribe toaccount_balance.changedto see when USD deposits are credited to customer balances (check examples on Account Balance).
Deposit Pending
Fires when an incoming deposit is being held for manual review. This can happen because of a name mismatch on a wire, or if an deposit type is above configured limits. Where "reason" can be = over_threshold | name_mismatch | other
{
"type": "DEPOSIT",
"status": "deposit_pending",
"transaction_id": "a790d94a-b6f0-42c0-9bfd-7065e4c7b7e9",
"virtual_account_id": "b6778167-7a81-49c4-b5ae-e81e701173a9",
"participant_code": "PART001",
"platform_code": "PLAT001",
"amount": "500.00",
"currency": "USD",
"rail": "wire",
"reference": "INV-2026-00417",
"reason": "over_threshold",
"originator_name": "Acme Corp Treasury",
"created_at": "2026-09-14T15:06:12Z"
}Deposit Cleared
Fires when an incoming deposit has been approved during screening and will be credited to the end customer.
{
"type": "DEPOSIT",
"status": "deposit_cleared",
"transaction_id": "a790d94a-b6f0-42c0-9bfd-7065e4c7b7e9",
"virtual_account_id": "b6778167-7a81-49c4-b5ae-e81e701173a9",
"participant_code": "PART001",
"platform_code": "PLAT001",
"amount": "500.00",
"currency": "USD",
"rail": "wire",
"reference": "INV-2026-00417",
"originator_name": "Acme Corp Treasury",
"created_at": "2026-09-14T15:13:02Z"
}Deposit Rejected
Fires when an incoming deposit will not be credited to the end customer, but funds are designated for return to the originator. Where "reason" can be = JURISDICTION_DENIED | NAME_MISMATCH
{
"type": "DEPOSIT",
"status": "deposit_rejected",
"transaction_id": "a790d94a-b6f0-42c0-9bfd-7065e4c7b7e9",
"virtual_account_id": "b6778167-7a81-49c4-b5ae-e81e701173a9",
"participant_code": "PART001",
"platform_code": "PLAT001",
"amount": "500.00",
"currency": "USD",
"rail": "wire",
"reference": "INV-2026-00417",
"reason": "JURISDICTION_DENIED",
"originator_name": "Acme Corp Treasury",
"created_at": "2026-09-14T15:10:47Z"
}Deposit Blocked
Fires when an incoming deposit will not be credited to the end customer, and funds will NOT be returned to originator due to sanctions screening results.
{
"type": "DEPOSIT",
"status": "deposit_blocked",
"transaction_id": "a790d94a-b6f0-42c0-9bfd-7065e4c7b7e9",
"virtual_account_id": "b6778167-7a81-49c4-b5ae-e81e701173a9",
"participant_code": "PART001",
"platform_code": "PLAT001",
"amount": "500.00",
"currency": "USD",
"rail": "wire",
"reference": "INV-2026-00417",
"reason": "SANCTIONS_MATCH",
"originator_name": "Acme Corp Treasury",
"created_at": "2026-09-14T15:12:30Z"
}Payout Initiated
Fires when an incoming deposit begins automatic conversion and payout to the account's configured external account. There is still a preceding deposit_received event for this settlement policy. This only applies to accounts with the settlement policy AUTO_CONVERT_AND_WITHDRAW.
{
"virtual_account_id": "47d7dfe4-fcae-45fe-9242-7e14795f449c",
"participant_code": "CUST01",
"platform_code": "PLAT01",
"transaction_id": "vat_9c4e1f7a2b6d3e8f",
"type": "DEPOSIT",
"originator_name": "Leslie Barbara Knope",
"rail": "wire",
"status": "payout_initiated",
"external_account_id": "107e8a2a-c835-4b76-b49d-a633d45727b9",
"asset": "USDC.SOL",
"reference": "INV-10432",
"created_at": "2026-08-25T09:10:44Z"
}Payout Completed
Fires once the conversion and payout have completed successfully. This only applies to accounts with the settlement policy AUTO_CONVERT_AND_WITHDRAW.
{
"virtual_account_id": "47d7dfe4-fcae-45fe-9242-7e14795f449c",
"participant_code": "CUST01",
"platform_code": "PLAT01",
"transaction_id": "vat_9c4e1f7a2b6d3e8f",
"type": "DEPOSIT",
"status": "payout_completed",
"external_account_id": "107e8a2a-c835-4b76-b49d-a633d45727b9",
"asset": "USDC.SOL",
"quantity": "2499.7",
"originator_name": "Leslie Barbara Knope",
"rail": "wire",
"reference": "INV-10432",
"created_at": "2026-08-25T09:10:44Z",
"settled_at": "2026-08-25T09:12:03Z"
}Payout Failed
Fires if the conversion or payout leg fails. This only applies to accounts with the settlement policy AUTO_CONVERT_AND_WITHDRAW.
{
"virtual_account_id": "47d7dfe4-fcae-45fe-9242-7e14795f449c",
"participant_code": "CUST01",
"platform_code": "PLAT01",
"transaction_id": "vat_9c4e1f7a2b6d3e8f",
"type": "DEPOSIT",
"originator_name": "Leslie Barbara Knope",
"rail": "wire",
"status": "payout_failed",
"external_account_id": "107e8a2a-c835-4b76-b49d-a633d45727b9",
"asset": "USDC.SOL",
"reference": "INV-10432",
"created_at": "2026-08-25T09:10:44Z"
}