---
updatedAt: 2026-09-15T13:11:20.000Z
agentTools:
  projectIndex: https://docs.zerohash.com/llms.txt
---

# Virtual Account Updates

# 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`.

<br />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

### Active

```json
{
  "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

```json
{
  "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

```json
{
  "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

```json
{
  "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

```json
{
  "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`.<br />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

### Deposit Received

Fires when a deposit lands at bank partner and is pending screening before being credited to customer.

```json
{
  "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"
}
```

<Callout icon="far fa-circle-info" theme="info">
  ### Note:

  For Virtual Accounts with the `HOLD` settlement policy, you will also want to subscribe to `account_balance.changed` to see when USD deposits are credited to customer balances (check examples on [Account Balance](https://docs.zerohash.com/zerohash/reference/account-balance)).
</Callout>

### 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`

```json
{
  "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.&#x20;

```json
{
  "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`

```json
{
  "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.

```json
{
  "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`.

```json
{
  "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`.

```json
{
  "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`.

```json
{
  "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"
}
```