API Reference
Transfers
Execute USDC transfers from an agent account. All transfers are validated against spending policy, signed on-chain, and settled in under 400ms.
Transfer lifecycle
- Agent submits —
POST /v1/transferswith recipient, amount, memo, idempotency key - Policy check — ClawdGo validates against the account's on-chain spending policy. If rejected, returns
402and fires atransfer.rejectedwebhook. - Signing — ClawdGo constructs and signs the Solana transaction using the PDA authority
- On-chain submission — transaction submitted to Solana. Typical finality: <400ms
- Response — returns
tx_signature,status: "settled", andsettled_attimestamp
POST
/v1/transfers
Initiate a USDC transfer from an agent account. Can be called with an operator key or an agent-scoped key.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
from | string | required | Source account_id. Must belong to the authenticated operator. |
to | string | required | Recipient. Either a ClawdGo account_id or a valid Solana USDC SPL token account address. |
amount | string | required | USDC amount as a decimal string. E.g., "25.00". Minimum: "0.000001". |
idempotency_key | string | required | Unique key for this transfer. Re-submitting the same key returns the original response. Max 128 chars. |
memo | string | optional | Optional memo string attached to the transfer. Required if the account policy has require_memo: true. Max 200 chars. |
Response — 200 OK (settled)
json
{
"transfer_id": "txn_02m9n5y3q7wpuv8ab",
"status": "settled",
"from": "acct_01j8k4x9p2qrst7yz",
"to": "9xTz4KqR8mYvPn3SdFgHj6WbCeAuLo1XkQi5NtZpMwV",
"amount_usdc": "25.000000",
"memo": "Invoice #1042 — vendor payment",
"idempotency_key": "inv-1042-2024-01-15",
"tx_signature": "5j4Kz9qXm2nWpRt8vYbFdCgHs3Ae7UoLkNi6ZwQxPmV4rBe...",
"solana_explorer_url": "https://explorer.solana.com/tx/5j4Kz9qX...",
"settled_at": "2024-01-15T10:41:02Z"
}
Response — 402 Payment Required (policy rejected)
json
{
"error": "policy_violation",
"message": "Transfer amount 750.00 exceeds max_single_transfer limit of 500.00 USDC",
"transfer_id": "txn_02m9n5y3q7wpuv8ab",
"status": "rejected"
}
GET
/v1/transfers/:id
Retrieve a specific transfer by its ID. Useful for polling transfer status or for audit purposes.
Error codes
| HTTP | Error code | Meaning |
|---|---|---|
402 | policy_violation | Transfer rejected by spending policy. |
402 | account_paused | Account has paused: true in policy. |
402 | insufficient_balance | Source account has insufficient USDC balance. |
409 | idempotency_conflict | Idempotency key reused with different parameters. |
422 | invalid_recipient | Recipient address is not a valid USDC SPL token account. |
503 | solana_unavailable | Solana RPC unavailable. Retry with backoff. |
Idempotency
All transfers require a unique idempotency_key. If you submit a request with a key you have used before:
- If the original transfer succeeded: returns the original settled response. No duplicate transfer is made.
- If the original transfer failed (non-policy failure): retries the transfer.
- If you use the same key with different parameters: returns
409 idempotency_conflict.
Keys expire after 24 hours. After expiry, the key can be reused freely.
Use deterministic keys. Good keys are derived from the underlying business event:
invoice-{id}-{date}, task-{task_id}-reward. Avoid random UUIDs unless you store them durably — a random key on retry creates a duplicate transfer.