Supported HOP Events
Subscribe through Create Webhook Endpoint or Update Webhook Endpoint. These events are emitted today:
A trading-account payout rejected at creation for
INSUFFICIENT_FUNDS or CREDIT_LIMIT_EXCEEDED emits payout.failed without a preceding payout.created. Match data.id to error.details.payout_id from the create response.
Reserved event names
The API accepts these subscriptions, but neither event is emitted today:Unsupported event names
Any other event name is rejected with422 Unprocessable Entity when you create or update an endpoint. Withdrawals raise payout.* events; withdraw.* is not an event family.
Example: unsupported withdraw.completed subscription
Example: unsupported withdraw.completed subscription
Event Envelope
Every delivery is an HTTPPOST whose JSON body follows this envelope:
Envelope fields
Delivery headers
The request also includes these headers:
See Webhook Security before accepting a delivery.
Payin Payload
Event:payin.received
data is the payin object exactly as the Payins API returns it, with every field present. Fields that do not apply are null, not omitted.
- Status:
pending,completed,failed, orvoided. - Credited balance:
deposit_destinationis{"type": "trading_account"}or{"type": "virtual_account", "virtual_account_id": "va_…"}.
Payin fields
Payin fields
- Identifiers:
id,object,account_id. - Amount:
amount,currency,amount_in_usd. - State:
status,payin_type. - Deposit:
deposit_destination,payment_rail,note. - Crypto:
network,txn_hash,destination_wallet_id,destination_address,source_address. - Sender:
sender_name,sender_account_masked,sender_bank_code,sender_country. - Lifecycle:
initiated_at,completed_at,failed_at,failed_reason,voided_at,voided_reason. - Audit:
created,updated,created_by,updated_by.
Example: payin.received
Example: payin.received
Payout Payload
Events:payout.created, payout.completed, payout.failed
These events cover both payouts and withdrawals. data.funding_source.type tells them apart.
- Resource shape:
datais the expanded payout object, matching an item in List Payouts. Get Payout returns a different shape. - Nested resources:
beneficiaryandpayout_destinationare included. Each isnullwhen the payout was created without that stored resource. - Account context:
account_idappears only in the envelope, never insidedata. - Status:
pending_approval,pending,processing,completed,failed,cancelled,returned, orvoided. Apayout.faileddelivery hasdata.statusoffailedorcancelled.
status through the Payouts API.
Payout fields
Payout fields
- Identifiers:
id,object. - Recipient:
beneficiary,payout_destination. - Amount and fee:
amount,currency,amount_in_usd,platform_fee. - Funding:
funding_source. - State:
status,payout_type. - Tracking:
tracking_details(uetr,imad,omad,trace_number), the compatibility fielduetr,network,txn_hash,note. - Lifecycle:
initiated_at,submitted_at,completed_at,failed_at,failed_reason,voided_at,voided_reason. - Audit:
created,updated,created_by,updated_by.
Example: payout.completed
Example: payout.completed
Transfer Payload
Event:transfer.completed
data is the transfer object. Its id starts with trf_. Each leg (source and destination) is {"type": "trading_account"} or {"type": "virtual_account", "virtual_account_id": "va_…"}.
Transfer fields
Transfer fields
- Identifiers:
id,object,account_id. - Balances:
source,destination. - Amount:
amount,currency. - State:
status. - References:
reference,internal_note. - Audit:
created,updated,created_by,updated_by.
Example: transfer.completed
Example: transfer.completed
Account Payload
Events:account.created, account.updated
- Creation:
account.createdcovers the default account Hop provisions when your customer is approved and every end-customer account a platform creates through the API. The latter echoes your own request, so a service that only listens to webhooks still sees every account; match it to your request bydata.id. - Updates:
account.updatedis sent only when Hop changes the account’sstatus. Your own API updates and changes to other fields do not emit it. - Identity and balances:
legal_name,business_registration_number,address,created_by, andupdated_byare alwaysnull. Read identity through the Accounts API.balancesis always an empty array. - Identifier and status:
idstarts withacct_;statusisactive,suspended, ordeactivated.
Account fields
Account fields
- Identifiers and name:
id,object,customer_id,name. - State:
status. - Identity:
legal_name,business_registration_number,address. - Balances:
balances. - Audit:
created,updated,created_by,updated_by.
Example: account.updated
Example: account.updated
Payout Destination Payload
Event:payout_destination.updated
data is the payout destination exactly as the Payout Destinations API returns it, so account numbers and wallet addresses stay masked. Fields that do not apply are null, not omitted.
The event fires on every change Hop makes to a destination, wallet or bank:
- Hop approves a wallet:
statusmoves frompendingtoactive, and payouts to it can be created from then on. - Hop rejects a wallet:
statusmoves frompendingtodisabled, and the wallet cannot be paid. - Hop corrects a destination’s details or status.
active is rejected with 422 PAYOUT_DESTINATION_INACTIVE.
Example: payout_destination.updated
Example: payout_destination.updated
Virtual Account Payload
Events:virtual_account.created, virtual_account.updated
data is the virtual account exactly as Get Virtual Account returns it, with balances as they stood when the event was sent.
- Creation:
virtual_account.createdis sent for every virtual account opened on your accounts. One you open through the API echoes your own request; one Hop opens for you is announced only here. It is alwayspendingwith every bank detailnull, so do not publish it as funding instructions. - Updates:
virtual_account.updatedis sent when the virtual account’sstatuschanges.pendingtoactivemeans the bank details have been issued andprovisioned_atis set: share them with payers from then on.activetofrozenand back means Hop blocked or released balance movements, anddisabledmeans Hop closed the virtual account. Balance changes do not emit it (usepayin.*andpayout.*), and neither do label changes you make. - Order and duplicates: deliveries can repeat or arrive out of order. Each one carries the virtual account as it stood when the event was sent, so keep the one with the latest
updatedfor eachdata.id, and read the virtual account when in doubt.
Example: virtual_account.updated (activated)
Example: virtual_account.updated (activated)
Virtual Account Group Payload
Events:virtual_account_group.created, virtual_account_group.updated
data is the group exactly as Get Virtual Account Group returns it, including requirements and the agreements summary.
- Creation:
virtual_account_group.createdis sent for every group opened on your accounts. A group you open through the API echoes your own request; a group Hop opens for you is announced only here. Match it bydata.id. - Updates:
virtual_account_group.updatedis sent whenever the group’sstatus,onboarding_statusorrequirementschange: onboarding needs more information (onboarding_statusisaction_neededandrequirementslists what to provide), moves to review, is approved or rejected, or Hop enables or disables the group. Your own changes, such as updating the account, uploading a document or accepting agreements, emit it once they change the group’s status or requirements. - Order and duplicates: deliveries can repeat or arrive out of order. Each one carries the group as it stood when the event was sent, so keep the one with the latest
updatedfor eachdata.id, and read the group when in doubt. - First events: opening a group usually sends
virtual_account_group.createdfollowed shortly byvirtual_account_group.updatedas the first requirements arrive.
Example: virtual_account_group.updated
Example: virtual_account_group.updated