> For the complete documentation index, see [llms.txt](https://docs.swap.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.swap.io/developer-tools/agent-api-x402/quickstart.md).

# Quickstart

A full swap is two paid calls: get quotes, then build the transaction for the quote you choose. Broadcasting and tracking (step 4 below) are optional: you can sign and send the built transaction yourself with any Solana RPC instead.

## 1. See the price

An unpaid request returns HTTP 402 with the price and payment terms for that exact request:

```bash
curl -s -X POST https://hermes.swap.io/v1/swap/quote \
  -H 'Content-Type: application/json' \
  -d '{
    "input":  {"token": "So11111111111111111111111111111111111111112", "amount": "1000000000", "chainKey": "sol"},
    "output": {"token": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "chainKey": "sol"},
    "userAddress": "YOUR_WALLET_ADDRESS",
    "slippageBps": 50
  }'
```

The response is a standard x402 payment-required body; `maxAmountRequired` is the price in atomic USDC (6 decimals, `"1000"` = $0.001).

## 2. Get quotes

Any x402-compatible client handles the pay-and-retry loop for you. Example with [`x402-solana`](https://www.npmjs.com/package/x402-solana):

```js
import { createX402Client } from 'x402-solana/client';
import { Keypair } from '@solana/web3.js';

const payer = Keypair.fromSecretKey(/* your key */);

const client = createX402Client({
  wallet: {
    address: payer.publicKey.toString(),
    signTransaction: async (tx) => { tx.sign([payer]); return tx; },
  },
  network: 'solana',
});

const quoteResp = await client.fetch('https://hermes.swap.io/v1/swap/quote', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    input:  { token: 'So11111111111111111111111111111111111111112', amount: '1000000000', chainKey: 'sol' },
    output: { token: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', chainKey: 'sol' },
    userAddress: payer.publicKey.toString(),
    slippageBps: 50,
  }),
});

const { quotes } = await quoteResp.json();
const best = quotes[0]; // quotes are ranked; bestQuote marks the winner
```

Each quote carries the provider, input and output amounts, price impact, minimum output and the provider's own `providerQuote` payload.

## 3. Build the transaction

Pass the chosen quote's `providerQuote` back to build the transaction:

```js
const buildResp = await client.fetch('https://hermes.swap.io/v1/swap/build-tx', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    provider: best.provider.key,
    userAddress: payer.publicKey.toString(),
    chainKey: 'sol',
    quoteResponse: best.providerQuote,
  }),
});

const { transaction } = await buildResp.json(); // base64, unsigned
```

Sign `transaction` with your `userAddress` key and broadcast it. Quotes are short-lived, so build and send promptly.

The official [`@x402/fetch`](https://www.npmjs.com/package/@x402/fetch) with `@x402/svm` works the same way. Your wallet only needs USDC; network fees of the payment itself are not yours to pay.

Every paid response carries an `X-PAYMENT-RESPONSE` header with the on-chain settlement transaction hash.

## 4. Submit and track (optional)

You can broadcast the signed transaction yourself with any Solana RPC. If you would rather Hermes do it, sign the transaction (see step 3) and call `submit-tx`, then poll the free `status` endpoint until it confirms:

```js
import { VersionedTransaction } from '@solana/web3.js';

const unsigned = VersionedTransaction.deserialize(Buffer.from(transaction, 'base64'));
unsigned.sign([payer]);
const signedTransaction = Buffer.from(unsigned.serialize()).toString('base64');

const submitResp = await client.fetch('https://hermes.swap.io/v1/swap/submit-tx', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    signedTransaction,
    provider: best.provider.key,
    chainKey: 'sol',
  }),
});
const { transactionHash } = await submitResp.json();

// Free: no payment needed. Poll with a delay, stop on any terminal status
// (including a failed transaction), and give up after a bounded deadline.
let status = null;
const deadline = Date.now() + 15_000;
while (Date.now() < deadline) {
  const statusResp = await fetch(`https://hermes.swap.io/v1/swap/status?chainKey=sol&id=${transactionHash}`);
  ({ status } = await statusResp.json());
  if (status === 'finalized' || status === 'failed') break;
  await new Promise((resolve) => setTimeout(resolve, 1_500));
}
```

`submit-tx` is paid and settles as soon as the network accepts the transaction and returns a `transactionHash`, not when it is confirmed or finalized. `status` is free, so poll it as often as you like to track confirmation; the top-level `status` field is the terminal signal (`finalized` or `failed`).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.swap.io/developer-tools/agent-api-x402/quickstart.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
