Prerequisites
Before you start, make sure you have completed the following:- Ensure the source_account has sufficient balance.
- (Recommended) Configure a Webhook Endpoint to receive Bulk Send status updates and drive an automated retry workflow.
1. How to send in batch
1.1 Create a Bulk Send
To create a Bulk Send, provide:- source_account: Source account ID (e.g., M1001)
- execution_mode: Execution mode (Strict / Partial)
- payout_params: Array of bulk send items. Each item includes:
- token_id
- receiving_address
- amount
- description (recommended: include business-traceable info such as payroll slip No./user ID/batch ID)
1.2 How to choose execution_mode
After receiving a Bulk Send request, Cobo first validates all addresses in the request (including format validation and compliance checks such as KYA).execution_mode determines whether Cobo continues with on-chain transfers for valid items when any item fails validation.
Behavior: Strict vs Partial
| execution_mode | If any address fails validation (e.g., KYA rejected) | On-chain transfer result | What you need to do |
|---|---|---|---|
| Strict | If any bulk send item has an invalid address | No on-chain transfers will be initiated (the entire batch is not executed) | Replace the problematic address(es) and resubmit the entire Bulk Send (must include all items |
| Partial | Allows some invalid addresses | Transfers will be executed for all validated items; invalid items will be skipped | Query failed items, replace addresses, and resend only the failed items |
Recommended scenarios
Use Strict (strong consistency: all-or-nothing)- Partner settlements (must take effect consistently within the same batch)
- Vendor payments (finance requires batch-level consistency)
- Any scenario where partial success is unacceptable
Use Partial (high throughput: partial failures allowed, retry later)- Global payroll payouts (large volume; a few bad addresses should not block the whole batch)
- Rebates/rewards airdrops (mixed address quality)
- Tips/revenue distribution for content platforms; merchant payout distribution for e-commerce/ads platforms (retry is acceptable)
Strictimproves financial consistency, but increases operational overhead due to “one bad address forces a full resubmission”.Partialscales better and is more automation-friendly, but requires a retry workflow for failed items.
1.3 Smart contract mechanism for Bulk Send
When executing a Bulk Send, Cobo uses smart contracts to perform batch transfers. Understanding this mechanism helps you correctly verify contract call information in your callback handler.Approve operation (triggered when allowance is insufficient)
When the smart contract’s allowance for a token is insufficient, anapprove call is first triggered on the token contract:
- Function called:
approve - calldata parameters:
_spender: The batch transfer contract address (see table below)_value: The transfer amount
Transfer operation
After the approve completes, the actual transfer calls thesendToken function on the batch transfer contract:
- Function called:
sendToken - calldata parameters:
token: The token contract address (see table below)recipients: List of recipient addressesvalues: Corresponding list of transfer amounts
Contract address reference
Since the contract addresses are fixed for each token, it is recommended to verify the contract addresses and function call information in your callback handler to ensure the callback completes correctly.| Chain | Token ID | Token contract address | Batch transfer contract address |
|---|---|---|---|
| Ethereum | ETH_USDT | 0xdac17f958d2ee523a2206206994597c13d831ec7 | 0x3d963e23a9229d2acd25e9ffc358be1a35460ecc |
| Ethereum | ETH_USDC | 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48 | 0x3d963e23a9229d2acd25e9ffc358be1a35460ecc |
| Arbitrum | ARBITRUM_USDT | 0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9 | 0x3d963e23a9229d2acd25e9ffc358be1a35460ecc |
| Arbitrum | ARBITRUM_USDCOIN | 0xaf88d065e77c8cc2239327c5edb3a432268e5831 | 0x3d963e23a9229d2acd25e9ffc358be1a35460ecc |
| Base | BASE_USDT | 0xfde4c96c8593536e31f229ea8f37b2ada2699bb2 | 0x3d963e23a9229d2acd25e9ffc358be1a35460ecc |
| Base | BASE_USDC | 0x833589fcd6edb6e08f4c7c32d4f71b54bda02913 | 0x3d963e23a9229d2acd25e9ffc358be1a35460ecc |
| Polygon | MATIC_USDT | 0xc2132d05d31c914a87c6611c10748aeb04b58e8f | 0x3d963e23a9229d2acd25e9ffc358be1a35460ecc |
| Polygon | MATIC_USDC2 | 0x3c499c542cef5e3811e1192ce70d8cc03d5c3359 | 0x3d963e23a9229d2acd25e9ffc358be1a35460ecc |
| BNB Smart Chain | BSC_USDT | 0x55d398326f99059ff775485246999027b3197955 | 0x3d963e23a9229d2acd25e9ffc358be1a35460ecc |
| BNB Smart Chain | BSC_USDC | 0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d | 0x3d963e23a9229d2acd25e9ffc358be1a35460ecc |
| TRON | TRON_USDT | TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t | TEmDa9FY9YBCg1HPL41RUnJorXRRV3rX7A |
2. Webhook-driven automation workflow (failure notification → query items → batch resend)
2.1 Subscribe to Bulk Send status update events
Cobo triggers a webhook event when the Bulk Send status transitions to any of the following:- Completed
- PartiallyCompleted
- Failed
- Pending
- Validating
- Transferring
- Completed
- PartiallyCompleted
- Failed
- Trigger the resend workflow only when the status enters PartiallyCompleted or Failed. During Validating / Transfering, you may only display or monitor progress.
- Implement webhook signature verification and idempotency handling (the same event may be replayed).
2.2 After a failure notification: query Bulk Send item details
After receiving a PartiallyCompleted or Failed webhook, call List bulk send items to query the status of each bulk send item:- Path parameter: bulk_send_id
- Operation: list_bulk_send_items
- Summary: List bulk send items
- status (execution status of the item)
- validation_status (address/compliance validation status)
- If status = Failed or NotExecuted → the item failed
- If validation_status = ValidationFailed → the address did not pass Cobo KYA validation
2.3 Automated retry: replace addresses and resend in batch
Resend strategy depends on execution_mode:A) Previous batch used Strict
- Under
Strict, if any address has an issue, no on-chain transfer is executed for the entire batch. - Therefore, on retry (resubmission), you must include all items (not only the failed ones).
- Query items and identify those with ValidationFailed or Failed/NotExecuted
- Replace the addresses for those items (or fix other parameters causing failures)
- Resubmit a new Bulk Send containing all items
B) Previous batch used Partial
- Under
Partial, successful items have already been transferred. - Therefore, on retry, submit only failed items (reduces the risk of duplicate transfers).
- Query items and filter failed items (
status=Failed/NotExecutedorvalidation_status=ValidationFailed) - Replace the addresses for failed items
- Create a new Bulk Send containing only these failed items
3. Reference implementation: webhook handling + auto resend (example)
This example demonstrates a typical workflow:- Receive webhook
- If status is
PartiallyCompleted/Failed, query items - Filter failed items and replace addresses (address replacement is handled by your business system)
- Create a new Bulk Send for resend
4. Best practices
Always include business-traceable identifiers in description(e.g.,batch_id + user_id/employee_id + period) for auditing, reconciliation, diagnosing failures, and address replacement.- Use different resend strategies for Strict vs Partial:
- Strict:retry must include all items
- Partial:retry only failed items (avoid duplicate payouts)
- Webhook idempotency: use
bulk_send_id + status + updated_timestampas an idempotency key to avoid duplicated resend triggers. - Failure classification:
- validation_status=ValidationFailed:prioritize replacing the address
- status=Failed/NotExecuted: also recommended to replace the address (per your rule), and retain the failure reason for risk control and user messaging
