For the complete documentation index, see llms.txt. This page is also available as Markdown.

API (Order-Router)

Haystack Order Router API specifications for fetching quotes and executing swaps.

Overview

Base URL: https://hayrouter.txnlab.dev

Swapping takes two calls:

  1. GET /api/fetchQuote finds the best route and returns a quote, including an opaque txnPayload.

  2. POST /api/fetchExecuteSwapTxns turns that txnPayload into a transaction group for the swapper to sign and submit.

The TypeScript SDK wraps both calls, including signing and submission. Use it unless you need to call the API directly.

API keys and rate limits

An API key is required for fetchQuote and fetchExecuteSwapTxns. It is passed as the apiKey query parameter (GET) or the apiKey body field (POST); there is no header-based authentication.

The public free-tier key 1b72df7e-1131-4449-8ce1-29b79dd3f51e is limited to 60 requests per minute per IP, shared between fetchQuote and fetchExecuteSwapTxns. To obtain a custom API key with a higher limit, reach out to support@txnlab.dev.

Requests over the limit receive 429 Too Many Requests with the plain-text body Rate limit exceeded. On fetchQuote and fetchAssets the 429 arrives after a delay of about 3 seconds and carries a Retry-After: 60 header; fetchExecuteSwapTxns returns it immediately, without the header. fetchAssets has no key and is limited to 10 requests per minute per IP.

Errors

Error responses are plain text (Content-Type: text/plain) containing a short message, for example invalid api key. The one exception is an unregistered referrer on fetchQuote, which returns JSON: {"error": "..."}.

Networks

Only Algorand mainnet is supported.

Fetch the Haystack quote for a given swap.

GET https://hayrouter.txnlab.dev/api/fetchQuote

Query Parameters

Name
Type
Description

apiKey*

String

fromASAID*

Integer

The asset ID of the input asset for the swap (ALGO ID is 0).

toASAID*

Integer

The asset ID of the output asset for the swap (ALGO ID is 0).

amount*

Integer

Swap amount. The input swap amount, if the swap type is fixed-input, or the desired output swap amount, if the swap type is fixed-output. The amount is expected to be in base units (not normalized to account for decimals). Eg. an amount of 1000001 for asset ALGO would equate to 1.000001 ALGO (since ALGO is displayed with 6 decimals).

type*

String

Swap type. Either fixed-input or fixed-output.

disabledProtocols

String

Comma-delimited list of protocols to exclude from routing (case-insensitive). Valid protocol names are: - Pact (includes Pact stableswap and Pact V2 pools) - TinymanV2 - Algofi (includes AlgoFi nanoswap and lending pools) - Folks - TAlgo - XAlgo Unrecognized names are ignored.

maxDepth

Integer

Maximum number of hops in a single route path. The default is 4, the maximum is 5.

maxGroupSize

Integer

The max allowable size of the transaction group for the quote to be generated. The default is 16 (the Algorand maximum). Slots needed by the transactions fetchExecuteSwapTxns prepends (see optIn) are reserved automatically.

optIn

Boolean

Set to true to have the transactions returned from fetchExecuteSwapTxns include the swapper's opt-in to the output asset. The default is false.

Whether or not an opt-in is necessary is up to the caller to determine. Ignored when the output asset is ALGO. Uses one slot of maxGroupSize.

referrerAddress

String

Algorand address of the referrer, who will receive 25% of the swap fees in their referrer escrow. The address must be registered with the referral program, otherwise the request fails with a 400. When not set, the protocol treasury receives the full fee.

feeBps

Integer

Fee in basis points charged on the output, split 75% / 25% between treasury and referrer. The default and minimum is 10 (0.10%); lower values are raised to 10. The order router app caps total fees (including captured positive slippage) at 3% of the expected output. See Fees.

atomicOnly

Boolean

Guarantee that the swap can be executed using a single transaction group. Either true or false. The default is true.

chain

String

Chain for the given swap. Only mainnet (the default) is supported.

Example request

Response fields

Field
Description

quote

The Haystack quote, in base units. For fixed-input quotes, the output amount the swapper receives (net of the Haystack fee). For fixed-output quotes, the input amount required.

profit

{ amount, asa }: how much better quote (after the Haystack fee) is than the best entry in quotes (swapping directly on that pool, with no Haystack fee), in base units of asa: more output for fixed-input, less input for fixed-output. 0 when the route doesn't beat the best direct pool after the fee; never negative. asa is an asset object.

priceBaseline

Baseline (spot) price of the pools the route uses, before price impact. Informational: userPriceImpact is computed from USD prices, not from this value.

userPriceImpact

Price impact to the user in percent, including fees, computed from the USD values below.

usdIn / usdOut

Approximate USD value of the input and output amounts. 0 if either asset has no USD price.

route

The routing of the swap: a list of { percentage, path } splits. Each path is a list of hops { name, class, in, out }, where in/out are asset objects. A hop split across several pools has a combined name, e.g. "tinyman-V2: 0.36% fee tier (97%), algofi: 0.75% fee tier (3%)".

flattenedRoute

Share of the route handled by each protocol (0–1, summing to 1), for display. Each split's percentage is divided evenly across its hops, then by each pool's share within a hop.

quotes

Quotes from individual pools that trade the pair directly ({ class, name, value }), best first, before the Haystack fee. Useful for comparison; an empty array when no pool trades the pair directly.

protocolFees

Estimated fees per protocol, in base units. The deflex key holds the Haystack Order Router fee.

requiredAppOptIns

Application IDs the swapper must be opted into before executing. Currently always empty.

txnPayload

{ iv, data }: an opaque, encrypted payload. Pass it unchanged to fetchExecuteSwapTxns as txnPayloadJSON.

fromASAID, toASAID, type

Echo of the request.

traceId

Request trace ID. Include it when reporting issues.

aggregatedArtifacts, ui

Internal routing details used by the Haystack app. Informational only and subject to change.

If no route is found, the response is still 200 with quote: 0, an empty route, and an empty txnPayload.data. The other fields are only partly filled in that case (for example, traceId is empty and type is returned as to or from). Check that quote is greater than 0 before calling fetchExecuteSwapTxns, which rejects the empty payload with a 400.

Other messages include:

  • type argument must be 'fixed-input' or 'fixed-output'

  • feeBps must be an integer between 0 and 9999

  • Invalid referrer address

  • invalid assets (followed by the details, e.g. an unknown asset ID, or fromASAID equal to toASAID)

An unregistered referrerAddress returns JSON:

Plain-text error message.

Fetch the transaction group for a given Haystack quote.

POST https://hayrouter.txnlab.dev/api/fetchExecuteSwapTxns

Returns a single atomic transaction group that executes the quote through the Order Router App. The group includes:

  • the swapper's opt-in to the output asset, if the quote was requested with optIn=true (pays its own fee)

  • any treasury escrow opt-ins needed to receive the fee in the output asset: per escrow, a 0.1 ALGO payment and an app call, both signed and paid by the swapper

  • the order router app's call opting into the route's assets, pre-signed by the server

  • the swapper's transfer of the input amount to the order router app, which carries the network fees for all the order router app calls

  • for routes through AlgoFi nanoswap, a payment from the swapper that funds those swaps, the swaps themselves (sent from the order router app account), and a transaction rekeying the app account back

  • the order router app calls that perform the swaps and finalize, pre-signed by the server

For fixed-output swaps, the route produces slightly more than the target. When the route can swap back to the input asset, the surplus is swapped back within the same group. For small targets of high-value assets, where that swap back would cost more than it returns, the route instead overshoots by a few base units, which the order router app keeps as fee (within the 3% cap). Any input left over is sent to the beneficiary.

Request Body

Name
Type
Description

address*

String

Algorand address of the swapper.

txnPayloadJSON*

Object

Txn payload from the Haystack quote (value at txnPayload key), unchanged.

slippage*

Number

Slippage tolerance in percent, from 0 (inclusive) to 100 (exclusive), e.g. 0.5 for 0.5%. For fixed-input, the minimum output is quote × (1 − slippage / 100). For fixed-output, the output is exact and the input sent is raised to quote / (1 − slippage / 100). When the route swaps its surplus back, that extra input is swapped forward through the same pool and the excess swapped back, so the swap still delivers if prices move against it by up to about half the slippage, at a cost of about two pool fees on the extra input. On other routes, and on swaps too small for this to cover its network fee, the extra input is not used. Unused input is sent to the beneficiary.

apiKey*

String

beneficiary

String

Algorand address that receives the swap output. The default is address.

Response fields

Field
Description

txns

The transactions of the group, in order. Each has data (base64 msgpack of the unsigned transaction), group (base64 group ID), logicSigBlob and signature.

txns[].logicSigBlob

false for transactions the swapper must sign. For transactions the server has already signed, the signed transaction bytes, encoded as an object mapping each byte index to its value ({"0": 130, "1": 163, ...}). Submit these as-is.

txns[].signature

false for transactions the swapper must sign; otherwise describes how the server signed the transaction. Can be ignored.

groupMetadata

One entry per group: group, labelText (Deflex to Swap for fixed-input, Deflex from Swap for fixed-output), amount (the input amount sent, after slippage), swapCount, labelMetadata and plannedRefund.

plannedRefundTotal

Reserved, currently always 0.

Other messages include:

  • invalid api key

  • Invalid request body

  • Slippage must be a valid number

  • Slippage must be a number between 0 (inclusive) and 100 (exclusive)

  • Invalid txnPayload data

  • Failed to parse decrypted payload (also returned for the empty payload of a quote with quote: 0)

  • Failed to parse artifacts from payload

Plain-text error message.

Fetch the list of supported assets

GET https://hayrouter.txnlab.dev/api/fetchAssets

Returns every asset the router can quote, ordered by number of swaps. No API key is required; limited to 10 requests per minute per IP.

Query Parameters

Name
Type
Description

chain

String

Only mainnet (the default) is supported.

Fetch the referrer escrow address

GET https://hayrouter.txnlab.dev/api/treasuryAddress

Returns the escrow account that holds a referrer's commissions. See Referral Program.

Query Parameters

Name
Type
Description

address*

String

Algorand address of the referrer.

Fetch treasury escrow account details

GET https://hayrouter.txnlab.dev/api/fetchTreasuryDetails

Returns the on-chain account state of the treasury escrow accounts that receive fees: the protocol treasury escrow, plus the referrer's escrow when referrerAddress is given. The server refreshes its copy every minute, and responses may be cached by a CDN for up to 10 minutes. An invalid referrerAddress returns a 500.

Query Parameters

Name
Type
Description

referrerAddress

String

Algorand address of the referrer.

chain

String

Only mainnet (the default) is supported.

Health check

GET https://hayrouter.txnlab.dev/api/health

Returns 200 with the plain-text body OK.

Last updated