Skip to main content

Overview

The Calldata API is the execution surface of 1tx. It takes an instrument and an amount and returns the ordered calls to make, already simulated against chain state at a pinned block. It holds nothing and signs nothing. There is no 1tx router in the path, no on-chain registration step for an instrument, and no custody: the calls target the protocol directly, and the account named in the request is the effective caller, token owner and receiver. Your wallet — an EOA sending them one at a time, or a smart account batching them — decides how they land. Three endpoints return the same envelope:
Every bundle is single-chain. A cross-chain deposit is a bridge bundle on the source chain and, once Circle attests the burn, an instrument bundle on the destination chain — two requests, not one call that spans chains.

Build an Instrument Bundle

GET /instruments/:instrumentId/calldata Builds the calls for one deposit or withdrawal, simulates them atomically at a pinned quote block, and returns what the simulation measured rather than what a model predicts.

Path Parameters

string
required
The 32-byte instrument id from GET /instruments. It embeds the chain, so the request carries no chainId.

Query Parameters

string
required
deposit or withdraw.
string
required
The account that supplies the tokens and receives the output. It is the effective caller of every call in the bundle.
string
required
Raw token units — never a decimal string. For deposit it is the amount of tokenIn; for withdraw, the amount of the underlying asset to take out. max empties the position and is valid only for withdraw.
string
default:"chain USDC"
What the account spends on a deposit. Anything other than the instrument’s underlying asset adds a swap leg in front of the deposit.
string
default:"chain USDC"
What the account receives on a withdrawal. Anything other than the underlying asset adds a swap leg after the withdrawal.
number
default:"50"
Applies to the swap leg only. A bundle with no swap ignores it.

Request

Response

A USDC deposit into an ERC-4626 vault, calldata truncated:

Response Fields

Reading the bundle

Every bundle is simulated with eth_simulateV1 at quoteBlock before it is returned, running all the calls in one block, in order, as the account. tokenOutDelta is the account’s tokenOut balance after minus before — that is where expectedOut comes from. A bundle whose simulation reverts, or that produces no output tokens, is never returned; you get a 400 instead.engine: "wallet_neutral_atomic" means the simulation makes no assumption about how you execute: it does not model a router, a smart-account batch or a paymaster, only the protocol calls. It is a statement about the calls, not about your wallet’s ability to send them.assumedBalances: true means the simulation overrode the account’s token balances to satisfy requires. It proves the calls work; it does not prove the account is funded. Check requires against real balances yourself.
requires lists exactly what the account must hold before the first call. The bundle always includes its own approve calls where a protocol needs one, sized to the bundle, so an existing allowance is not assumed. Compound V3 is the exception every integrator hits: Comet uses allow(manager, true) rather than an ERC-20 approve on the withdrawal path, and the bundle emits that call for you.
When tokenIn/tokenOut is not the instrument’s underlying asset, the bundle gains a swap leg — Uniswap V3 or V4, on a route pinned per underlying — placed before the deposit or after the withdrawal. Only then are expiresAt, minOut and leftovers populated.A quote that prices further than 100 bps below par for a stable pair, or that carries more than 100 bps of impact against a reference quote, is refused rather than returned at a bad price. Past expiresAt, request fresh calldata; the old bundle will revert on its own minOut rather than fill badly.A max withdrawal cannot be swapped: the exit amount is only known after the withdrawal runs, and an exact-output swap needs it up front. Ask for an exact underlying amount instead.
  • 400 — inactive instrument, unsupported chain, amount=max on a deposit, a max withdrawal combined with a swap, a swap withdrawal on a non-exact amount, an expired quote, a reverted simulation, or a simulation that produced no output.
  • 404 — no such instrument.
  • 501 — the instrument has no recipe, or its recipe is not implemented. erc4626, aave-v3 and comet are served today.
  • 503 — RPC, the swap quote or the simulator was unavailable.

Build a Bridge Bundle

GET /bridge/calldata Builds the CCTP V2 source burn — approve plus depositForBurn — that moves USDC to another chain. The account is both the burner and the recipient on the destination side.

Query Parameters

number
required
Source chain. Must be configured for CCTP V2.
number
required
Destination chain. Must differ from the source.
string
required
Raw USDC units to burn.
string
required
Burns the USDC on the source chain and receives it on the destination chain.
boolean
required
true uses Fast Transfer (finality threshold 1000), false Standard (2000). Fast settles in seconds against Circle’s allowance and charges the fee quoted in maxFee; Standard waits for hard finality. A source chain without fast support refuses true.

Request

Response

maxFee is quoted from Circle for this route, amount and finality threshold, and is written into the burn. sourceDomain and destinationDomain are CCTP domain ids, not chain ids — you need them to track the message.

After the burn

The bundle ends at the burn. To complete a cross-chain deposit:
  1. Send the bridge bundle on fromChainId.
  2. Poll bridge status with the source transaction hash until Circle’s attestation lands and the USDC is minted to account on toChainId.
  3. Request GET /instruments/:instrumentId/calldata on the destination chain and send that bundle.
Step 3 is a fresh request, built at a fresh quote block. Do not build it before the mint: its simulation would be pinned to a block where the funds have not arrived.

Errors

  • 400 — a chain not configured for CCTP V2, identical source and destination, fast=true where fast transfer is unavailable, or a reverted simulation.
  • 502 — Circle’s fee quote was unavailable.
  • 503 — RPC or the simulator was unavailable.

Executing a bundle

The calls are plain transactions. Send them in the order returned, on chainId:
  • EOA — one transaction per call, each confirmed before the next. Atomicity is the simulation’s claim about the calls, not a guarantee about your sending; a bundle stopped halfway leaves the account holding whatever the last completed call produced.
  • Smart account (ERC-4337 / EIP-5792) — send the calls as one batch and the bundle lands or reverts as a whole, which is what the simulation actually modelled. Gas and sponsorship are your wallet’s concern; 1tx neither pays nor requires a paymaster.
Rebuild rather than reuse. A bundle is pinned to quoteBlock, and a bundle carrying a swap is dead after expiresAt.