Vudy sends
Sends move tokens to recipients identified by address or Vudy tag. Use the dedicated /channel/vudy/send/* routes and poll for completion.
Prerequisites#
- API key + profile context (session or headers)
- Sufficient token allowance and gas (see Wallets)
- Recipient address or resolvable Vudy tag
Flow overview#
- Resolve tags if needed
- Preview the send
- Ensure allowances and gas
- Create the send
- Process each regular, gas, or sponsored transaction
- Poll parent/child transaction status until
completedorexpired
1. Resolve a Vudy tag (optional)#
curl -sS "https://api-stg.vudy.app/channel/vudy/tag?tag=USERNAME" \
-H "x-api-key: vudy_sandbox_YOUR_KEY"Use tag / tags or address (not both). Multiple tags: ?tags=alice,bob or repeated tag=.
2. Preview#
curl -sS https://api-stg.vudy.app/channel/vudy/send/preview \
-H "x-api-key: vudy_sandbox_YOUR_KEY" \
-H "x-profile-id: PROFILE_UUID" \
-H "x-team-id: TEAM_UUID" \
-H "Content-Type: application/json" \
-d '{
"senderAddress": "0xSENDER",
"amount": 50,
"channelParams": {
"chain": "ethereum",
"token": "USDC",
"recipients": [{ "address": "0xRECIPIENT", "amount": 50 }]
}
}'Preview does not persist a send.
3. Create#
curl -sS https://api-stg.vudy.app/channel/vudy/send/create \
-H "x-api-key: vudy_sandbox_YOUR_KEY" \
-H "x-profile-id: PROFILE_UUID" \
-H "x-team-id: TEAM_UUID" \
-H "Content-Type: application/json" \
-d '{
"targetAddress": "0xSENDER",
"amount": 50,
"channelParams": {
"chain": "ethereum",
"token": "USDC",
"note": "Payroll",
"recipients": [
{ "address": "0xRECIPIENT", "amount": 50 },
{ "vudyTag": "teammate", "amount": 10 }
]
}
}'const { data } = await fetch(
"https://api-stg.vudy.app/channel/vudy/send/create",
{
method: "POST",
headers: {
"x-api-key": process.env.VUDY_API_KEY,
"x-profile-id": profileId,
"x-team-id": teamId,
"Content-Type": "application/json",
},
body: JSON.stringify({
targetAddress: senderAddress,
amount: 50,
channelParams: {
chain: "ethereum",
token: "USDC",
recipients: [{ address: recipient, amount: 50 }],
// sendAutomatically: true also requires orgId (opaque org id from verify-otp)
},
}),
},
).then((r) => r.json());
// { txId, sendId, transactions, gasTransactions, allowanceOk, needsSponsorship, ... }
Each recipient must include address or vudyTag.
4. Process transactions#
Use transactions, gasTransactions, allowanceOk, and needsSponsorship from create. The route id below may be the returned sendId or txId.
| Step | Path |
|---|---|
| Prepare external sponsored signature | POST /channel/vudy/send/{id}/prepare-sponsored-tx |
| Process sponsored transaction | POST /channel/vudy/send/{id}/process-sponsored-tx |
| Process regular or gas transaction | POST /channel/vudy/send/{id}/process-send-tx |
Approve allowances via Wallets when allowanceOk is false.
For a regular or gas transaction, call with the session bound to the sender profile:
curl -sS https://api-stg.vudy.app/channel/vudy/send/SEND_OR_TX_ID/process-send-tx \
-H "x-api-key: vudy_sandbox_YOUR_KEY" \
-H "Authorization: Bearer SESSION_JWT" \
-H "Content-Type: application/json" \
-d '{"txType":"regular","txIndex":0}'For a managed wallet, the response contains txHash. For an external wallet, it contains to, data, and value; sign and broadcast that payload with the sender wallet.
For an externally signed sponsored transaction:
const prepared = await fetch(
`https://api-stg.vudy.app/channel/vudy/send/${sendId}/prepare-sponsored-tx`,
{
method: "POST",
headers: {
"x-api-key": process.env.VUDY_API_KEY,
Authorization: `Bearer ${session}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ txIndex: 0 }),
},
).then((r) => r.json());
const userSignature = await wallet.signTypedData(prepared.data.typedData);
await fetch(
`https://api-stg.vudy.app/channel/vudy/send/${sendId}/process-sponsored-tx`,
{
method: "POST",
headers: {
"x-api-key": process.env.VUDY_API_KEY,
Authorization: `Bearer ${session}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
prepareId: prepared.data.prepareId,
attestation: prepared.data.attestation,
userSignature,
}),
},
);5. Status transitions#
| Stage | Status |
|---|---|
| Created | pending |
| Confirmed on-chain | completed |
| Processing failed | failed |
| Timed out | expired |
| Cancelled | canceled |
Poll GET /channels/vudy/{txId} or GET /v1/tx/{id}. Listing txs may also expire stale pending sends.
No outbound completion event is emitted for sends. Reconcile by polling.