Skip to main content
POST
/
submit
Build a broadcast-ready transaction for a previously issued quote
curl --request POST \
  --url https://quiet-bloodhound-531.convex.site/submit \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <api-key>' \
  --data '
{
  "quoteId": "<string>",
  "user": "<string>",
  "useNativeIn": true,
  "unwrapNativeOut": true,
  "gasPriceWei": "<string>",
  "maxFeePerGasWei": "<string>",
  "maxPriorityFeePerGasWei": "<string>"
}
'
{
  "quoteId": "<string>",
  "chainId": 123,
  "to": "<string>",
  "data": "<string>",
  "value": "<string>"
}

Documentation Index

Fetch the complete documentation index at: https://docs.o1.exchange/llms.txt

Use this file to discover all available pages before exploring further.

Use POST /submit to convert a quoteId from POST /quote into the calldata your wallet broadcasts.
  • Authentication: x-api-key header required.
  • Quote TTL: quotes expire roughly 10 seconds after /quote. Submitting an expired quoteId returns 404.

Request

POST {API_URL}/submit
Content-Type: application/json
x-api-key: <YOUR_API_KEY>

Body parameters

FieldTypeRequiredDescription
quoteIdstringyesThe quoteId from a recent /quote response.
useraddressyesThe wallet that will sign and broadcast the transaction.
useNativeInbooleannoOverride routePlan.nativeIn. Set true to send native ETH; the router wraps msg.value to WETH before dispatching legs.
unwrapNativeOutbooleannoOverride routePlan.nativeOut. Set true to receive native ETH instead of WETH.
permitobjectnoOptional EIP-2612 permit payload for one-tx approve+swap. See permit payload below.
gasPriceWeistringnoHint for legacy gas pricing (gasPrice).
maxFeePerGasWeistringnoHint for EIP-1559 maxFeePerGas.
maxPriorityFeePerGasWeistringnoHint for EIP-1559 maxPriorityFeePerGas.
The gas price fields are hints only. They are not currently echoed back into the calldata; your wallet client should set its own gas pricing when broadcasting.

permit payload

When you have a fresh EIP-2612 permit signature for tokenIn, include it to skip the standard approve transaction.
{
  "permit": {
    "value": "1000000000",
    "deadline": 1712180600,
    "v": 27,
    "r": "0x...",
    "s": "0x..."
  }
}
FieldTypeNotes
valuestringAmount permitted in token base units. Must be >= amountIn.
deadlineintegerUnix seconds at which the permit expires.
v / r / scomponentsEIP-2612 signature pieces.
The router consumes the permit inside the same transaction; if it fails, the whole swap reverts. See ERC-20 approvals for the full pattern.

Response

{
  "quoteId": "a1b2c3d4e5f6...",
  "chainId": 8453,
  "to": "0xe56e22354DDdc07cF2dfbCFb53a90fB0a56E50D5",
  "data": "0x...",
  "value": "0"
}

Response fields

FieldTypeDescription
quoteIdstringEcho of the quoteId you submitted.
chainIdintegerAlways 8453 while only Base is supported.
toaddressAlways the O1Router address. See Router contract.
datahexEncoded swapExactIn(...) calldata.
valuestringmsg.value to send with the transaction in wei. Non-zero only for native-in swaps (useNativeIn: true).

Sending the transaction

The response is intentionally minimal so any signer works. Example with viem:
const txHash = await walletClient.sendTransaction({
  to: submit.to as `0x${string}`,
  data: submit.data as `0x${string}`,
  value: BigInt(submit.value),
});
ethers v6:
const txResponse = await wallet.sendTransaction({
  to: submit.to,
  data: submit.data,
  value: submit.value,
});
Do not modify data before sending. The router validates the route plan against the submitted quoteId; any tamper attempt will revert.

Native ETH and unwrap behavior

Want toSet on /quoteSet on /submit
Sell native ETHtokenIn = native sentinel (0xEeee...EEeE or 0x0)useNativeIn: true
Receive native ETHtokenOut = native sentinelunwrapNativeOut: true
When you sell native ETH, the response value carries amountIn and the router wraps to WETH internally. See the Native ETH guide for the full matrix.

Common pitfalls

404 on /submit

Quote expired. Re-fetch via /quote with the same parameters and resubmit. Don’t cache quoteId longer than expiresAt minus a small safety window.

`value` is 0 for ETH swaps

You forgot useNativeIn: true. The router can’t infer it from tokenIn alone in /submit because the API does not assume the user has changed their mind since /quote.

Tx reverts with slippage error

Pool state moved between /quote and broadcast. Increase slippageBps slightly or re-quote and resend.

Allowance error

The user hasn’t approved the router for tokenIn. Approve O1Router for at least amountIn, or use a permit payload. See ERC-20 approvals.

Authorizations

x-api-key
string
header
required

Body

application/json
quoteId
string
required
user
string
required

20-byte hex address. The sentinel 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE (or the zero address) signals the chain's native asset (ETH on Base) and is recognized in tokenIn/tokenOut.

Pattern: ^0x[a-fA-F0-9]{40}$
useNativeIn
boolean

Override routePlan.nativeIn. When true the router wraps msg.value to WETH before dispatching legs.

unwrapNativeOut
boolean

Override routePlan.nativeOut. When true the router unwraps WETH to ETH for the recipient.

permit
object
gasPriceWei
string

Non-negative integer encoded as a decimal string (wei).

Pattern: ^[0-9]+$
maxFeePerGasWei
string

Non-negative integer encoded as a decimal string (wei).

Pattern: ^[0-9]+$
maxPriorityFeePerGasWei
string

Non-negative integer encoded as a decimal string (wei).

Pattern: ^[0-9]+$

Response

Transaction payload

quoteId
string
required
chainId
integer
required
to
string
required

20-byte hex address. The sentinel 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE (or the zero address) signals the chain's native asset (ETH on Base) and is recognized in tokenIn/tokenOut.

Pattern: ^0x[a-fA-F0-9]{40}$
data
string
required

Hex-encoded bytes.

Pattern: ^0x[a-fA-F0-9]*$
value
string
required

msg.value in wei (non-zero only for native-in swaps).

Pattern: ^[0-9]+$