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

# Quickstart

> Validate a MultiversX pair, request a quote, inspect transaction data, and verify the quote before signing.

Validate a MultiversX pair, request a swap quote, and verify the response fields needed before signing.

## Prerequisites

| Requirement   | Value                                        |
| ------------- | -------------------------------------------- |
| Base URL      | `https://swap.xoxno.com`                     |
| Auth          | None                                         |
| Rate limit    | 100 requests per second per IP               |
| Amount format | Integer strings in the token's smallest unit |

## 1. Validate The Pair

Call `/api/v1/pair-config` before quoting so your client has decimals and minimum input.

<Tabs>
  <Tab title="cURL">
    ```bash theme={"system"}
    curl "https://swap.xoxno.com/api/v1/pair-config?\
    from=WEGLD-bd4d79&\
    to=USDC-c76f1f"
    ```
  </Tab>

  <Tab title="TypeScript">
    ```ts theme={"system"}
    const pairRes = await fetch(
      "https://swap.xoxno.com/api/v1/pair-config?from=WEGLD-bd4d79&to=USDC-c76f1f"
    );
    if (!pairRes.ok) throw new Error(`pair check failed: ${pairRes.status}`);

    const pair = await pairRes.json();
    if (!pair.supported) throw new Error(pair.error);

    console.log(pair.decimalsIn, pair.decimalsOut, pair.minAmountIn);
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={"system"}
    import requests

    res = requests.get(
        "https://swap.xoxno.com/api/v1/pair-config",
        params={"from": "WEGLD-bd4d79", "to": "USDC-c76f1f"},
        timeout=10,
    )
    res.raise_for_status()

    pair = res.json()
    if not pair["supported"]:
        raise RuntimeError(pair["error"])

    print(pair["decimalsIn"], pair["decimalsOut"], pair["minAmountIn"])
    ```
  </Tab>

  <Tab title="Rust">
    ```rust theme={"system"}
    // Run inside an async function with reqwest and serde_json.
    let pair: serde_json::Value = reqwest::Client::new()
        .get("https://swap.xoxno.com/api/v1/pair-config")
        .query(&[("from", "WEGLD-bd4d79"), ("to", "USDC-c76f1f")])
        .send()
        .await?
        .error_for_status()?
        .json()
        .await?;

    if pair["supported"] != true {
        return Err(format!("pair unsupported: {}", pair["error"]).into());
    }

    println!(
        "{} {} {}",
        pair["decimalsIn"], pair["decimalsOut"], pair["minAmountIn"]
    );
    ```
  </Tab>
</Tabs>

Expected response:

```json theme={"system"}
{
  "supported": true,
  "decimalsIn": 18,
  "decimalsOut": 6,
  "minAmountIn": "1000000000"
}
```

## 2. Request A Quote

Quote 1 WEGLD to USDC. `1000000000000000000` is 1 WEGLD at 18 decimals.

<Tabs>
  <Tab title="cURL">
    ```bash theme={"system"}
    curl "https://swap.xoxno.com/api/v1/quote?\
    from=WEGLD-bd4d79&\
    to=USDC-c76f1f&\
    amountIn=1000000000000000000&\
    slippage=0.005"
    ```
  </Tab>

  <Tab title="TypeScript">
    ```ts theme={"system"}
    const params = new URLSearchParams({
      from: "WEGLD-bd4d79",
      to: "USDC-c76f1f",
      amountIn: "1000000000000000000",
      slippage: "0.005",
    });

    const quoteRes = await fetch(`https://swap.xoxno.com/api/v1/quote?${params}`);
    if (!quoteRes.ok) throw new Error(`quote failed: ${quoteRes.status}`);

    const quote = await quoteRes.json();
    console.log(quote.amountOut, quote.amountOutMin, quote.priceImpact);
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={"system"}
    import requests

    res = requests.get(
        "https://swap.xoxno.com/api/v1/quote",
        params={
            "from": "WEGLD-bd4d79",
            "to": "USDC-c76f1f",
            "amountIn": "1000000000000000000",
            "slippage": "0.005",
        },
        timeout=10,
    )
    res.raise_for_status()

    quote = res.json()
    print(quote["amountOut"], quote["amountOutMin"], quote["priceImpact"])
    ```
  </Tab>

  <Tab title="Rust">
    ```rust theme={"system"}
    // Run inside an async function with reqwest and serde_json.
    let quote: serde_json::Value = reqwest::Client::new()
        .get("https://swap.xoxno.com/api/v1/quote")
        .query(&[
            ("from", "WEGLD-bd4d79"),
            ("to", "USDC-c76f1f"),
            ("amountIn", "1000000000000000000"),
            ("slippage", "0.005"),
        ])
        .send()
        .await?
        .error_for_status()?
        .json()
        .await?;

    println!(
        "{} {} {}",
        quote["amountOut"], quote["amountOutMin"], quote["priceImpact"]
    );
    ```
  </Tab>
</Tabs>

Inspect these fields:

| Field            | Use                                  |
| ---------------- | ------------------------------------ |
| `amountOut`      | Smallest-unit output estimate.       |
| `amountOutMin`   | Slippage-protected minimum output.   |
| `amountOutShort` | Display amount for the output token. |
| `priceImpact`    | Decimal price impact estimate.       |

## 3. Request Transaction Data

Pass `sender` only when the user is ready to sign.

```bash theme={"system"}
curl "https://swap.xoxno.com/api/v1/quote?\
from=WEGLD-bd4d79&\
to=USDC-c76f1f&\
amountIn=1000000000000000000&\
slippage=0.005&\
sender=erd1..."
```

The response can include:

| Field         | Meaning                                                                    |
| ------------- | -------------------------------------------------------------------------- |
| `transaction` | Full MultiversX transaction object for wallet signing.                     |
| `txData`      | Encoded contract call data when a full transaction object is not returned. |

<Warning>
  Do not reuse `txData` across quote requests. It encodes route and slippage state from that request.
</Warning>

## Verify

You have a valid quickstart result when:

* `/api/v1/pair-config` returns `supported: true`.
* `amountIn` is greater than or equal to `minAmountIn`.
* `/api/v1/quote` returns non-zero `amountOut`.
* `amountOutMin` matches the slippage shown to the user.
* If `transaction` is present, `transaction.sender` matches the connected wallet.

## Common Failure

| Symptom                                 | Cause                                                           | Fix                                                                              |
| --------------------------------------- | --------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| Quote returns `400`                     | Both `amountIn` and `amountOut` were sent, or neither was sent. | Send exactly one amount field.                                                   |
| Pair is unsupported                     | Token is unknown or no route exists.                            | Stop before quoting and show `error` from pair config.                           |
| Signed transaction fails for ESDT input | Client used `txData` as the full data field.                    | Use the full `transaction` object, or wrap `txData` in the ESDT transfer prefix. |

## Next Steps

* [Quote endpoint](/aggregator/quote)
* [Pair config](/aggregator/pair-config)
* [Token amounts](/resources/token-amounts)
* [Quote freshness](/resources/quote-freshness)
