> For the complete documentation index, see [llms.txt](https://docs.sodax.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sodax.com/developers/packages/foundation/swaps-api.md).

# @sodax/swaps-api

Minimal, type-safe HTTP client for the SODAX backend **Swaps API v2**.

* Implements the `ISwapsApiV2` contract from `@sodax/types` over `fetch`.
* Validates every response at runtime with [valibot](https://valibot.dev), and transforms each chain-specific unsigned `tx` back to its domain shape (decimal-string → `bigint`, Injective index-object bytes → `Uint8Array`).
* Zero dependency on `@sodax/sdk`, viem, or wallet providers — only `@sodax/types` (types) and `valibot`.

It is the single source of the swaps wire client: `@sodax/sdk`'s `SwapsApiService` (`sodax.api.swaps`) is a thin adapter over this package, adding the SDK's `Result<T>` contract, logger, and transport-config resolution on top. Use `@sodax/swaps-api` directly when you want just the swaps backend without pulling in the full SDK.

## Install

```bash
pnpm add @sodax/swaps-api valibot
```

## Usage

```ts
import { SwapsApi, SwapsApiError } from '@sodax/swaps-api';

const api = new SwapsApi({ baseUrl: 'https://<swaps-api-host>' });

const tokens = await api.getTokens();
const quote = await api.getQuote({
  tokenSrc,
  tokenSrcChainKey,
  tokenDst,
  tokenDstChainKey,
  amount,
  quoteType: 'exact_input',
  partnerFee: { address: partnerReceiverOnSonic, percentage: 10 }, // 10 bps = 0.1%
});
```

`baseUrl` is required and injected by the caller — the package never hardcodes environment URLs. Optionally set `timeout` (ms — an overall per-call deadline that includes retries; on expiry the call throws `TIMEOUT_ERROR`), a custom `fetch` (for tests or non-standard runtimes; it receives the timeout `AbortSignal`), and extra `headers`.

## Partner fees

`partnerFee` has no default — this client forwards the body as given and does not read `new Sodax({ fee })` / `new Sodax({ swaps: { partnerFee } })`. Send the same value on quote and create-intent:

```ts
const partnerFee = { address: partnerReceiverOnSonic, percentage: 10 }; // 10 = 0.1%, 100 = 1%

const quote = await api.getQuote({ ...quoteBody, partnerFee });
const intent = await api.createIntent({ ...intentBody, partnerFee });
```

`checkAllowance` / `approve` inherit the field but ignore it. See [MONETIZE\_SDK.md](https://github.com/icon-project/sodax-sdks/blob/main/packages/sdk/docs/MONETIZE_SDK.md) for the orchestrator path.

## Errors

Every method **throws** a `SwapsApiError` on failure — a single typed error whose `code` is one of `NETWORK_ERROR` / `TIMEOUT_ERROR` / `HTTP_ERROR` / `PARSE_ERROR` / `VALIDATION_ERROR`, with diagnostic `context` (endpoint, method, path, HTTP status, validation issues) and the underlying failure on `.cause`. Idempotent calls (reads, polls, pure-compute POSTs like `getQuote`) are retried a few times on transient HTTP / network failures; a `timeout` and mutating calls are never retried.

> Note: this throwing contract is intentional and distinct from `@sodax/sdk`'s `sodax.api.swaps`, which wraps these calls and returns `Result<T>` instead of throwing.
