# Create a swap order

> Create a durable swap order (supply your own sessionId only with a valid integrator key)

`POST /v2/swaps`

Create a durable swap order (supply your own sessionId only with a valid integrator key).

**Authentication:** None required. Optional: [integrator key](https://docs.wagyu.xyz/authentication.md) in `X-Integrator-Key`.

> **This creates a real order:** There is no sandbox and no idempotency key. Never retry this call automatically after a timeout: the first request may have created the order. See [Errors, limits, retries](https://docs.wagyu.xyz/actions-and-retries.md#retry-policy).

## Request body

- `fromChainId` · integer · **required** — Non-negative integer chain identifier.
- `toChainId` · integer · **required** — Non-negative integer chain identifier.
- `fromToken` · string · **required** — Token contract address on the corresponding chain. For a chain's native coin, send "native" or its native symbol.
- `toToken` · string · **required** — Token contract address on the corresponding chain. For a chain's native coin, send "native" or its native symbol.
- `fromAmount` · string (atomic integer) · **required** — Positive base-10 integer in the asset’s atomic unit.
- `toAddress` · string · **required** — Destination address. Its chain-specific validity is checked by the engine.
- `fromTokenSymbol` · string — Optional symbol hint for the same token. Resolution is driven by the token address, not by this value.
- `toTokenSymbol` · string — Optional symbol hint for the same token. Resolution is driven by the token address, not by this value.
- `sessionId` · string (pattern `^[0-9a-f-]{16,64}$`) — Optional session credential for an integrator to group its own orders. Requires a valid integrator API key.
- `refundAddress` · string (max 256) — Refund destination. Its chain-specific validity is checked by the engine.
- `coinflip` · boolean — Opt into the bonus flip when this order is eligible. The decision itself is sent later to PUT /v2/swaps/{id}/coinflip.
- `fundingProvider` · `"privy"` or null — Fiat onramp that will fund this order, when the deposit comes from a card purchase instead of a wallet.
- `integratorFeePercent` · number (0–5) — Optional integrator fee percentage. Requires a valid integrator API key.
- `clickId` · object — Google Ads click identifier, when this order came from an ad. Stored apart from the order, used once to report the conversion, then deleted; it is never published back on any order read.
  - `kind` · `"gclid"` · `"wbraid"` · `"gbraid"` · **required**
  - `value` · string (pattern `^[A-Za-z0-9_-]{16,200}$`) · **required**
- `source` · object — Where the visit that created this order came from. Marketing only: stored apart from the order, counted in reports, never published back on any order read.
  - `utmSource` · string (pattern `^[a-z0-9._-]{1,64}$`) — The landing link's utm_source.
  - `utmMedium` · string (pattern `^[a-z0-9._-]{1,64}$`) — The landing link's utm_medium.
  - `utmCampaign` · string (pattern `^[a-z0-9._-]{1,64}$`) — The landing link's utm_campaign.
  - `referrer` · string (pattern `^(?=.{1,253}$)[a-z0-9-]{1,63}(?:\.[a-z0-9-]{1,63})+$`) — Hostname of the site the visitor came from. Never a full URL.
  - `landing` · string (pattern `^\/[A-Za-z0-9/._-]{0,199}$`) — Path of the visit's first page.

## Response

`200` returns an object with:

- `orderId` · string · **required**
- `product` · `"swap"` · **required**
- `sessionId` · string (pattern `^[0-9a-f-]{16,64}$`) · **required** — 16–64 character hexadecimal/hyphen owner-session credential.
- `status` · `"awaiting_deposit"` · `"awaiting_xmr1"` · `"awaiting_trx1"` · `"awaiting_zec1"` · `"processing"` · `"completed"` · `"failed"` · `"expired"` · `"refunded"` · `"needs_review"` · **required**
- `customerState` · one of the variants below · **required** — Authoritative customer display/action state. Clients must not infer lifecycle from status or resource presence.
  - **kind = "awaiting_deposit"**
  - **kind = "processing"**
  - **kind = "action_required"**
  - **kind = "paused"**
  - **kind = "completed"**
  - **kind = "refunded"**
  - **kind = "expired"**
  - **kind = "failed"**
- `depositAddress` · string · **required**
- `depositAddressForms` · array of object
  - `kind` · `"shielded"` · `"transparent"` · **required**
  - `address` · string · **required**
- `depositChainId` · integer · **required** — Non-negative integer chain identifier.
- `depositToken` · string · **required**
- `depositTokenSymbol` · string · **required**
- `depositTokenDecimals` · integer (0–36) · **required**
- `depositAmount` · string (atomic integer) · **required** — Positive base-10 integer in the asset’s atomic unit.
- `toChainId` · integer · **required** — Non-negative integer chain identifier.
- `toToken` · string · **required**
- `toTokenSymbol` · string · **required**
- `toTokenDecimals` · integer (0–36) · **required**
- `toAddress` · string · **required**
- `expectedOutput` · string or null · **required**
- `amountUsd` · number · **required**
- `expiresAt` · string · **required**
- `bonusStage` · `"none"` · `"coinflip"`
- `coinflipRequested` · boolean
- `fundingProvider` · `"privy"` or null

Errors use the [standard error envelope](https://docs.wagyu.xyz/actions-and-retries.md#the-error-envelope): branch on `code`, never on the message.

## Example

<!-- curl -->
```bash
curl -X POST 'https://api-beta.wagyu.xyz/v2/swaps' \
  -H 'content-type: application/json' \
  -d '{
    "fromChainId": 20000000000001,
    "toChainId": 0,
    "fromToken": "bitcoin",
    "toToken": "XMR",
    "fromAmount": "1000000",
    "toAddress": "<your-monero-address>"
  }'
```

<!-- JavaScript -->
```javascript
const res = await fetch('https://api-beta.wagyu.xyz/v2/swaps', {
  method: 'POST',
  headers: {"content-type":"application/json"},
  body: JSON.stringify({
    "fromChainId": 20000000000001,
    "toChainId": 0,
    "fromToken": "bitcoin",
    "toToken": "XMR",
    "fromAmount": "1000000",
    "toAddress": "<your-monero-address>"
  }),
});
const data = await res.json();
```

<!-- Python -->
```python
import requests

res = requests.post('https://api-beta.wagyu.xyz/v2/swaps', json={
        "fromChainId": 20000000000001,
        "toChainId": 0,
        "fromToken": "bitcoin",
        "toToken": "XMR",
        "fromAmount": "1000000",
        "toAddress": "<your-monero-address>"
    }, timeout=30)
data = res.json()
```

_No response is captured for this route: calling it creates or changes a real order. The response fields above come from the live contract._

---
Source: https://docs.wagyu.xyz/api-reference/create-swap-order · Built from the live Wagyu API on 2026-11-04.
