> ## Documentation Index
> Fetch the complete documentation index at: https://tetrafi.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> From your first firm quote to a settled trade on the RFQ API.

By the end of this page an RFQ trade of yours will have settled on-chain. The route there: find a tradable corridor, put LPs in competition, authorize the winner, watch the escrow do its job.

<Info>
  **Outcome:** a working quote-to-settlement loop you can build on.

  **Time:** one coffee (10-15 minutes).

  **Bring:** EVM wallet basics, a grasp of token approvals, and an API key (`tfk_test_` targets the sandbox).
</Info>

## Step 1 - Find What's Tradable

What's quotable is a moving target - LPs join, corridors open - so treat this data as a feed to poll, never a constant to pin.

### List Tradable Pairs

Fetch the pairs currently quotable across your workspace's eligible solvers:

```
GET /api/v1/pairs
```

<CodeGroup>
  ```bash bash theme={null} theme={null}
  curl https://api.tetrafi.io/api/v1/pairs \
    -H "X-API-Key: tfk_test_..."
  ```

  ```python python theme={null} theme={null}
  import httpx

  resp = httpx.get(
      "https://api.tetrafi.io/api/v1/pairs",
      headers={"X-API-Key": "tfk_test_..."},
  )
  data = resp.json()
  print(data)
  ```
</CodeGroup>

Response (abridged):

```json theme={null} theme={null}
{
  "pairs": [
    {
      "input":  { "chainId": 10,   "address": "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85", "symbol": "USDC", "decimals": 6 },
      "output": { "chainId": 8453, "address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "symbol": "USDC", "decimals": 6 },
      "corridor": "optimism-base"
    }
  ]
}
```

Each entry names the exact input and output asset - use those `chainId` + `address` pairs verbatim in your quote requests. The networks themselves are listed on [Supported Chains](/supported-chains).

### See Who's Quoting

Solvers and LPs are the counterparties behind every RFQ quote. You can inspect the roster your workspace can reach:

```
GET /api/v1/solvers
```

<CodeGroup>
  ```bash bash theme={null} theme={null}
  curl https://api.tetrafi.io/api/v1/solvers \
    -H "X-API-Key: tfk_test_..."
  ```

  ```python python theme={null} theme={null}
  import httpx

  resp = httpx.get(
      "https://api.tetrafi.io/api/v1/solvers",
      headers={"X-API-Key": "tfk_test_..."},
  )
  for s in resp.json()["solvers"][:5]:
      print(s["id"], s.get("status"))
  ```
</CodeGroup>

Key discovery fields:

| Field                  | Description                                                             |
| ---------------------- | ----------------------------------------------------------------------- |
| `input` / `output`     | The tradable asset on each side - `chainId` plus contract `address`     |
| `decimals`             | The exponent between human units and base units - six for USDC, so ×10⁶ |
| `corridor`             | Directional route name; the cross-chain analog of a trading pair        |
| solver `id` / `status` | Who can quote, and whether they're currently active                     |

<Tip>
  **Keep it fresh:** a daily re-pull of the pair list is the floor - inventory shifts and new listings land continuously.
</Tip>

## Step 2 - Collect Firm Quotes

Every quote is a live commitment with a countdown attached (roughly a minute of validity) - collect them at decision time, not ahead of it.

### Authentication

<Warning>
  Requests without a credential are rejected with `401 AUTH_REQUIRED` - there is no anonymous quoting.
</Warning>

Use a `tfk_test_` key against the sandbox while you build, then switch to `tfk_live_` for production. See [Authentication](/core-concepts/authentication) for key setup.

### A First Quote Request

```
POST /api/v1/rfq/quotes
```

The request body describes your intent:

| Field              | Description                                                    | Example               |
| ------------------ | -------------------------------------------------------------- | --------------------- |
| `user`             | Wallet that signs and funds the trade                          | `0xYourWalletAddress` |
| `intent.inputs[]`  | What you're sending: `{user, asset{chainId, address}, amount}` | 25 USDC on Optimism   |
| `intent.outputs[]` | What you receive: `{receiver, asset{chainId, address}}`        | USDC on Base          |
| `intent.swapType`  | `ExactInput` or `ExactOutput`                                  | `ExactInput`          |
| `supportedTypes`   | Order payloads your signer can handle                          | `["escrow-v0"]`       |

<Note>
  **Delivery is addressable:** funding and signing belong to the input's `user`, but each output lands wherever its `receiver` says - a third-party wallet included, whichever execution mode runs.
</Note>

<Accordion title="ExactInput or ExactOutput?">
  * `ExactInput` fixes what you send - "sell 25 USDC, receive whatever it buys"
  * `ExactOutput` fixes what you get - "deliver exactly 20 USDC, charge what it takes"
</Accordion>

<Accordion title="From human units to base units">
  ```
  base_units = human_amount × 10^decimals
  ```

  So 250 USDC (6 decimals) travels on the wire as 250 × 10⁶ = `250000000`
</Accordion>

Example - moving 25 USDC from Optimism to Base:

<CodeGroup>
  ```bash bash theme={null} theme={null}
  curl -X POST https://api.tetrafi.io/api/v1/rfq/quotes \
    -H "X-API-Key: tfk_test_..." \
    -H "Content-Type: application/json" \
    -d '{
      "user": "0x2e7E7cc62919eAf4c502dAC34753cFc5A29e9693",
      "intent": {
        "intentType": "swap",
        "inputs": [{
          "user": "0x2e7E7cc62919eAf4c502dAC34753cFc5A29e9693",
          "asset": {"chainId": 10, "address": "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85"},
          "amount": "25000000"
        }],
        "outputs": [{
          "receiver": "0x2e7E7cc62919eAf4c502dAC34753cFc5A29e9693",
          "asset": {"chainId": 8453, "address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}
        }],
        "swapType": "ExactInput"
      },
      "supportedTypes": ["escrow-v0"]
    }'
  ```

  ```python python theme={null} theme={null}
  import httpx

  API = "https://api.tetrafi.io/api/v1"
  ME = "0x2e7E7cc62919eAf4c502dAC34753cFc5A29e9693"

  usdc_op   = {"chainId": 10,   "address": "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85"}
  usdc_base = {"chainId": 8453, "address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}

  amount_human = 25.0
  decimals = 6

  resp = httpx.post(
      f"{API}/rfq/quotes",
      json={
          "user": ME,
          "intent": {
              "intentType": "swap",
              "inputs": [{"user": ME, "asset": usdc_op,
                          "amount": str(int(amount_human * 10**decimals))}],
              "outputs": [{"receiver": ME, "asset": usdc_base}],
              "swapType": "ExactInput",
          },
          "supportedTypes": ["escrow-v0"],
      },
      headers={"X-API-Key": "tfk_test_..."},
  )
  quotes = resp.json()
  print(quotes)
  ```
</CodeGroup>

<Tip>
  **Building a wallet or super-app?** Quotes whose execution mode is `apiSubmit` let TetraFi handle on-chain submission for your users. The [Order Submission guide](/rfq-api/guides/gasless-execution) covers that path end to end.
</Tip>

### Making Sense of the Response

Every entry is a firm quote from a competing solver or LP - ranked, with the best first:

```json theme={null} theme={null}
{
  "quotes": [
    {
      "quoteId": "q_01J2M8...",
      "solverId": "lp-atlas",
      "order": {
        "type": "escrow-v0",
        "payload": { "domain": { "...": "..." }, "types": { "...": "..." }, "message": { "...": "..." } }
      },
      "validUntil": 1784560045,
      "eta": 40,
      "preview": {
        "inputs":  [{ "asset": "eip155:10/erc20:0x0b2C...Ff85",  "amount": "25000000", "symbol": "USDC", "decimals": 6 }],
        "outputs": [{ "asset": "eip155:8453/erc20:0x8335...2913", "amount": "24987500", "symbol": "USDC", "decimals": 6 }]
      },
      "integrityChecksum": "9c41f2...",
      "routingPath": "direct",
      "platformFeeBps": 5,
      "lpSpreadBps": 3
    }
  ],
  "totalQuotes": 3,
  "metadata": {
    "totalDurationMs": 380,
    "solversQueried": 5,
    "solversSuccess": 3
  }
}
```

What to read first:

| Field               | Description                                                          |
| ------------------- | -------------------------------------------------------------------- |
| `quoteId`           | Carries the quote through preflight, submission, and tracking        |
| `solverId`          | The LP or solver standing behind this commitment                     |
| `preview.outputs`   | What you'll receive - the amount here is what the escrow enforces    |
| `validUntil`        | Unix expiry; sign and submit before it passes                        |
| `order`             | The `escrow-v0` EIP-712 envelope you sign - exactly as returned      |
| `integrityChecksum` | Ties your submission to this precise quote; any drift is rejected    |
| `metadata`          | The competition at a glance - how many were asked, how many answered |

<Warning>
  **Never hardcode contract addresses.** Approval spenders and settlement addresses come from the preflight `nextActions` for the quote you picked - they differ by chain, funding lock, and workspace: your trades enter through **your workspace's own router contract**, deployed for your workspace at provisioning.

  See [Settlement & Smart Contracts](/core-concepts/settlement-smart-contracts) and the [Token Approvals guide](/core-concepts/token-approvals).
</Warning>

## Step 3 - Sign and Settle

Preflight your chosen quote, run any approval actions it lists, then follow its plan: sign the `escrow-v0` payload and submit - or broadcast the prepared transaction yourself when the quote's mode is `walletBroadcast`.

<Note>
  Partial fills are supported when the intent sets `partialFill: true`. See the [Partial Fills guide](/rfq-api/guides/partial-fills).
</Note>

The preflight plan (`nextActions`) contains everything: approval transactions ready to broadcast, the typed data to sign, and where to submit it.

<Info>
  For the full `apiSubmit` path - signing the typed data and POSTing the order while TetraFi handles gas - see the [Order Submission guide](/rfq-api/guides/gasless-execution).
</Info>

```python theme={null} theme={null}
import time

import httpx
from eth_account import Account
from eth_account.messages import encode_typed_data

API = "https://api.tetrafi.io/api/v1"
KEY = "tfk_test_..."
PRIVATE_KEY = "0x<your_private_key_hex>"

headers = {"X-API-Key": KEY}
account = Account.from_key(PRIVATE_KEY)

# --- 1. Pick the best quote ---
selected = quotes["quotes"][0]

# --- 2. Preflight it ---
pf = httpx.post(f"{API}/rfq/orders/preflight", headers=headers,
                json={"quoteResponse": selected}).json()

# (run any tokenApproval actions here - see the Token Approvals guide)

# --- 3. Sign the escrow-v0 payload ---
sign_action = next(a for a in pf["nextActions"] if a["purpose"] == "orderSignature")
signable = encode_typed_data(full_message=sign_action["typedData"])
signature = Account.sign_message(signable, private_key=PRIVATE_KEY).signature.hex()

# --- 4. Submit ---
order = httpx.post(f"{API}/rfq/orders",
                   headers={**headers, "Idempotency-Key": selected["quoteId"]},
                   json={"quoteResponse": selected, "signature": signature}).json()
print("Order:", order["id"])

# --- 5. Follow it to settlement ---
while True:
    o = httpx.get(f"{API}/rfq/orders/{order['id']}", headers=headers).json()
    print("status:", o["status"])
    if o["status"] in ("settled", "failed"):
        break
    time.sleep(2)
```

The moving parts:

| Step      | What happens                                                                                        |
| --------- | --------------------------------------------------------------------------------------------------- |
| Preflight | Confirms the quote is still executable and hands you the exact action plan                          |
| Sign      | Your wallet signs the order's typed data, verbatim                                                  |
| Settle    | Funds lock in escrow, delivery is verified, and your output is released - or the escrow refunds you |

## Where Next

Ready for more? The guides go deeper:

<CardGroup cols={2}>
  <Card title="Token Approvals" icon="key" href="/core-concepts/token-approvals">
    The approval loop and the three funding locks.
  </Card>

  <Card title="Order Submission" icon="wand-magic-sparkles" href="/rfq-api/guides/gasless-execution">
    Gas-free UX for your users: TetraFi carries the transaction.
  </Card>

  <Card title="Partial Fills" icon="chart-pie" href="/rfq-api/guides/partial-fills">
    Fill what's available now, refund the rest.
  </Card>

  <Card title="Multi-Token Trades" icon="arrows-rotate" href="/rfq-api/guides/multi-token-trades">
    Multiple inputs and outputs in a single order.
  </Card>
</CardGroup>
