API reference
Create a swap order
POST
/v2/swapsCreate a durable swap order (supply your own sessionId only with a valid integrator key).
Authentication: None required. Optional: integrator key in X-Integrator-Key.
#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"· requiredvalue· 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 · requiredproduct·"swap"· requiredsessionId· 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"· requiredcustomerState· 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 · requireddepositAddressForms· array of objectkind·"shielded"·"transparent"· requiredaddress· string · required
depositChainId· integer · required — Non-negative integer chain identifier.depositToken· string · requireddepositTokenSymbol· string · requireddepositTokenDecimals· integer (0–36) · requireddepositAmount· string (atomic integer) · required — Positive base-10 integer in the asset’s atomic unit.toChainId· integer · required — Non-negative integer chain identifier.toToken· string · requiredtoTokenSymbol· string · requiredtoTokenDecimals· integer (0–36) · requiredtoAddress· string · requiredexpectedOutput· string or null · requiredamountUsd· number · requiredexpiresAt· string · requiredbonusStage·"none"·"coinflip"coinflipRequested· booleanfundingProvider·"privy"or null
Errors use the standard error envelope: branch on code, never on the message.
#Example
curl
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
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
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.