Exact Output Swaps¶
Exact Output quotes start with the amount the recipient must receive. The current flow uses wallet funding with a fixed input debit, gas_mode="pay_more" and funding_policy="wallet_fixed_exact_output". It does not draw an existing Vault balance to fund the swap. Successful output can exceed the target after integer rounding; read the confirmed amount for the actual result.
Availability depends on the target deployment. A temporary 503 does not establish whether an execution failed; preserve its identity and follow the retry rules below.
Request a Quote¶
Authentication: None.
Request Body¶
{
"quote_uuid": "client-quote-001",
"from_token": "0x1111111111111111111111111111111111111111",
"to_token": "0x2222222222222222222222222222222222222222",
"to_amount": "1000000",
"max_from_amount": "1200000",
"owner_address": "0x3333333333333333333333333333333333333333",
"recipient": "0x3333333333333333333333333333333333333333",
"expiration": 1800000000,
"gas_mode": "pay_more",
"funding_policy": "wallet_fixed_exact_output"
}
GET /api/v1/system/time to set a future expiration with enough time to quote, sign and execute. | Field | Required | Description |
|---|---|---|
quote_uuid | No | 1–64 visible ASCII characters without spaces. A UUID is generated if omitted. Supply and persist one to make quote retries identifiable |
from_token, to_token | Yes | Distinct, nonzero, strictly lowercase 0x EVM addresses |
owner_address, recipient | Yes | Nonzero lowercase signing/funding and destination wallets |
to_amount | Yes | Target output in positive uint256 decimal-string raw units |
max_from_amount | No | Maximum wallet input debit, including the quoted gas fee, as a positive raw string |
expiration | Yes | Integer Unix seconds, 0 < expiration < 2**48; must leave execution time after quoting |
gas_mode | Yes | pay_more |
funding_policy | Yes | wallet_fixed_exact_output |
Extra fields, floating-point amounts and noncanonical raw strings are rejected. Quote validity is at most 30 seconds and ends at least 30 seconds before the route expiration; always use returned expires_at.
Response¶
| Field | Description |
|---|---|
quote_uuid | Identifier used for execution and status lookup |
execution_flow | exact_output_fok_v1 |
status | quoted |
expires_at | Quote expiry in Unix seconds |
funding_policy, gas_mode | The accepted funding and gas choices |
route_params | Exact EIP-712 Intent fields to sign; its uuid is the signed uint256, not quote_uuid |
signing_domain | EIP-712 domain to use for this quote |
permit | Funding authorization metadata; the same supported-permit/approve branches as Swap |
fee_breakdown.quoted_gas_fee_input_raw | Gas fee denominated in raw input-token units |
fee_breakdown.wallet_debit_raw | Fixed total wallet debit |
fee_breakdown.expected_recipient_output_raw | Expected output, at least to_amount |
fee_breakdown.confirmed_recipient_output_raw | null at quote time |
fee_breakdown.gas_fee_usd | Gas cost in USD as a decimal string |
route_params.maxInputAmount and initialDepositAmount equal the fixed wallet debit. minOutputAmount is the requested target. Sign all returned Intent fields unchanged using the Intent type and this quote's signing_domain.
Execute¶
Authentication: EIP-712 Intent signature. If supplied, the API key must belong to the quote owner.
Request Body¶
{
"quote_uuid": "client-quote-001",
"signature": "0x...",
"permit_signature": "0x...",
"permit_deadline": 1800000000
}
quote_uuid and signature are required. Supply permit_signature / permit_deadline only when the stored quote requires a supported EIP-2612 permit. Otherwise complete the approve flow and omit both fields; unexpected permit fields are rejected. A pending execution returns HTTP 202; other successful HTTP responses use 200. HTTP 200 alone does not mean the trade succeeded: inspect status.
Query Status¶
GET /api/v1/swap/exact-output/{quote_uuid}
GET /api/v1/swap/exact-output?quote_uuid=client-quote-001
Authentication: API Key required; results are private to the quote owner. Prefer the query form for opaque/custom IDs and let your HTTP client encode the parameter. The path form only works for IDs suitable for one path segment: a valid ID such as a/b can return 404 even as a%2Fb, because the slash is decoded for routing. Such a 404 does not establish that the quote is absent.
| Status | Meaning |
|---|---|
quoted | Quote exists and remains valid; no confirmed execution result |
expired | Unexecuted quote is no longer valid |
pending | Execution outcome is still unresolved |
succeeded | Successful settlement confirmed |
failed | Execution reached a terminal failure |
Quoted/expired responses contain quote_uuid, execution_flow and status. Once a durable execution exists, responses additionally include order_id, route_uuid, intent_hash, transaction_hash, error_code, confirmed_recipient_output_raw and confirmed_actual_input_cost_raw; confirmation fields may be null while pending. Use the confirmed fields, not quote estimates, for final accounting.
Retries and Errors¶
- Retry a quote using the same
quote_uuidand unchanged quote fields. A changed request bound to the same ID returns 409; an expired identity is not a new quote. - Persist the exact execution body before sending it. After a timeout, 503 or pending result, query that ID and retry the identical signed body if needed. Changing signature bytes or permit content conflicts with an already claimed execution; see the encoding note below.
- Do not create a new quote ID to replace an execution whose outcome is unknown. Status reads remain available when new quote/execution admission is disabled.
A pending result can include automatic retry of a temporary submission failure when the service has established that no transaction was broadcast. It can also mean submission or chain recovery is still unresolved. Neither case asks the client to create a new quote or sign a replacement Intent; keep polling the original quote_uuid until a terminal result.
| HTTP | Meaning / action |
|---|---|
| 400 | Invalid Intent/permit signature, unexpected permit or funding preflight failure |
| 401 | Missing/invalid API Key on status lookup |
| 404 | Quote not found |
| 409 | Quote/execution identity conflict; some permit nonce conflicts require a fresh quote before admission |
| 410 | Plan or quote expired |
| 422 | Invalid request, input cap exceeded or a typed quote rejection |
| 429 | Rate limit; honor Retry-After when present |
| 503 | Temporarily unavailable or admission disabled; retain the ID and check status |
Typed 4xx errors use detail.code, including EXACT_OUTPUT_QUOTE_CONFLICT, EXACT_OUTPUT_EXECUTION_CONFLICT, EXACT_OUTPUT_PLAN_EXPIRED and EXACT_OUTPUT_INPUT_CAP_EXCEEDED. Shared Swap preflight errors can instead use detail.error_code or a string. 5xx failures normally use the generic 503 response; do not depend on an internal EXACT_OUTPUT_* code surviving that response.
Intent and permit length limits are listed under signature encoding. Preserve and retry the original signed body for compatibility: new execution claims normalize equivalent hex encodings to signature bytes, but changing the signature bytes or signed content changes the execution identity; historical claims can still use the original string fingerprint. The whole-body limit also applies.