> For the complete documentation index, see [llms.txt](https://hinkal-team.gitbook.io/hinkal/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hinkal-team.gitbook.io/hinkal/hinkal-api/api-reference/swap.md).

# Swap

## Execute a private swap

> Relays a swap within the shielded balance, using swap calldata obtained from\
> \`GET /get-swap-data\`.\
> \
> \*\*EVM\*\*: \`feeToken\` is the input token. \`feeAmount\` is optional (computed server-side\
> if omitted). Authorized by a normal mode session (secp256k1 request signature, bound to\
> \`"POST /swap"\`) or an EIP-712 \`Swap\` typed-data signature.\
> \
> \*\*Solana\*\*: \`feeToken\` is not used — the server always uses \`tokenAddresses\[1]\` (the\
> output token) as the fee token; any value passed is ignored. The relay fee is computed\
> automatically; \`feeAmount\` is only needed to lock in an exact amount already returned by\
> \`GET /get-fee\` (with \`mintFrom = inputTokenAddress\`). Exactly two token addresses are\
> required: \`\[inputToken, outputToken]\`. Authorized by a normal mode session (secp256k1 request signature,\
> bound to \`"POST /swap"\`) or an EIP-712 mode session with a per-transaction ed25519\
> plain-text signature (primary type \`Swap\`).\
> \
> \*\*\`tokenAddresses\` and \`amounts\` for a swap:\*\*\
> \- Index 0: input token address, amount is negative (tokens leaving shielded balance)\
> \- Index 1: output token address, amount is positive (tokens entering shielded balance)<br>

```json
{"openapi":"3.0.3","info":{"title":"Hinkal API","version":"1.0.0"},"tags":[{"name":"Swap"}],"servers":[{"url":"https://api.hinkal.io","description":"Production"}],"paths":{"/swap":{"post":{"operationId":"swap","summary":"Execute a private swap","description":"Relays a swap within the shielded balance, using swap calldata obtained from\n`GET /get-swap-data`.\n\n**EVM**: `feeToken` is the input token. `feeAmount` is optional (computed server-side\nif omitted). Authorized by a normal mode session (secp256k1 request signature, bound to\n`\"POST /swap\"`) or an EIP-712 `Swap` typed-data signature.\n\n**Solana**: `feeToken` is not used — the server always uses `tokenAddresses[1]` (the\noutput token) as the fee token; any value passed is ignored. The relay fee is computed\nautomatically; `feeAmount` is only needed to lock in an exact amount already returned by\n`GET /get-fee` (with `mintFrom = inputTokenAddress`). Exactly two token addresses are\nrequired: `[inputToken, outputToken]`. Authorized by a normal mode session (secp256k1 request signature,\nbound to `\"POST /swap\"`) or an EIP-712 mode session with a per-transaction ed25519\nplain-text signature (primary type `Swap`).\n\n**`tokenAddresses` and `amounts` for a swap:**\n- Index 0: input token address, amount is negative (tokens leaving shielded balance)\n- Index 1: output token address, amount is positive (tokens entering shielded balance)\n","tags":["Swap"],"parameters":[{"$ref":"#/components/parameters/XHinkalRequestSignatureNormalMode"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sessionId":{"type":"string","format":"uuid"},"nonce":{"type":"string","format":"uuid"},"signature":{"type":"string","description":"EIP-712 or ed25519 signature (EIP-712 mode only)"},"chainId":{"type":"integer"},"tokenAddresses":{"type":"array","items":{"type":"string"},"description":"[inputTokenAddress, outputTokenAddress]"},"amounts":{"type":"array","items":{"type":"string"},"description":"[negativeInputAmount, positiveOutputAmount]"},"externalActionId":{"type":"string","description":"External action id string returned by GET /get-swap-data (e.g. \"Lifi\", \"Okx\")"},"swapData":{"type":"string","description":"Swap calldata returned by GET /get-swap-data"},"feeToken":{"type":"string","description":"Fee token for EVM swaps (typically the input token).\nNot used on Solana — the server always uses tokenAddresses[1]; any value passed is ignored.\n"},"feeAmount":{"type":"string","description":"Optional — omit it and the server computes the fee automatically. Pass it\nonly to lock in a fee amount already quoted from GET /get-fee.\n"}},"required":["sessionId","nonce","chainId","tokenAddresses","amounts","externalActionId","swapData"]}}}},"responses":{"200":{"description":"Relayed transaction hash","headers":{},"content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"txHash":{"type":"string"},"nonce":{"type":"string","description":"Echoed per-request `nonce` from the request, added before signing."}},"required":["success","txHash","nonce"]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"$ref":"#/components/responses/NonceConflict"},"500":{"$ref":"#/components/responses/ServerError"}}}}},"components":{"parameters":{"XHinkalRequestSignatureNormalMode":{"name":"x-hinkal-request-signature","in":"header","required":false,"schema":{"type":"string"},"description":"Required for **normal mode** sessions: hex-encoded compact secp256k1 signature `secp256k1_sign(SHA256(binding + \"\\n\" + JSON.stringify(body)))`, where `binding` is `\"POST <routePath>\"` for this endpoint. Omit for **EIP-712 mode** sessions — include `signature` in the request body instead. See [Authentication](/enclave-api/authentication) for the full signing scheme."}},"responses":{"BadRequest":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FailedResponse"}}}},"Unauthorized":{"description":"Invalid signature or reused nonce","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FailedResponse"}}}},"NonceConflict":{"description":"Request `nonce` already consumed. Each `nonce` is single-use; generate a fresh UUID for every request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FailedResponse"}}}},"ServerError":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FailedResponse"}}}}},"schemas":{"FailedResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[false]},"error":{"type":"string"}},"required":["success","error"]}}}}
```
