Skip to Content
XO SwapV3 API StableEndpointsOrdersCreate Fixed Order

Create an order

POST/v3/orders

Description

Create an order using rates. This endpoint is designed for standard swaps using fixed rates from /v3/pairs/:pairId/rates.

If due to the user’s location there’s a restriction in the swap, it will return an error instead.

Header Parameters

NameDescriptionRequiredExample
App-NameApp-Name for the authorizationyesacme-inc
App-VersionApp-Version for the authorizationno23.5.5
App-PlatformClient platform: desktop, mobile, or browsernobrowser
ForwardedIf you are proxying requests to the API, you must include the "Forwarded" header with the original request IP address. This is used for geolocation availability purposes.no
User-AgentUser-Agent for the authorizationnoAgentName/1.0.0

Payload

NameDescriptionRequired
fromAmountAmount the user is sending to exchange in the 'from' asset unit. Exact when swapMode is ExactIn. When it is ExactOut, it is an estimate — but the estimate provider limits are checked against, so it still has to be realistic. See Swap Modes below.yes
fromAddressAddress from which the user is sending the funds.yes
fromAddressTagThe tag/memo of the fromAddress. Only required for certain assets like ATOM, EOS, XRP, etc.no
toAmountThe amount you want to receive in the 'to' asset. Estimated when swapMode is ExactIn, exact when it is ExactOut.yes
toAddressThe address to receive the exchanged fundsyes
toAddressTagThe tag/memo of the toAddress. Only required for certain assets like ATOM, EOS, XRP, etc.no
pairIdThe pair id for this exchange. Read the pairs documentation to find the correct one.yes
slippagePercentage of slippage tolerance with a 2% by default.no
swapModeEither 'ExactIn' or 'ExactOut', with 'ExactIn' by default. Decides which of fromAmount and toAmount is the exact amount. See Swap Modes below.no

Swap Modes

swapMode decides which side of the swap is exact. Both fromAmount and toAmount are still required in either mode. The one that is not exact is an estimate, and in ExactOut that estimate is not inert — see fromAmount in ExactOut below.

ModeExact amountUse it when
ExactIn (default)fromAmountThe user picks how much to send, and you price what they will receive.
ExactOuttoAmountThe user picks how much to receive, and you price what they have to send.

fromAmount in ExactOut

fromAmount is not what the user ends up sending in ExactOut: the selected route decides that, and the created order returns it as amount. But it is not ignored either, and two of its uses can change the outcome of the request:

  • Limits. Provider limits are checked against fromAmount in the from asset unit, exactly as in ExactIn (rate.min.value <= fromAmount and rate.max.value >= fromAmount). They are never applied to toAmount. A fromAmount outside a provider’s limits drops that provider; outside every provider’s limits, there is no route left and the order fails.
  • Route ranking. Miner fees are weighed against fromAmount, so an estimate that is far off can rank a worse route first.

So send a real estimate, not a placeholder. There is no ExactOut-keyed pricing endpoint in v3 — /v3/pairs/:pairId/rates is not amount-keyed and /v3/pairs/:pairId/quotes takes an amount in the from asset — so derive the estimate from the same rates payload by inverting the best-rate formula. This is the arithmetic the API itself applies to the winning route:

ExactOut estimate
// Inverse of `toAmount = fromAmount * rate.amount.value - rate.minerFee.value`.
// Rate values are numbers, but body amounts are strings — coerce before adding,
// since `+` concatenates where `*` and `-` would have coerced.
const fromAmount = (Number(toAmount) + rate.minerFee.value) / rate.amount.value;

Amounts cross back into the request body as strings, so send fromAmount.toFixed(8) rather than the number.

Example payload:

ExactOut payload
// The user wants exactly 1000 USDC, whatever it costs in BTC.
const body = {
  pairId: 'BTC_USDC',
  swapMode: 'ExactOut',
  toAmount: '1000',
  fromAmount: '0.01050000', // estimate, from the formula above
  fromAddress: 'bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq',
  toAddress: '0x531a9aA0f2cF0F0B193d6Ca6aA9d990a54A2657a',
};

ExactOut is more restricted than ExactIn. It only routes through providers that support exact output, so a pair that prices fine with ExactIn can legitimately return no route with ExactOut. ExactOut orders are also excluded from fee-sponsorship campaigns. And swapMode is only accepted here — POST /v3/orders/float has no swapMode, so floating orders are always ExactIn.

Response

Successful order creation
{
  "amount": {
    "assetId": "BTC",
    "value": 0.47
  },
  "createdAt": "2019-08-24T14:15:22Z",
  "fromAddress": "EJVsaNYRzo1GVhzrmYM5WnxU9FUnBtibjKNAkkq9YaP2",
  "fromAddressTag": "string",
  "fromTransactionId": "37CUt9gzAGN8LcZ2haCFmioAXn2FPp9f7y",
  "id": "vQm7GDXboWw6NbL",
  "message": "string",
  "pairId": "BTC_ETH",
  "payInAddress": "37CUt9gzAGN8LcZ2haCFmioAXn2FPp9f7y",
  "payInAddressTag": "string",
  "providerOrderId": "6fkmegv6ce6mz68refdd",
  "rateId": "6d31e45a-daa8-4578-84da-9fedb3117c1f",
  "toAddress": "0x531a9aA0f2cF0F0B193d6Ca6aA9d990a54A2657a",
  "toAddressTag": "string",
  "toTransactionId": "0x531a9aA0f2cF0F0B193d6Ca6aA9d990a54A2657a",
  "updatedAt": "2019-08-24T14:15:22Z",
  "status": "awaiting",
  "extraFeatures": {
    "pid": "string",
    "stringAmounts": "string"
  }
}

Start building

XO

Request Demo

Schedule a call with our team

Select a product
Arrow right

Start building
Grateful

Contact Us

We're here to help