External account status updates

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:

ParameterDescriptionType
participant_codeThe Zero Hash identifier for the customerstring
account_nicknameName given to the account. Empty if no nickname was given.string
account_typeIndicates if the account is checking or savingsstring
external_account_idThe unique identifier generated by Zero Hash for the account. This must be used to make subsequent payment requests.string
external_account_statusThe status of the linked account, which indicates if the account can be used or not. Possible values:pending, approved, rejected, closed, locked, disabledstring
status_reasonIf 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.

StatusDescription
pendingAccount creation requested, basic validations passed, and Zero Hash is running identity checks.
approvedIdentity checks passed and the account is created and ready for use.
rejectedIdentity checks failed and the account cannot be used.
closedEither 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

{
  "participant_code": "PAR123",
  "account_nickname": "test",
  "account_type": "checking",
  "external_account_id": "123",
  "external_account_status": "approved",
  "timestamp": 1633456800001
}

Status change: approved

{
  "participant_code": "PAR123",
  "account_nickname": "test",
  "account_type": "savings",
  "external_account_id": "123",
  "external_account_status": "disabled",
  "timestamp": 1633456800003
}

Status change: 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

{
  "participant_code": "PAR123",
  "account_nickname": "test",
  "account_type": "savings",
  "external_account_id": "123",
  "external_account_status": "locked",
  "timestamp": 1633456800002
}

Status change: disabled

{
  "participant_code": "PAR123",
  "account_nickname": "test",
  "account_type": "savings",
  "external_account_id": "123",
  "external_account_status": "disabled",
  "timestamp": 1633456800003
}

Status change: closed

{
  "participant_code": "PAR123",
  "account_nickname": "test",
  "account_type": "savings",
  "external_account_id": "123",
  "external_account_status": "closed",
  "timestamp": 1633456800004
}

Status change: failed

{
  "participant_code": "PAR123",
  "account_nickname": "test",
  "account_type": "savings",
  "external_account_id": "123",
  "external_account_status": "failed",
  "timestamp": 1633456800005
}