Onchain Trigger
Create a trigger address for a beneficiary. When you send tokens to this address, BLOX converts the tokens and pays the beneficiary. The deposit starts the transfer and also supplies the money for it. Thus, your prefund balance stays available for the payouts that you create. For the procedure, refer to Pay a beneficiary from a deposit.
Two records show one flow of money. The deposit is the tokens that arrive on-chain. The transfer is the bank payment that the deposit starts. The deposit shows the transfer in result.withdrawal. The transfer has its own status.
The trigger address accepts a deposit only from an allowed sender. Before you give the trigger address to a sender, allow that sender.
A read request must have the blox-api-key header. A write request must have the API key and an HTTP message signature. Every error response has the format { "code": "…", "message": "…", "requestId": "…" }. Use code to identify the error. Do not use message.
| Method | Endpoint | Purpose |
|---|---|---|
POST | /v1/payouts/beneficiaries/{beneficiaryId}/address | Create a trigger address for a beneficiary |
GET | /v1/payouts/beneficiaries/{beneficiaryId}/address/whitelist | List the allowed senders of a trigger address |
POST | /v1/payouts/beneficiaries/{beneficiaryId}/address/whitelist | Allow a sender |
PATCH | /v1/payouts/beneficiaries/{beneficiaryId}/address/whitelist/{senderId} | Disable or enable an allowed sender and keep it in the list |
DELETE | /v1/payouts/beneficiaries/{beneficiaryId}/address/whitelist/{senderId} | Remove an allowed sender |
GET | /v1/payouts/deposits/{id} | Get a deposit and the transfer that it started |
POST | /v1/payouts/deposits/check-missed | Tell BLOX to examine a transaction that BLOX did not detect |
POST | /v1/payouts/deposits/{id}/redrive | Retry a deposit that did not start a transfer |
Create a deposit trigger address
/v1/payouts/beneficiaries/{beneficiaryId}/addressAPI key + signatureCreates the trigger address for a beneficiary. The beneficiary must be active. A beneficiary has one trigger address for its lifetime. If you send this request again, BLOX returns the same address. Thus, an Idempotency-Key is not necessary.
The limit is 20 requests each minute. When you delete the beneficiary, BLOX deactivates its trigger address.
Success response (201)
{
"address": "0x7c1a3e889d2b4f618a441f0b6d3c9a5588ab01cd",
"network": "EVM",
"destination": {
"type": "BENEFICIARY",
"id": "7c1a3e88-9d2b-4f61-8a44-1f0b6d3c9a55"
}
}| Field | Type | Description |
|---|---|---|
address | string | The trigger address. Send supported tokens to this address |
network | string | EVM |
destination.type | string | BENEFICIARY |
destination.id | string (UUID) | The beneficiary that BLOX pays |
The trigger address does not accept a deposit until you allow at least one sender. The same value is in autoWithdrawalAddress on the Beneficiary object.
Expected errors
| Status | code | When |
|---|---|---|
403 | FEATURE_DISABLED | The feature to pay a beneficiary from a deposit is not enabled on your account |
404 | NOT_FOUND | The beneficiary is unknown, belongs to a different account, or is not active |
429 | RATE_LIMITED | More than 20 requests in the last minute |
List allowed senders
/v1/payouts/beneficiaries/{beneficiaryId}/address/whitelistAPI keyReturns the allowed senders of the beneficiary's trigger address. The oldest sender is first.
Success response (200)
[
{
"id": "3f8c1d02-5b47-4a6e-91cd-77e2b0a4f915",
"address": "0x9a3f7c21b8e04d6f5a19c2e70b48d3f61a5e9d02",
"label": "Treasury wallet",
"active": true,
"createdAt": "2026-08-07T09:31:05.000Z"
}
]| Field | Type | Description |
|---|---|---|
id | string (UUID) | Use this value to disable or remove the sender |
address | string | The sender address in lowercase |
label | string | null | Your note for the sender |
active | boolean | BLOX accepts deposits only from active senders. Refer to disable |
createdAt | string (ISO 8601) | The time that you created the allowed sender |
The list also contains disabled senders. Disabled senders count toward the limit of 50 senders until you remove them.
If the beneficiary does not have a trigger address, BLOX returns 404 NOT_FOUND.
Allow a sender
/v1/payouts/beneficiaries/{beneficiaryId}/address/whitelistAPI key + signatureAllows one sender address to start transfers to this beneficiary. A trigger address can have a maximum of 50 allowed senders.
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
address | string | Yes | 0x and 40 hex characters | The address that you send tokens from. Letter case is not important |
label | string | No | 1–120 characters | Your note for the sender. BLOX returns it in read responses |
Success response (201)
Returns the new allowed sender in the same format as List allowed senders.
Expected errors
| Status | code | When |
|---|---|---|
400 | VALIDATION_FAILED | address is not a valid address, or label is longer than 120 characters |
400 | CONFLICT | The address is already an allowed sender of this trigger address |
403 | LIMIT_EXCEEDED | The trigger address already has 50 allowed senders |
404 | NOT_FOUND | The beneficiary does not have a trigger address, or belongs to a different account |
Disable or re-enable a sender
/v1/payouts/beneficiaries/{beneficiaryId}/address/whitelist/{senderId}API key + signatureDisables or enables an allowed sender. The sender stays in the list and keeps its label. A disabled sender does not start transfers. This change has an immediate effect. You can enable a disabled sender again.
Use this endpoint for a wallet that you will send from again. If you will not send from a wallet again, remove the sender. Only removal makes the place of the sender available in the limit of 50 senders.
Request body
| Field | Type | Description |
|---|---|---|
active | boolean | Set false to disable the sender. Set true to enable it again |
Success response (200)
Returns the allowed sender in the same format as List allowed senders.
Expected errors
| Status | code | When |
|---|---|---|
400 | VALIDATION_FAILED | active is missing or is not a boolean |
403 | ACCOUNT_FROZEN | The account is frozen. You can still remove a sender |
403 | ACCOUNT_PENDING_VERIFICATION | The account is pending verification |
404 | NOT_FOUND | The sender id is unknown or belongs to a different trigger address |
Remove an allowed sender
/v1/payouts/beneficiaries/{beneficiaryId}/address/whitelist/{senderId}API key + signatureRemoves the allowed sender. BLOX stops accepting deposits from that sender. The place of the sender in the limit of 50 senders becomes available. This change does not affect deposits that the sender sent before the removal. Sign only @method and @path. A Content-Digest header is not necessary.
Success response (200)
{ "success": true }If the sender id is unknown or belongs to a different trigger address, BLOX returns 404 NOT_FOUND.
Get a deposit
/v1/payouts/deposits/{id}API keyReturns a deposit to a trigger address and the transfer that the deposit started. The deposit webhook event sends the same payload.
Use the endpoint of the channel that received the deposit. To get a deposit that BLOX paid into your own bank account, use GET /v1/wallet/deposits/{id}.
Success response (200)
{
"id": "5e9d0273-8a41-4c62-b0f7-1d3e8c95a460",
"txHash": "0x5d5355...103ee3",
"logIndex": 12,
"chainId": 1,
"tokenId": "a71c4e08-2f96-4b3d-85ae-6c0f7d21b943",
"amount": "100000",
"from": "0x9a3f7c21b8e04d6f5a19c2e70b48d3f61a5e9d02",
"status": "COMPLETED",
"confirmations": 24,
"triggerAddress": "0x7c1a3e889d2b4f618a441f0b6d3c9a5588ab01cd",
"destination": {
"type": "BENEFICIARY",
"id": "7c1a3e88-9d2b-4f61-8a44-1f0b6d3c9a55",
"name": "ADA LOVELACE"
},
"result": {
"status": "COMPLETED",
"statusReason": null,
"withdrawal": {
"id": "c4a80f13-6d29-4e75-83b1-9f0c2a7e5d68",
"amount": "100000",
"status": "COMPLETED",
"refId": "FW-20260807-0001",
"reference": "Invoice 4471",
"createdAt": "2026-08-07T09:31:05.000Z",
"updatedAt": "2026-08-07T09:34:22.000Z"
}
},
"createdAt": "2026-08-07T09:30:44.000Z",
"updatedAt": "2026-08-07T09:34:22.000Z"
}| Field | Type | Description |
|---|---|---|
id | string (UUID) | The deposit id |
txHash | string | The hash of the transaction that sent the deposit |
logIndex | integer | The log position of the deposit in the transaction |
chainId | integer | The chain of the deposit |
tokenId | string (UUID) | The token of the deposit |
amount | string | The deposit amount in the smallest unit of the token |
from | string | The address that sent the tokens |
status | string | PENDING: the transaction is not confirmed. PROCESSING: the transaction is confirmed and the tokens are not credited. COMPLETED: the tokens are credited. FAILED: BLOX did not credit the tokens |
confirmations | integer | The number of confirmations at this time |
triggerAddress | string | The trigger address that received the deposit |
destination | object | The beneficiary that BLOX pays |
result | object | null | The result of the transfer |
result.status | string | PENDING, PROCESSING, COMPLETED, or FAILED |
result.statusReason | string | null | The reason for the failure. Refer to Deposit status reason values |
result.withdrawal | object | null | The transfer. null until BLOX creates the transfer |
amount and result.withdrawal.amount use different units. amount is in the smallest unit of the token. result.withdrawal.amount is in sen. Read each value from its own field.
A transfer is not in the GET /v1/payouts response. A transfer does not use your prefund balance.
If the deposit id is unknown, belongs to a different account, or identifies a deposit that BLOX paid into your own bank account, BLOX returns 404 NOT_FOUND.
Deposit status reason values
If result.status is not FAILED, result.statusReason is null. These values are different from the payout status reason values. The payout values apply to a payout that you create.
| Value | Meaning |
|---|---|
sender_not_allowed | The deposit is from an address that is not an allowed sender |
inactive_destination | The beneficiary is deleted or not active |
missing_destination_bank_details | The beneficiary does not have bank account details |
feature_disabled | The feature to pay a beneficiary from a deposit is not enabled on your account |
account_frozen, account_suspended, account_terminated | The status of your account stopped the transfer |
withdrawal_amount_out_of_range | The amount is less than the minimum or more than the maximum for your account |
daily_fiat_withdrawal_limit_exceeded | Your account reached its daily limit |
monthly_fiat_withdrawal_limit_exceeded | Your account reached its monthly limit |
fiat_withdrawal_rejected, fiat_withdrawal_failed, fiat_withdrawal_cancelled | The transfer to the bank account did not complete |
proxy_destination_not_supported | The beneficiary has a DuitNow proxy. A transfer from a deposit can go only to a bank account. Use a beneficiary that has a bank account, or pay the proxy with Create payout |
provider_error | The payment network reported a different error. Contact BLOX and give the deposit id |
Older deposits can show inactive_beneficiary or missing_beneficiary_bank_details. These are the old names for inactive_destination and missing_destination_bank_details.
In all cases, the tokens stay credited to your wallet. If you can correct the cause, correct it and retry the deposit.
Check for a missed deposit
/v1/payouts/deposits/check-missedAPI key + signatureTells BLOX to examine a transaction that BLOX did not detect. Use this endpoint if you sent tokens to a trigger address and you did not get a payout.deposit.updated webhook event.
This is the only endpoint that accepts a transaction hash. If BLOX already detected the transaction, the response contains the deposit ids. Use these ids with Get a deposit and Retry a deposit. The limit is 30 requests each minute.
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
txHash | string | Yes | 0x and 64 hex characters | The hash of the transaction that sent the deposit |
chainId | integer | Yes | An active BLOX network | The chain of the transaction |
Success response (201)
{
"status": "ALREADY_DETECTED",
"depositIds": ["5e9d0273-8a41-4c62-b0f7-1d3e8c95a460"]
}| Field | Type | Description |
|---|---|---|
status | string | QUEUED: BLOX accepted the transaction for processing. Wait for the webhook event. ALREADY_DETECTED: BLOX detected the transaction before this request |
depositIds | string[] | The ids of the deposits in the transaction. The array has values on ALREADY_DETECTED and is empty on QUEUED |
Read status before you read depositIds. On QUEUED, an empty array means that the deposits do not exist yet. It does not mean that BLOX found no deposits. One transaction can pay more than one beneficiary. On QUEUED, wait for the webhook event. Do not send the request again.
Expected errors
| Status | code | When |
|---|---|---|
400 | VALIDATION_FAILED | txHash is not a valid hash, or chainId is not a positive integer |
403 | FEATURE_DISABLED | The feature to pay a beneficiary from a deposit is not enabled on your account |
404 | NOT_FOUND | chainId does not match an active BLOX network |
429 | RATE_LIMITED | More than 30 requests in the last minute |
Retry a deposit
/v1/payouts/deposits/{id}/redriveAPI key + signatureTries again to start a transfer for a credited deposit that did not start a transfer. Use this endpoint after you correct the cause. For example, allow the sender, activate the beneficiary again, or wait until the limit period resets.
You can send this request more than one time. If the deposit already has a transfer, the response contains that transfer. BLOX does not create a second transfer. The limit is 60 requests each minute.
Do not send a request body. Sign only @method and @path.
Success response (201)
Returns the deposit in the same format as Get a deposit. The response shows the deposit after the retry.
Expected errors
| Status | code | When |
|---|---|---|
400 | INVALID_REQUEST | The deposit status is not COMPLETED. BLOX cannot retry the deposit |
403 | FEATURE_DISABLED | The feature to pay a beneficiary from a deposit is not enabled on your account |
404 | NOT_FOUND | The deposit is unknown, belongs to a different account, or did not go to a trigger address |
429 | RATE_LIMITED | More than 60 requests in the last minute |
Webhook events
BLOX sends two webhook events about this flow to your PAYOUT webhook endpoint. A deposit starts the transfer. These webhook events tell you about each deposit and its transfer. The payout.created and payout.updated webhook events are for the payouts that you create with POST /v1/payouts.
| Event | Sent when |
|---|---|
payout.deposit.updated | A deposit to a trigger address is confirmed on chain, is credited, or is retried |
payout.withdrawal.updated | A transfer from a deposit changes status |
For the envelope, signature verification, retries, and URL rules, refer to Payout Webhook Events and Webhooks.
payout.deposit.updated
{
"id": "5e9d0273-...",
"txHash": "0x5d5355...103ee3",
"logIndex": 12,
"chainId": 1,
"tokenId": "a71c4e08-...",
"amount": "100000",
"from": "0x9a3f7c21b8e04d6f5a19c2e70b48d3f61a5e9d02",
"status": "COMPLETED",
"confirmations": 24,
"triggerAddress": "0x7c1a3e889d2b4f618a441f0b6d3c9a5588ab01cd",
"destination": { "type": "BENEFICIARY", "id": "7c1a3e88-...", "name": "ADA LOVELACE" },
"result": { "status": "FAILED", "statusReason": "sender_not_allowed", "withdrawal": null },
"createdAt": "2026-08-07T09:30:44.000Z",
"updatedAt": "2026-08-07T09:34:22.000Z"
}The fields are the same as in the REST response. For the full table, refer to GET /v1/payouts/deposits/{id}. For the reason values, refer to deposit status reason values.
BLOX sends this webhook event two times for each deposit. The status in the payload identifies the event:
status | When | result |
|---|---|---|
PROCESSING | The deposit transaction is confirmed on chain. The tokens are not in your balance. | null |
COMPLETED | The tokens are credited to your wallet. BLOX decided the result of the transfer. | The result of the transfer, or null if the deposit did not start a transfer |
Only COMPLETED means that the tokens are in your wallet. BLOX usually credits the tokens a few minutes after confirmation. On Ethereum, this takes longer when network fees are high.
A retry can send a PROCESSING event after the COMPLETED event for the same deposit. If your record of a deposit is COMPLETED, do not change it to a different status.
If BLOX refuses a deposit for a reason that you can correct, the COMPLETED event shows the reason. You can retry that deposit. BLOX also sends this webhook event for deposits on Solana. For Solana, txHash is the transaction signature (base58), and chainId is 101.
payout.withdrawal.updated
{
"withdrawalId": "c4a80f13-...",
"status": "COMPLETED",
"statusReason": null,
"amount": "100000",
"refId": "FW-20260807-0001",
"reference": "Invoice 4471",
"destination": { "type": "BENEFICIARY", "id": "7c1a3e88-...", "name": "ADA LOVELACE" },
"depositId": "5e9d0273-...",
"createdAt": "2026-08-07T09:31:05.000Z",
"updatedAt": "2026-08-07T09:34:22.000Z"
}| Field | Description |
|---|---|
withdrawalId | The id of the transfer |
status | PENDING, PROCESSING, COMPLETED, REJECTED, FAILED, or CANCELLED |
statusReason | Has a value only on REJECTED, FAILED, and CANCELLED |
amount | The amount in sen, as a string |
refId | The bank reference |
reference | Your reference, if you set one |
destination | The beneficiary that BLOX pays |
depositId | The id of the deposit that started the transfer. Use this value to connect the two webhook events |
These transfers are different from payouts. A withdrawalId is not a payoutId. If you use a withdrawalId with GET /v1/payouts/{id}, BLOX returns 404.