Your first swap

Quote a rate and execute a swap between two currencies.

This walks the minimum API calls to swap one currency for another. It assumes you've completed Authentication and are signing requests.

1. Quote the rate

Ask what 100 USD is worth in USDC right now. Each Currency is a plain object with the amount in its smallest denomination as a string (value), an ISO/asset code, and decimals (crypto also carries a chain):

POST /quote.get
Content-Type: application/json

{
    "currency_in":  { "value": "100", "code": "USD", "decimals": 2 },
    "currency_out": { "value": "0", "code": "USDC", "decimals": 6, "chain": "ethereum" }
}

(On a quote, currency_out.value is only a placeholder — "0" asks "what's the output worth?".) Response:

{
    "data": {
        "bid": { "value": "998000", "code": "USDC", "decimals": 6 },
        "ask": { "value": "1002000", "code": "USDC", "decimals": 6 },
        "direction": "ask",
        "fees": [],
        "stablecoin": null
    }
}

Show this rate to your user, or use it server-side to estimate output.

2. Execute the swap

POST /transaction.initiateSwap
Content-Type: application/json

{
    "currency_in":  { "value": "1000", "code": "USD", "decimals": 2 },
    "currency_out": { "value": "10000000", "code": "USDC", "decimals": 6, "chain": "ethereum" },
    "external_accounts": { "from": null, "to": null }
}

Pass a non-zero amount on both sides — currency_in is what you send, currency_out is the amount you expect back (take it from a recent quote.get). The engine checks that implied rate against the live market within a small tolerance, then re-quotes at execution time, so a slightly stale estimate is fine. The response is the new transaction id:

{ "data": "08a4d98b-07b1-4948-a6e7-7c0ee556d564" }

This is a PENDING transaction id — poll it via transaction.get or await it via webhook. There is no client idempotency key; the swap re-quotes at execution time.

3. Wait for settlement

The swap settles asynchronously. You have two options:

  • Webhook (recommended) — register a webhook and react to transaction.updated events reporting a terminal status. See Webhook setup.
  • Polling — call transaction.get with the returned transaction id until status === "COMPLETED". Backoff aggressively.

Next steps