---
title: "Get quote (by send amount, by target receive amount, or a re-quote)"
method: POST
path: "/agent/swap/quote"
tags: ["agent", "swap"]
---

# Get quote (by send amount, by target receive amount, or a re-quote)

`POST /agent/swap/quote`

## Request

- Base URL: `https://xmrtousdc.xyz/api/v1`
- URL: `https://xmrtousdc.xyz/api/v1/agent/swap/quote`
- Auth: none declared

Give direction and exactly one of amount (send asset) or receiveAmount (receive asset), or requoteOf alone. Returns state "quoted", data.amount (send amount, human units), data.quoteId (bound to that send amount and single-use: it opens at most one order), data.expiresAt (end of the confirmation window, not a price lock), data.expiresInSec and data.acceptWindowSec (QUOTE_MAX_AGE_SEC: 300 s on this deployment, default 300), data.intentCommitment, data.terms {send, receive {estimate, estimateAtomic, minimum, minimumAtomic, minimumPublished}, guaranteed:false, estimatedTimeSec, fees {itemized, integratorFee, breakdown?, feeFraction?, swapperFee: null, note}, minimumSwapUsd, minimumSendEstimate, belowProviderMinimum}, data.confirmation ({ required: false, quoteId, acceptUntil, instruction }) and the raw data.quote. The provider publishes no minimum receive amount (Wagyu v2): terms.receive.minimum is null and minimumPublished false, never derived from the estimate. With receiveAmount, Swapper searches a send amount whose estimated receive amount meets the target (rounded up to 0.01 USDC or 0.0001 XMR, at most 5 provider quotes) and adds data.target; basis "minimum" (target the provider minimum instead) is refused with 400 minimum_not_published while the provider publishes none. requoteOf re-quotes the stored inputs of an earlier quote (same direction, chain, send amount or target, destination) and adds data.delta. For u2x, data.prerequisites lists what the sending wallet needs (native USDC contract, ETH for gas on Arbitrum One) before any order exists. Estimates are not guaranteed: the final amount is set when the swap runs. Fees are included in the rate: Swapper's integrator fee (data.terms.fees.integratorFee) and the provider's own fees (itemized only when the provider reports them). Create with data.quoteId while it is valid. Creates no order. Optional agent key (x-agent-key header or agentKey): the quote and its order use the agent fee shown in GET /agent/key. 451 if the caller's region is restricted.

## Headers

- `x-agent-key` string

## Request body

- AgentQuoteRequest: direction plus exactly one of amount or receiveAmount (both or neither: 400 invalid_request with details.field = amount and details.reason = amount_xor_receiveAmount), or requoteOf alone (with other fields: 400).
  - `direction` 'x2u' | 'u2x': x2u = XMR->USDC, u2x = USDC->XMR. Buying XMR: u2x.
  - `chain` union: Optional while Arbitrum One (42161) is the only live chain.
    - string
    - integer
  - `amount` string: What the user SENDS: decimal string in send-asset units (XMR for x2u, USDC for u2x).
  - `receiveAmount` string: What the user wants to RECEIVE: decimal string in receive-asset units (USDC for x2u, XMR for u2x). Same precision and positivity rules as amount, against the receive asset's decimals.
  - `basis` 'estimate' | 'minimum': With receiveAmount: "estimate" (the default) finds a send amount whose estimated output meets the target. "minimum" would target the provider's published minimum (minReceived), but it is refused with 400 invalid_request (details.field basis, details.reason minimum_not_published) while the provider publishes no minimum receive amount, which is always the case on Wagyu v2. With amount instead of receiveAmount: 400 requires_receiveAmount. Echoed as data.target.basis.
  - `to` string: Optional on quote; validated if present (same destination checks as create).
  - `requoteOf` string, required: Re-quote an earlier quote's stored inputs (same direction, chain, send amount or target, destination), for example after it expired or once the user is funded. Send it alone (an agent key goes in the x-agent-key header). Returns a new quote plus data.delta. Unknown quoteId: 404 quote_not_found.
  - `agentKey` string: Optional agent key (POST /agent/key): this quote and the order created from it carry a lower integrator fee (data.agentKey, terms.fees.integratorFee). The x-agent-key header works too.

## Response `200`

Quote response

- QuoteResponse
  - `ok` boolean
  - `operation` string
  - `state` string
  - `data` object
    - `direction` 'x2u' | 'u2x'
    - `amount` string: Send amount in human units. With receiveAmount, the amount Swapper found; the quoteId is bound to it, so create needs only the quoteId.
    - `quoteId` string: Single-use: it opens at most one order.
    - `quotedAt` string, date-time
    - `expiresAt` string, date-time: End of Swapper's acceptance window for this quote. Not a provider price lock.
    - `expiresInSec` integer: Seconds left until expiresAt when the response was built.
    - `acceptWindowSec` integer: Length of the acceptance window in seconds (QUOTE_MAX_AGE_SEC: 300 on this deployment, default 300).
    - `intentCommitment` object: SHA-256 commitment to the quoted terms (docs/QUOTE_INTENT_COMMITMENT.md): { version, algorithm, digest, claim }. claim values are strings (chainId too) because they are hashed in a canonical form. Pass digest as quoteIntentDigest on create to have Swapper re-check the stored quote.
    - `to` string, nullable: The destination the quote was made for, if any.
    - `requoteOf` string: Present on a re-quote: the earlier quoteId.
    - `delta` QuoteDelta: Present only on a requoteOf response: how the new quote compares with the previous one.
      - `previousQuoteId` string
      - `receiveEstimateChange` object, nullable: { atomic (signed integer string), percent (signed decimal string, 2 places) }: new estimate minus the previous one; null when either is unknown.
      - `minimumChange` object, nullable: Change of the provider minimum, in the same form as receiveEstimateChange; null while the provider publishes no minimum.
      - `sendChange` object, nullable: Present when a receiveAmount re-quote found a different send amount; same form.
    - `next` object: { action: create_order, createPath, createUrl, createBody: { quoteId }, missing: [] or ["to"], requiresIdempotencyKey: true }, or { action: requote_with_larger_amount, reason: below_provider_minimum, minimumSwapUsd } when the quote is below the provider minimum.
    - `confirmation` object: { required: false, quoteId, acceptUntil, instruction }: how the quote is accepted (create with this quoteId before acceptUntil). required: false means nothing on Swapper's side requires a confirmation; whether to confirm with the user first follows the user's and the client's policy. Without a published minimum the instruction says the receive amount is an estimate.
    - `terms` object
      - `send` object: { amount, amountAtomic, symbol, decimals }
      - `receive` object: { symbol, decimals, estimate, estimateAtomic, minimum, minimumAtomic, minimumPublished, estimateUsd }. minimum and minimumAtomic are null and minimumPublished is false while the provider publishes no minimum receive amount (always on Wagyu v2); Swapper never derives a minimum from the estimate. The estimate is not a floor: the final amount is set when the swap runs.
        - `estimate` string, nullable
        - `estimateAtomic` string, nullable
        - `minimum` string, nullable
        - `minimumAtomic` string, nullable
        - `minimumPublished` boolean
      - `guaranteed` false
      - `estimatedTimeSec` number, nullable: The provider's time estimate; null on Wagyu v2, which gives none.
      - `fees` object: { itemized, integratorFee: { percent, amountUsd } | null, breakdown? (the provider's display values), feeFraction?, swapperFee: null, note }. integratorFee is Swapper's revenue: the provider takes it out of the swap inside the quoted rate, so the estimate already includes it. swapperFee is null: nothing is charged on top of the quote beyond integratorFee. The provider's own fees are included in the rate too and itemized only when the provider reports them. USD values are display estimates.
      - `acceptUntil` string, date-time
      - `minimumSwapUsd` number, nullable: Provider minimum swap value in USD for the send chain (cached, informational).
      - `minimumSendEstimate` string, nullable: minimumSwapUsd in the send asset (human units) at this quote's own USD rate, rounded up to 0.0001 XMR or 0.01 USDC. An estimate: the provider's USD values are display estimates and its rate moves. null when the minimum or the quote's USD value is unknown or zero.
      - `belowProviderMinimum` boolean, nullable: true when the quote's USD value is below minimumSwapUsd (a dust amount whose USD value is 0 counts); null when unknown. Create refuses such a quote with 422 below_provider_minimum; the provider stays authoritative.
    - `target` QuoteTarget: Present only for receiveAmount quotes.
      - `mode` 'receive'
      - `basis` 'estimate' | 'minimum': What the search targeted: the estimated output (estimate, the default). minimum (the provider's published minimum) is refused with 400 minimum_not_published while the provider publishes none.
      - `receiveAmount` string
      - `receiveAmountAtomic` string
      - `estimateMeetsTarget` boolean: Whether the estimate reaches the target (true for a found send amount).
      - `minimumMeetsTarget` boolean, nullable: null while the provider publishes no minimum (always on Wagyu v2): the result can fall short of the target. With a published minimum: whether it reaches the target.
      - `upstreamQuotes` integer
      - `note` string: The estimate meets the target; without a published minimum the result can still fall short; nothing is guaranteed.
    - `prerequisites` FundingRequirements: What the sending wallet needs (from packages/shared/src/funding.js). Included in u2x quotes as data.prerequisites.
      - `sendAsset` object: { symbol, kind, chain, chainId, tokenAddress?, decimals }
      - `gas` PaymentGas
        - `symbol` string
        - `chain` string
        - `note` string
      - `pitfalls` string[]
      - `destination` string
    - `quote` object: Raw provider quote (atomic units).
    - `swapDetails` object

## Other responses

- `400`: invalid_request (details.field, details.reason): amount_xor_receiveAmount (both or neither given), ambiguous_amount (commas, spaces, underscores or units, e.g. 1,5, which is never guessed; details.hint), invalid_format, too_many_decimals, too_large (receiveAmount would need a send amount above the accepted maximum), a destination reason (invalid_evm_address, bad_checksum, zero_address, token_contract, invalid_monero_address, bad_monero_checksum, wrong_network, wrong_direction), invalid_basis, requires_receiveAmount (basis minimum with amount), minimum_not_published (basis minimum while the provider publishes no minimum receive amount: Wagyu v2 never does; quote without basis), requoteOf_exclusive (requoteOf sent together with other fields), invalid_quote_id, or an unsupported chain.
- `401`: agent_key_invalid: the agent key is malformed or unknown (details.field agentKey, details.reason malformed | unknown). Quote without it, or request one at POST /agent/key.
- `403`: agent_key_revoked: the agent key was revoked (details.field agentKey). Quote without it.
- `404`: quote_not_found: the requoteOf quoteId is unknown or too old. Quote again with direction and amount or receiveAmount.
- `415`: unsupported_media_type: the body must be JSON (content-type: application/json).
- `422`: target_not_reached: no send amount whose estimate meets receiveAmount was found before the search budget (5 provider quotes) ran out. details: receiveAmount, receiveAmountAtomic, bestSendAmount, bestSendAmountAtomic, bestEstimate, bestEstimateAtomic, upstreamQuotes. Quote again with amount, or another target. no_route: the provider has no route for this swap right now (retryable, Retry-After). below_provider_minimum: the provider refused the amount (details.minimumSwapUsd); a quote the provider prices below its minimum is answered 200 with terms.belowProviderMinimum true instead.
- `429`: Rate limited (also when too many receiveAmount searches run at once; a search spends one rate-limit token per provider quote). Honor Retry-After.
- `451`: geo_blocked
- `502`: upstream_* provider error (details.upstreamCode); retry later.
- `503`: service_paused: new swaps are paused (the provider is not ready; with details.reason provider_api_deprecated or provider_maintenance the provider refuses new orders on this API, not retryable), upstream_unavailable / upstream_unreachable (retryable), or agent_keys_unavailable: an agent key was sent while keys are not offered on this deployment (quote without it).

---

[API](https://skmtc.dev/xmrtousdc/apis/swapper-agent-api.md) · [All operations](https://skmtc.dev/xmrtousdc/apis/swapper-agent-api/llms.txt) · [OpenAPI document](https://skmtc.dev/xmrtousdc/apis/swapper-agent-api/revisions/9f4252126907?raw)
