Wallet API Reference
This page shows all Wallet endpoints in the sequence of integration. Use https://api.sandbox.blox.my for tests. Use https://api.blox.my in production.
A read request must have the blox-api-key header. A write request must have the API key and an HTTP message signature. If an endpoint shows an Idempotency-Key header, the write request must also have that header. Store the Idempotency-Key UUID v4 before you send the first request.
In request bodies, amounts are integers in sen. In responses, amounts are strings. Every error uses { "code": "…", "message": "…", "requestId": "…" }. Use code to identify the error. Do not use message to identify the error. For the error behavior that all endpoints share, see Errors.
| Method | Endpoint | Purpose |
|---|---|---|
GET | /v1/wallet/address | Get the EVM and Solana deposit addresses |
GET | /v1/wallet/balance | Get the available and pending balances |
GET | /v1/wallet/networks | Get the active networks and token IDs |
POST | /v1/wallet/token/withdrawals | Send tokens to an external address |
GET | /v1/wallet/token/withdrawals/{id} | Get the status of one token transfer |
GET | /v1/wallet/bank-accounts | List linked bank accounts |
POST | /v1/wallet/fiat/withdrawals | Withdraw MYR to a linked bank account |
GET | /v1/wallet/fiat/withdrawals/{id} | Get the status of one fiat withdrawal |
POST | /v1/wallet/bank-accounts/{bankAccountId}/address | Create a trigger address for a linked bank account |
GET | /v1/wallet/bank-accounts/{bankAccountId}/address/whitelist | List the allowed senders of a trigger address |
POST | /v1/wallet/bank-accounts/{bankAccountId}/address/whitelist | Allow a sender |
PATCH | /v1/wallet/bank-accounts/{bankAccountId}/address/whitelist/{senderId} | Disable or enable an allowed sender and keep it in the list |
DELETE | /v1/wallet/bank-accounts/{bankAccountId}/address/whitelist/{senderId} | Remove an allowed sender |
GET | /v1/wallet/deposits/{id} | Get a deposit and the fiat withdrawal that it started |
POST | /v1/wallet/deposits/check-missed | Ask BLOX to examine a transaction that BLOX did not detect |
POST | /v1/wallet/deposits/{id}/redrive | Retry a deposit that did not start a fiat withdrawal |
GET | /v1/wallet/transactions | List wallet transactions for reconciliation |
Get wallet address
/v1/wallet/addressAPI keyReturns the deposit addresses of the wallet. If an address does not exist, BLOX creates it automatically.
Response — 200
{
"evmAddress": "0x742d35Cc6634C0532925a3b333Bc9e1234f8bD21",
"solAddress": "DRpbCBMxVnDK7maPM5tGv6MvB3v1sRMC99PZ8okm99hy"
}| Field | Type | Description |
|---|---|---|
evmAddress | string | The deposit address for all supported EVM networks |
solAddress | string | The Solana deposit address |
Error responses
| Status | code | When |
|---|---|---|
401 | UNAUTHORIZED | The API key is missing, unknown, or inactive |
403 | FEATURE_DISABLED | The Wallet API is not enabled for the account |
403 | ACCOUNT_TERMINATED | The account is terminated |
429 | RATE_LIMITED | The number of requests is more than the rate limit of the route or the account |
5xx | INTERNAL_ERROR | An unexpected error occurred at BLOX. Report the requestId to BLOX |
Error examples
401 UNAUTHORIZED
{
"code": "UNAUTHORIZED",
"message": "API key is required",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}Get wallet balance
/v1/wallet/balanceAPI keyReturns the wallet balance that you can use and the pending balance.
Response — 200
{
"walletBalance": "250000",
"pendingWithdrawal": "0"
}| Field | Type | Description |
|---|---|---|
walletBalance | string | The wallet balance that you can use, in sen |
pendingWithdrawal | string | The balance that outgoing withdrawals use at this time, in sen |
Error responses
| Status | code | When |
|---|---|---|
401 | UNAUTHORIZED | The API key is missing, unknown, or inactive |
403 | FEATURE_DISABLED | The Wallet API is not enabled for the account |
403 | ACCOUNT_TERMINATED | The account is terminated |
429 | RATE_LIMITED | The number of requests is more than the rate limit of the route or the account |
5xx | INTERNAL_ERROR | An unexpected error occurred at BLOX. Report the requestId to BLOX |
Error examples
401 UNAUTHORIZED
{
"code": "UNAUTHORIZED",
"message": "API key is required",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}Get supported networks
/v1/wallet/networksAPI keyReturns the active networks and the active tokens on each network. Get the tokenId from this endpoint at runtime. The IDs in sandbox and production are different.
| Query | Type | Required | Description |
|---|---|---|---|
id | string | No | Returns one network, identified by its network ID |
tokenId | string (UUID) | No | Returns the network that contains this token |
Each network has the fields id, name, type, and tokens. Use the id of a token as the tokenId in token transfers and Onramp checkouts. Use EVM tokens with 0x addresses. Use Solana tokens with Base58 addresses.
The Environments & Chains page also shows contract addresses and chain IDs. At runtime, use this endpoint.
Error responses
| Status | code | When |
|---|---|---|
400 | VALIDATION_FAILED | The id or the tokenId has an incorrect format |
401 | UNAUTHORIZED | The API key is missing, unknown, or inactive |
403 | FEATURE_DISABLED | The Wallet API is not enabled for the account |
403 | ACCOUNT_TERMINATED | The account is terminated |
429 | RATE_LIMITED | The number of requests is more than the rate limit of the route or the account |
5xx | INTERNAL_ERROR | An unexpected error occurred at BLOX. Report the requestId to BLOX |
Error examples
400 VALIDATION_FAILED
For a tokenId with an incorrect format:
{
"code": "VALIDATION_FAILED",
"message": "tokenId: Invalid UUID",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}Create token transfer
/v1/wallet/token/withdrawalsAPI key + signatureSends a token from the BLOX wallet to an external address. The limit for this endpoint is 30 requests per minute for each account.
Header
| Header | Required | Description |
|---|---|---|
Idempotency-Key | Yes | A UUID v4 that you store for this token transfer before the first request |
Body
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
tokenId | string (UUID) | Yes | Active token | The ID from GET /v1/wallet/networks |
addressTo | string | Yes | Must be on the network of the token | The wallet address of the recipient |
amount | integer | Yes | 1000–100000000 sen | The total debit from the wallet (RM10–RM1,000,000) |
reference | string | No | Maximum 32 characters | Your reference for reconciliation |
An EVM address has 0x and 40 hexadecimal characters. A Solana address uses Base58. BLOX rejects a token transfer to your own deposit address, to a contract address, or to a different restricted destination.
The amount in the request is the total debit from the wallet. If there is a network fee, BLOX deducts it before delivery. The response shows the net amount and the fee in a separate field.
Response — 200
{
"id": "9b3bd9db-75d8-44dc-a74b-16fe968a01c7",
"status": "CREATED",
"toAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f8bD21",
"amount": "10000",
"fee": "0",
"reference": "ORDER-4471",
"source": "API",
"tokenId": "550e8400-e29b-41d4-a716-446655440000",
"token": {
"symbol": "MYRC",
"name": "MYR Coin",
"network": { "id": "ethereum", "name": "Ethereum", "type": "EVM" }
},
"txHash": null,
"confirmations": null,
"confirmedAt": null,
"createdAt": "2026-01-16T10:30:00.000Z",
"updatedAt": "2026-01-16T10:30:00.000Z"
}The first status of an EVM token transfer is CREATED. The first status of a Solana token transfer is PENDING. For all fields and statuses, see the Token transfer object.
Store one UUID v4 before you send the request. If you get no response, a timeout, 202, or 5xx, send the request again with the same key. For 24 hours, the same key with the same body returns the initial token transfer. The same key with a different body returns 422 CONFLICT. If you get a 4xx, correct the request and use a new key.
Error responses
| Status | code | When |
|---|---|---|
400 | INVALID_REQUEST | BLOX does not accept the idempotency key, the token, or the destination |
400 | VALIDATION_FAILED | The body, the address, the amount, or the reference is not valid |
400 | INSUFFICIENT_BALANCE | The wallet balance is less than the requested debit |
400 | LIMIT_EXCEEDED | The account reached a configured daily or monthly limit |
401 | UNAUTHORIZED | The API key or the request signature is missing or not valid |
403 | FEATURE_DISABLED | The Wallet API is not enabled for the account |
403 | ACCOUNT_FROZEN | The account is frozen |
403 | ACCOUNT_TERMINATED | The account is terminated |
403 | ACCOUNT_PENDING_VERIFICATION | The account is pending verification |
422 | CONFLICT | You used the idempotency key before with a different body |
429 | RATE_LIMITED | There were more than 30 create requests in one minute |
5xx | INTERNAL_ERROR | An unexpected error occurred at BLOX. Report the requestId to BLOX |
Error examples
400 INVALID_REQUEST
{
"code": "INVALID_REQUEST",
"message": "Missing idempotency key",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}400 VALIDATION_FAILED
For a request with amount: 999:
{
"code": "VALIDATION_FAILED",
"message": "amount: Amount can't be less than 10 MYR",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}400 INSUFFICIENT_BALANCE
{
"code": "INSUFFICIENT_BALANCE",
"message": "Insufficient MYRC balance in wallet.",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}400 LIMIT_EXCEEDED
{
"code": "LIMIT_EXCEEDED",
"message": "Daily transaction limit exceeded.",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}401 UNAUTHORIZED
{
"code": "UNAUTHORIZED",
"message": "API key is required",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}403 FEATURE_DISABLED
{
"code": "FEATURE_DISABLED",
"message": "Feature wallet_api is not enabled for this account.",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}403 ACCOUNT_FROZEN
{
"code": "ACCOUNT_FROZEN",
"message": "Your account has been frozen. Please contact support.",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}403 ACCOUNT_TERMINATED
{
"code": "ACCOUNT_TERMINATED",
"message": "Your account has been terminated. Please contact support.",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}403 ACCOUNT_PENDING_VERIFICATION
{
"code": "ACCOUNT_PENDING_VERIFICATION",
"message": "Your account is pending verification. This action is not allowed for this account at this time.",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}422 CONFLICT
{
"code": "CONFLICT",
"message": "Idempotency key used with different request payload",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}429 RATE_LIMITED
{
"code": "RATE_LIMITED",
"message": "Too many token withdrawals. Please try again later.",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}500 INTERNAL_ERROR
{
"code": "INTERNAL_ERROR",
"message": "An unexpected error occurred.",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}Get token transfer
/v1/wallet/token/withdrawals/{id}API keyReturns one token transfer. This endpoint returns the token transfer immediately after you create it. Use this endpoint to monitor the status.
| Path | Type | Description |
|---|---|---|
id | string (UUID) | The id that the create request returned |
Response — 200: Token transfer object. An unknown ID, or an ID that belongs to a different account, returns 404 NOT_FOUND.
While an EVM token transfer is CREATED, GET /v1/wallet/transactions does not show it. Thus, use this endpoint to get the correct status from the time of creation.
Error responses
| Status | code | When |
|---|---|---|
401 | UNAUTHORIZED | The API key is missing, unknown, or inactive |
403 | FEATURE_DISABLED | The Wallet API is not enabled for the account |
403 | ACCOUNT_TERMINATED | The account is terminated |
404 | NOT_FOUND | The token transfer is unknown or belongs to a different account |
429 | RATE_LIMITED | The number of requests is more than the rate limit of the route or the account |
5xx | INTERNAL_ERROR | An unexpected error occurred at BLOX. Report the requestId to BLOX |
Error examples
404 NOT_FOUND
{
"code": "NOT_FOUND",
"message": "Token withdrawal not found",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}List bank accounts
/v1/wallet/bank-accountsAPI keyReturns the active bank accounts that are linked to the BLOX account. To create a fiat withdrawal, use the id of a verified bank account as the bankAccountId.
| Query | Type | Required | Constraints | Description |
|---|---|---|---|---|
search | string | No | — | Filters the results by account name |
limit | integer | No | 1–100, default 25 | The number of records on each page |
cursor | string | No | The last id on the previous page | Do not send for the first page |
Response — 200
{
"data": [
{
"id": "6639e2e8-9d71-4a77-9fd7-34fcd0ce5355",
"name": "Business account",
"accountNumber": "123456789012",
"verified": true,
"bank": { "code": "MBBM", "name": "Maybank" },
"createdAt": "2026-01-10T04:00:00.000Z",
"updatedAt": "2026-01-10T04:00:00.000Z"
}
],
"hasMore": false,
"nextCursor": null
}| Field | Type | Description |
|---|---|---|
id | string (UUID) | Send this value as bankAccountId in a fiat withdrawal |
name | string | The label of the account |
accountNumber | string | The full bank account number. BLOX does not mask it |
verified | boolean | true if BLOX verified the account |
bank | object | null | { code, name } |
createdAt / updatedAt | string | ISO 8601 timestamps |
Send the request again with the next cursor until hasMore is false. The response has no total field.
Error responses
| Status | code | When |
|---|---|---|
400 | VALIDATION_FAILED | A query parameter has an incorrect format or is outside its constraints |
401 | UNAUTHORIZED | The API key is missing, unknown, or inactive |
403 | FEATURE_DISABLED | The Wallet API is not enabled for the account |
403 | ACCOUNT_TERMINATED | The account is terminated |
429 | RATE_LIMITED | The number of requests is more than the rate limit of the route or the account |
5xx | INTERNAL_ERROR | An unexpected error occurred at BLOX. Report the requestId to BLOX |
Error examples
400 VALIDATION_FAILED
For ?limit=101:
{
"code": "VALIDATION_FAILED",
"message": "limit: Number must be less than or equal to 100",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}Create fiat withdrawal
/v1/wallet/fiat/withdrawalsAPI key + signatureSends MYR from the BLOX wallet to a linked bank account. The limit for this endpoint is 30 requests per minute for each account.
Header
| Header | Required | Description |
|---|---|---|
Idempotency-Key | Yes | A UUID v4 that you store for this fiat withdrawal before the first request |
Body
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
bankAccountId | string (UUID) | Yes | An active linked bank account | The ID from GET /v1/wallet/bank-accounts |
amount | integer | Yes | 1000–100000000 sen | The amount of the fiat withdrawal (RM10–RM1,000,000) |
reference | string | No | Maximum 20 characters | Your reference for reconciliation |
For an individual account, the maximum is RM300,000 for each request. A business account can use the full range for each request. Other limits for each account can also apply.
Response — 200
{
"id": "1de31ea3-c2b5-454b-a1f0-547c21738aef",
"status": "PENDING",
"amount": "50000",
"fee": "0",
"reference": "WD-4471",
"refId": "FW-20260116-A1B2C3",
"source": "API",
"destination": {
"name": "ADA LOVELACE",
"accountNumber": "1234567890",
"bank": { "code": "MBBM", "name": "Maybank" }
},
"confirmedAt": null,
"createdAt": "2026-01-16T10:30:00.000Z",
"updatedAt": "2026-01-16T10:30:00.000Z"
}For all fields and statuses, see the Fiat withdrawal object. The idempotency and retry rules are the same as for token transfers. Store the key before you send the request. Use the same key for each retry of the same fiat withdrawal.
Error responses
| Status | code | When |
|---|---|---|
400 | INVALID_REQUEST | BLOX does not accept the idempotency key, or the amount is not permitted for the account |
400 | VALIDATION_FAILED | The body, the amount, or the reference is not valid |
400 | INSUFFICIENT_BALANCE | The wallet balance is less than the withdrawal amount |
400 | LIMIT_EXCEEDED | The account reached a configured daily or monthly limit |
401 | UNAUTHORIZED | The API key or the request signature is missing or not valid |
403 | FEATURE_DISABLED | The Wallet API is not enabled for the account |
403 | ACCOUNT_FROZEN | The account is frozen |
403 | ACCOUNT_TERMINATED | The account is terminated |
403 | ACCOUNT_PENDING_VERIFICATION | The account is pending verification |
404 | NOT_FOUND | The bank account is unknown, is not active, or belongs to a different account |
422 | CONFLICT | You used the idempotency key before with a different body |
429 | RATE_LIMITED | There were more than 30 create requests in one minute |
5xx | INTERNAL_ERROR | An unexpected error occurred at BLOX. Report the requestId to BLOX |
Error examples
400 INVALID_REQUEST
{
"code": "INVALID_REQUEST",
"message": "Missing idempotency key",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}400 VALIDATION_FAILED
For a request with amount: 999:
{
"code": "VALIDATION_FAILED",
"message": "amount: Amount can't be less than 10 MYR",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}400 INSUFFICIENT_BALANCE
{
"code": "INSUFFICIENT_BALANCE",
"message": "Insufficient MYRC balance in wallet.",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}400 LIMIT_EXCEEDED
{
"code": "LIMIT_EXCEEDED",
"message": "Daily transaction limit exceeded.",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}401 UNAUTHORIZED
{
"code": "UNAUTHORIZED",
"message": "API key is required",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}403 FEATURE_DISABLED
{
"code": "FEATURE_DISABLED",
"message": "Feature wallet_api is not enabled for this account.",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}403 ACCOUNT_FROZEN
{
"code": "ACCOUNT_FROZEN",
"message": "Your account has been frozen. Please contact support.",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}403 ACCOUNT_TERMINATED
{
"code": "ACCOUNT_TERMINATED",
"message": "Your account has been terminated. Please contact support.",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}403 ACCOUNT_PENDING_VERIFICATION
{
"code": "ACCOUNT_PENDING_VERIFICATION",
"message": "Your account is pending verification. This action is not allowed for this account at this time.",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}404 NOT_FOUND
{
"code": "NOT_FOUND",
"message": "Bank account not found",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}422 CONFLICT
{
"code": "CONFLICT",
"message": "Idempotency key used with different request payload",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}429 RATE_LIMITED
{
"code": "RATE_LIMITED",
"message": "Too many fiat withdrawals. Please try again later.",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}500 INTERNAL_ERROR
{
"code": "INTERNAL_ERROR",
"message": "An unexpected error occurred.",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}Get fiat withdrawal
/v1/wallet/fiat/withdrawals/{id}API keyReturns one fiat withdrawal. Send GET /v1/wallet/fiat/withdrawals/{id} again until the status is COMPLETED, FAILED, or REJECTED.
| Path | Type | Description |
|---|---|---|
id | string (UUID) | The id that the create request returned |
Response — 200: Fiat withdrawal object. An unknown ID, or an ID that belongs to a different account, returns 404 NOT_FOUND.
Error responses
| Status | code | When |
|---|---|---|
401 | UNAUTHORIZED | The API key is missing, unknown, or inactive |
403 | FEATURE_DISABLED | The Wallet API is not enabled for the account |
403 | ACCOUNT_TERMINATED | The account is terminated |
404 | NOT_FOUND | The fiat withdrawal is unknown or belongs to a different account |
429 | RATE_LIMITED | The number of requests is more than the rate limit of the route or the account |
5xx | INTERNAL_ERROR | An unexpected error occurred at BLOX. Report the requestId to BLOX |
Error examples
404 NOT_FOUND
{
"code": "NOT_FOUND",
"message": "Fiat withdrawal not found",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}Create a deposit trigger address
/v1/wallet/bank-accounts/{bankAccountId}/addressAPI key + signatureCreates a trigger address for a linked bank account. When tokens arrive at this address, BLOX automatically sends a fiat withdrawal to that bank account. You do not send a create request. For more information, see Withdraw automatically on deposit.
The bank account must be active. A bank account has one trigger address for all of its life. If you send this request again, it returns the same address. Thus, an Idempotency-Key is not necessary. The limit for this endpoint is 20 requests per minute.
Success response (201)
{
"address": "0x7c1a3e889d2b4f618a441f0b6d3c9a5588ab01cd",
"network": "EVM",
"destination": {
"type": "BANK_ACCOUNT",
"id": "b21f4c77-3e5a-4d90-9c18-6a2f7e0b4d31"
}
}| Field | Type | Description |
|---|---|---|
address | string | The trigger address. Send supported tokens to this address |
network | string | EVM |
destination.type | string | BANK_ACCOUNT |
destination.id | string (UUID) | The bank account that gets the fiat withdrawal |
Until you allow one or more senders, a deposit to this address does not start a fiat withdrawal.
Expected errors
| Status | code | When |
|---|---|---|
403 | FEATURE_DISABLED | Automatic withdrawal on deposit is not enabled for your account |
404 | NOT_FOUND | The bank account 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/wallet/bank-accounts/{bankAccountId}/address/whitelistAPI keyReturns the allowed senders of the trigger address of this bank account. 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 |
active | boolean | Only deposits from active senders start fiat withdrawals. See disable |
createdAt | string | ISO 8601 |
The list also shows disabled senders. A disabled sender counts in the limit of 50 senders until you remove it.
If the bank account does not have a trigger address, the response is 404 NOT_FOUND.
Allow a sender
/v1/wallet/bank-accounts/{bankAccountId}/address/whitelistAPI key + signatureAdds one allowed sender to the trigger address of this bank account. Deposits from this sender start fiat withdrawals to the bank account. 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. The address is not case-sensitive |
label | string | No | 1–120 characters | Your note. Read requests return it |
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 for this trigger address |
403 | LIMIT_EXCEEDED | The trigger address already has 50 allowed senders |
404 | NOT_FOUND | The bank account does not have a trigger address, or it belongs to a different account |
Disable or re-enable a sender
/v1/wallet/bank-accounts/{bankAccountId}/address/whitelist/{senderId}API key + signatureDisables or enables an allowed sender. A disabled sender stays in the list and keeps its label. After you disable a sender, its deposits do not start fiat withdrawals. This change occurs immediately. You can enable the sender again at a later time.
If you will send from the wallet again, disable the sender. If you will not use the wallet again, remove the sender. Only a removal makes a place available in the limit of 50 senders.
Request body
| Field | Type | Description |
|---|---|---|
active | boolean | false disables the sender. true enables the sender again |
Success response (200)
Returns the 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/wallet/bank-accounts/{bankAccountId}/address/whitelist/{senderId}API key + signatureRemoves the allowed sender. After the removal, deposits from that sender do not start fiat withdrawals. The removal makes a place available in the limit of 50 senders. This change has no effect on deposits that are already in progress. Sign only @method and @path. A Content-Digest is not necessary.
Success response (200)
{ "success": true }If the sender id is unknown or belongs to a different trigger address, the response is 404 NOT_FOUND.
Get a deposit
/v1/wallet/deposits/{id}API keyReturns a deposit. If the deposit started a fiat withdrawal, the response also shows that fiat withdrawal. The deposit webhook sends the same payload.
Success response (200)
{
"id": "5e9d0273-8a41-4c62-b0f7-1d3e8c95a460",
"txHash": "0x5d53558791c9346d644d077354420f9a93600acf54eb806ecb9aad077c103ee3",
"logIndex": 12,
"chainId": 1,
"tokenId": "a71c4e08-2f96-4b3d-85ae-6c0f7d21b943",
"amount": "100000",
"from": "0x9a3f7c21b8e04d6f5a19c2e70b48d3f61a5e9d02",
"status": "COMPLETED",
"confirmations": 24,
"triggerAddress": "0x7c1a3e889d2b4f618a441f0b6d3c9a5588ab01cd",
"destination": {
"type": "BANK_ACCOUNT",
"id": "b21f4c77-3e5a-4d90-9c18-6a2f7e0b4d31",
"name": "ACME SDN BHD"
},
"result": {
"status": "COMPLETED",
"statusReason": null,
"withdrawal": {
"id": "c4a80f13-6d29-4e75-83b1-9f0c2a7e5d68",
"amount": "100000",
"status": "COMPLETED",
"refId": "FW-20260807-0001",
"reference": "ACME payout",
"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 contains the deposit |
logIndex | integer | The position of this deposit in the transaction |
chainId | integer | The chain of the deposit |
tokenId | string (UUID) | The token of the deposit. It matches a token from GET /v1/wallet/networks |
amount | string | The deposit amount, in the smallest unit of the token |
from | string | The address that sent the tokens |
status | string | PENDING before confirmation. PROCESSING after confirmation, until BLOX credits the tokens. COMPLETED after BLOX credits the tokens. FAILED if BLOX did not credit the tokens |
confirmations | integer | The number of confirmations at this time |
triggerAddress | string | null | The trigger address that received the deposit. null if the deposit did not go to a trigger address |
destination | object | null | The bank account that gets the fiat withdrawal, or null |
result | object | null | The result of the automatic withdrawal. null if the deposit did not start a withdrawal |
result.status | string | PENDING, PROCESSING, COMPLETED, or FAILED |
result.statusReason | string | null | The reason for the failure. See Status reason values |
result.withdrawal | object | null | The fiat withdrawal object, after BLOX creates the fiat withdrawal |
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.
If the deposit id is unknown or belongs to a different account, the response is 404 NOT_FOUND.
Deposit status reason values
If result.status is not FAILED, result.statusReason is null.
| Value | Meaning |
|---|---|
sender_not_allowed | The deposit came from an address that is not an allowed sender |
inactive_destination | The bank account was removed or deactivated |
missing_destination_bank_details | BLOX has no bank details for the bank account |
feature_disabled | Automatic withdrawal on deposit is not enabled for your account |
account_frozen, account_suspended, account_terminated | The status of your account stopped the withdrawal |
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 the daily limit |
monthly_fiat_withdrawal_limit_exceeded | Your account reached the monthly limit |
fiat_withdrawal_rejected, fiat_withdrawal_failed, fiat_withdrawal_cancelled | The fiat withdrawal did not complete |
provider_error | The payment network reported a different error. Contact BLOX and give the deposit id |
In all cases, the tokens stay in your wallet balance. If you can correct the cause, correct it and then retry the deposit. For example, allow the sender, activate the bank account again, or wait for the start of the next daily or monthly limit period.
Check for a missed deposit
/v1/wallet/deposits/check-missedAPI key + signatureAsks BLOX to examine a transaction that BLOX did not detect. Use this endpoint if you sent tokens and no deposit appeared.
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 for this endpoint is 30 requests per minute.
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
txHash | string | Yes | 0x and 64 hex characters | The hash of the transaction that contains 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 if BLOX accepted the transaction for processing. ALREADY_DETECTED if BLOX detected the transaction before |
depositIds | string[] | The ids of the deposits in the transaction. The array has values for ALREADY_DETECTED and is empty for QUEUED |
Read status before you read depositIds. For QUEUED, an empty array means that the deposits do not exist yet. It does not mean that BLOX found no deposits. One transaction can contain more than one deposit. If the status is 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 | Automatic withdrawal on deposit is not enabled for your account |
404 | NOT_FOUND | No active BLOX network matches chainId |
429 | RATE_LIMITED | More than 30 requests in the last minute |
Retry a deposit
/v1/wallet/deposits/{id}/redriveAPI key + signatureExamines again a deposit that BLOX credited but that did not start a fiat withdrawal. Use this endpoint after you correct the cause. For example, allow the sender, activate the bank account again, or wait for the start of the next daily or monthly limit period.
You can send this request more than one time with no risk. If the deposit already started a fiat withdrawal, the response shows that fiat withdrawal. BLOX does not create a second fiat withdrawal. The limit for this endpoint is 60 requests per minute.
This request has no body. Sign only @method and @path.
Success response (201)
Returns the deposit after the retry, in the same format as Get a deposit.
Expected errors
| Status | code | When |
|---|---|---|
400 | INVALID_REQUEST | The deposit status is not COMPLETED yet. There is nothing to retry |
403 | FEATURE_DISABLED | Automatic withdrawal on deposit is not enabled for 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 |
List wallet transactions
/v1/wallet/transactionsAPI keyReturns the wallet transactions. The newest transaction is first. Use this endpoint for history and reconciliation. To monitor one withdrawal, use the read endpoint for that resource.
| Query | Type | Required | Constraints | Description |
|---|---|---|---|---|
startDt | string | No | ISO 8601 datetime | Created on or after this time |
endDt | string | No | ISO 8601 datetime | Created on or before this time |
type | string | No | IN or OUT | The direction of the transaction |
mode | string | No | FIAT or TOKEN | The mode of the transaction |
limit | integer | No | 1–100, default 25 | The number of records on each page |
cursor | string | No | The nextCursor from the previous response | Do not send for the first page |
Response — 200
{
"data": [
{
"transactionId": "9b3bd9db-75d8-44dc-a74b-16fe968a01c7",
"type": "OUT",
"mode": "TOKEN",
"status": "PENDING",
"amount": "-10000",
"fee": "0",
"effectiveAmount": "-10000",
"beneficiary": "0x742d35Cc6634C0532925a3b844Bc9e7595f8bD21",
"reference": "ORDER-4471",
"refId": "",
"source": "API",
"networkId": "ethereum",
"createdAt": "2026-01-16T10:30:00.000Z",
"confirmedAt": null
}
],
"hasMore": true,
"nextCursor": "MjAyNi0wMS0xNlQxMDozMDowMC4wMDBafDliM2Jk…"
}Send nextCursor as cursor in the next request. Do this until hasMore is false. The response has no total field. Treat each cursor as an opaque string. The response does not show a transaction that has the status CREATED. It shows the transaction after the status changes.
| Field | Type | Description |
|---|---|---|
transactionId | string (UUID) | The identifier of the wallet transaction |
type | string | IN or OUT |
mode | string | FIAT or TOKEN |
status | string | The status of the transaction at this time |
amount | string | Signed amount in sen |
fee | string | Fee in sen |
effectiveAmount | string | The net signed change to the wallet balance, in sen |
beneficiary | string | null | The destination address, the bank account, or a different recipient label |
reference | string | null | Your reference for reconciliation |
refId | string | The BLOX reference, if it is available |
source | string | The source of the transaction, for example API |
networkId | string | null | The blockchain network of a token transaction |
createdAt | string | ISO 8601 creation timestamp |
confirmedAt | string | null | ISO 8601 completion timestamp |
Error responses
| Status | code | When |
|---|---|---|
400 | VALIDATION_FAILED | A query parameter has an incorrect format or is outside its constraints |
401 | UNAUTHORIZED | The API key is missing, unknown, or inactive |
403 | FEATURE_DISABLED | The Wallet API is not enabled for the account |
403 | ACCOUNT_TERMINATED | The account is terminated |
429 | RATE_LIMITED | The number of requests is more than the rate limit of the route or the account |
5xx | INTERNAL_ERROR | An unexpected error occurred at BLOX. Report the requestId to BLOX |
Error examples
400 VALIDATION_FAILED
For ?limit=101:
{
"code": "VALIDATION_FAILED",
"message": "limit: Number must be less than or equal to 100",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}Shared response schemas
Token transfer object
| Field | Type | Description |
|---|---|---|
id | string (UUID) | The unique identifier of the token transfer |
status | string | CREATED, PENDING, PROCESSING, COMPLETED, or FAILED |
toAddress | string | The wallet address of the recipient |
amount | string | The net amount that the recipient gets, in sen |
fee | string | The fee that BLOX deducted from the requested amount, in sen |
reference | string | null | Your reference for reconciliation |
source | string | API for token transfers that you created through the API |
tokenId | string (UUID) | The identifier of the token |
token | object | { symbol, name, network: { id, name, type } } |
txHash | string | null | The on-chain transaction hash, after BLOX sends the transaction to the network |
confirmations | number | null | The number of confirmations at this time |
confirmedAt | string | null | ISO 8601 completion time |
createdAt / updatedAt | string | ISO 8601 timestamps |
Fiat withdrawal object
| Field | Type | Description |
|---|---|---|
id | string (UUID) | The unique identifier of the fiat withdrawal |
status | string | PENDING, PROCESSING, COMPLETED, FAILED, or REJECTED |
amount | string | The amount of the fiat withdrawal, in sen |
fee | string | The fee of the fiat withdrawal, in sen |
reference | string | null | Your reference for reconciliation |
refId | string | The BLOX reference for the fiat withdrawal. Give this reference when you contact BLOX support |
source | string | API for fiat withdrawals that you created through the API |
destination | object | null | { name, accountNumber, bank: { code, name } } |
confirmedAt | string | null | ISO 8601 completion time |
createdAt / updatedAt | string | ISO 8601 timestamps |