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:
GET /api/fetchQuotefinds the best route and returns a quote, including an opaquetxnPayload.POST /api/fetchExecuteSwapTxnsturns thattxnPayloadinto a transaction group for the swapper to sign and submit.
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
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
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 9999Invalid referrer addressinvalid assets(followed by the details, e.g. an unknown asset ID, orfromASAIDequal totoASAID)
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
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.
beneficiary
String
Algorand address that receives the swap output. The default is address.
Response fields
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 keyInvalid request bodySlippage must be a valid numberSlippage must be a number between 0 (inclusive) and 100 (exclusive)Invalid txnPayload dataFailed to parse decrypted payload(also returned for the empty payload of a quote withquote: 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
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
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
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