Appearance
Wallets and multisend
Read the smart wallets available to your integration, then use multiSendFromWallet to send from one wallet to several EVM destinations. Each batch executes atomically on one chain and returns a job ID for tracking.
Read available wallets
AgioCard_vw_partner_wallet exposes wallets within your managed customer scope. Use their IDs and token balances when constructing a transfer.
graphql
query Wallets($offset: Int!) {
AgioCard_vw_partner_wallet(order_by: { id: asc }, limit: 20, offset: $offset) {
id
wallet_address
chain_id
chain_name
status
wallet_type
total_balance_usd
token_balances {
token_chain_id
chain_id
token_symbol
token_balance
token_balance_usd
token_address
is_native
decimals
smart_wallet_trading_enabled
verified
}
}
}json
{ "offset": 0 }Increase offset by 20 until the page is shorter than 20. Add where: { id: { _eq: 1234 } } to look up a known wallet.
| Field | Use |
|---|---|
Wallet id | Numeric sourceWalletId for multisend |
Wallet chain_id | Wallet registration network |
Token token_chain_id | Agio asset-and-chain record ID; use as tokenChainId |
Token chain_id | Execution network for that token |
token_balance | Amount held, in token units |
token_balance_usd | USD value of the token balance |
smart_wallet_trading_enabled, verified | Both must be true for multisend eligibility |
tokenChainId is an Agio record ID, not an EVM chain number. A wallet's registration chain can also differ from the execution chain. Select the token record for the network you intend to use.
Send a batch
graphql
mutation SendBatch($input: MultiSendFromWalletInput!) {
multiSendFromWallet(input: $input) {
success
jobId
alreadyEnqueued
retryAfterSec
errorCode
errorMessage
}
}json
{
"input": {
"sourceWalletId": 1234,
"transfers": [
{ "tokenChainId": 42, "destination": "0x1111111111111111111111111111111111111111", "amount": "100.5" },
{ "tokenChainId": 42, "destination": "0x2222222222222222222222222222222222222222", "amount": "250" }
],
"idempotencyKey": "9bc10f33-52d5-4816-a34d-24a580790c61"
}
}The source wallet must be accessible to your partner organization. Every transfer must resolve to the same execution chain; split transfers across chains into separate batches. Destinations must be valid nonzero EVM addresses. amount is a positive decimal string in token units and cannot exceed the token's decimal precision.
After success: true, store jobId and poll the job. A success: false result means the request did not complete successfully; inspect its code and, after an uncertain internal failure, check the existing batch before submitting again.
Retry the same batch
Choose a globally unique idempotencyKey, such as a UUID, for each logical batch and persist it before submitting. Reuse that exact key and payload after a timeout. A repeated key refers to the existing job, even if the submitted payload changes; do not use one key for different transfers.
The key is optional, at most 128 characters, and contains no whitespace. When omitted, Agio derives it from your partner organization, source wallet, and normalized transfers. Amounts such as "100.5" and "100.50" normalize to the same base units. To intentionally send an otherwise identical second batch, give it a new explicit key.
A duplicate submission normally returns success: true, alreadyEnqueued: true, and the original jobId. Poll that job. Changing the key after an uncertain outcome can send the funds twice.
Poll job status
graphql
query BatchStatus($jobId: String!) {
multiSendJobStatus(jobId: $jobId) {
success
jobId
status
txHash
failedReason
attempts
errorCode
errorMessage
}
}json
{ "jobId": "<multisend jobId>" }| Status | Action |
|---|---|
pending, running | Wait and poll again |
submitted | Keep checking the same job; broadcast may already have occurred |
completed | Record txHash and reconcile destination balances |
failed | Read the diagnostic and resolve the failure before creating another batch |
insufficient_balance | Fund the source wallet, then create a new logical batch |
Poll every few seconds with backoff for a long-running job. failedReason is diagnostic text, not a stable machine code. errorCode reports a failure to read the job, such as NOT_FOUND, rather than the transfer outcome.
Uncertain broadcast
A batch can remain submitted when its confirmation outcome is unknown. Do not create a replacement batch with a new key. Reconcile the source wallet's on-chain history or contact Agio before sending again.
Bulk-fund cardholders
Use each application's deposit address and chain as a destination. Group addresses by chain and select the token record accepted as collateral by those cardholders' program. Multisend eligibility alone does not establish that a token is accepted as card collateral.
Send one transfer per deposit address. After the job completes, check each destination's token balance and cardholder spending power. A collateral deposit address is separate from a source smart wallet; use a wallet ID from the available-wallets query as sourceWalletId.
Limits and validation
| Control | Default |
|---|---|
| Transfers per batch | 1–20 |
| Total batch value | $500,000 |
| Enqueue rate per partner organization | 5 requests per 10 minutes |
| Endpoint request body | 512 KB |
These are server defaults and can vary by environment. The worker checks live balances and USD value before broadcast. If a required USD price is unavailable, the batch is rejected. A successful enqueue does not bypass those checks.
Error codes
| Code | Action |
|---|---|
FORBIDDEN | Check partner access to the source wallet |
VALIDATION_ERROR | Correct transfer count, address, amount, precision, token ID, or key |
MIXED_CHAINS | Split the batch by execution chain |
TOKEN_CHAIN_NOT_ELIGIBLE | Select a verified token enabled for smart-wallet trading |
RATE_LIMITED | Wait retryAfterSec, then retry the same key and payload |
NOT_FOUND | Check jobId; jobs outside your organization are not visible |
INTERNAL_ERROR | Check the existing batch and reconcile before submitting again |