Webhook events trigged by linked bank accounts updates.
Platforms leveraging Zero Hash’s ACH product should subscribe to webhooks to know if linked external accounts, via Create external accounts, have been approved.
The x-zh-hook-payload-type
to subscribe for is external_account_status_changed
.
Once a platform is set up to receive external account status webhooks, the payload is a JSON object containing the following fields:
Parameter | Description | Type |
---|---|---|
participant_code | The Zero Hash identifier for the customer | string |
account_nickname | Name given to the account. Empty if no nickname was given. | string |
account_type | Indicates if the account is checking or savings | string |
external_account_id | The unique identifier generated by Zero Hash for the account. This must be used to make subsequent payment requests. | string |
external_account_status | The status of the linked account, which indicates if the account can be used or not. Possible values:pending , approved , rejected , closed , locked , disabled | string |
status_reason | If status = rejected , this field gives more context as to why the account has entered this status. Possible values: UNSPECIFIED ,PARTICIPANT_INFO_UNAVAILABLE , IDENTITY_MATCH_UNAVAILABLE , INVALID_SCORES , PROCESSOR_TOKEN | string |
External account statuses
The following statuses are emitted via webhook. Platforms are notified at account creation and at any point throughout the lifecycle of the account.
Status | Description |
---|---|
pending | Account creation requested, basic validations passed, and Zero Hash is running identity checks. |
approved | Identity checks passed and the account is created and ready for use. |
rejected | Identity checks failed and the account cannot be used. |
closed | Either the account was returned as closed when making a payment request, or the end customer actively closed their account. |
locked* | Zero Hash risk and compliance team was alerted to suspicious activity and locked the account for further investigation. |
disabled* | Zero Hash risk and compliance team investigations resulted in a positive hit of suspicious activity and the team determined that the account can no longer be used. |
*Note: Most often these actions will be at the whole participant level, rather than individually at the account level. See Participant Statuses for more.
Payloads
External accounts can represent both a fiat and a crypto account. The shape of the JSON will allow you to tell them apart:
Blockchain Account
{
"account_nickname": "test-sol",
"external_account_id": "c476a81f-a29f-4e22-88db-1f521d7cf004",
"external_account_status": "pending",
"participant_code": "ABC789",
"timestamp": 1729195673718
}
Bank Account
{
"account_nickname": "Bank of America",
"account_type": "checking",
"external_account_id": "0f68333e-2114-469d-b505-c850d776e063",
"external_account_status": "approved",
"participant_code": "ABC123",
"timestamp": 1729195673718
}
RTP Availability
We support both ACH and RTP networks in the US. The availability of RTP networks may change as banks add support for them. Therefore, we will send you a Webhook notification if you want to start using RTP for that specific account. Generally, RTP is much faster than ACH and offers benefits for your users. Check this page to learn more: Fiat Payments
{
"request_id": "R1234",
"account_id": "AC1234",
"platform_code": "PC1234",
"supported_networks": {
"plaid_supported_networks": {
"rtp": {
"credit": true
}
}
},
"timestamp": 1633456800000
}
Status change
Every time the external account changes statuses, we will notify you via Webhooks. Keep in mind that an external account status can change even long after it was created. Here are all the possible payloads we may send.
Note that the examples above apply to bank accounts, but they also work the same for crypto accounts
Status change: pending
pending
{
"participant_code": "PAR123",
"account_nickname": "test",
"account_type": "checking",
"external_account_id": "123",
"external_account_status": "approved",
"timestamp": 1633456800001
}
Status change: approved
approved
{
"participant_code": "PAR123",
"account_nickname": "test",
"account_type": "savings",
"external_account_id": "123",
"external_account_status": "disabled",
"timestamp": 1633456800003
}
Status change: rejected
rejected
{
"participant_code": "PAR123",
"account_nickname": "test",
"account_type": "checking",
"external_account_id": "123",
"external_account_status": "rejected",
"timestamp": 1633456800001,
"status_reason": "invalid processor token"
}
Status change: locked
locked
{
"participant_code": "PAR123",
"account_nickname": "test",
"account_type": "savings",
"external_account_id": "123",
"external_account_status": "locked",
"timestamp": 1633456800002
}
Status change: disabled
disabled
{
"participant_code": "PAR123",
"account_nickname": "test",
"account_type": "savings",
"external_account_id": "123",
"external_account_status": "disabled",
"timestamp": 1633456800003
}
Status change: closed
closed
{
"participant_code": "PAR123",
"account_nickname": "test",
"account_type": "savings",
"external_account_id": "123",
"external_account_status": "closed",
"timestamp": 1633456800004
}
Status change: failed
failed
{
"participant_code": "PAR123",
"account_nickname": "test",
"account_type": "savings",
"external_account_id": "123",
"external_account_status": "failed",
"timestamp": 1633456800005
}