Skip to main content
DEX Aggregator add-on. Route swaps across the Cardano DEXes currently marked buildable by GET /api/aggregator/supported-dexes for best execution. You request a quote, Nexus returns the best route and an unsigned transaction CBOR, you sign it with your wallet, and Nexus co-signs and submits it. The aggregator is non-custodial: Nexus never holds your funds or keys, and you sign every transaction.
The build and submit endpoints require the Transaction Builder add-on. Without it they return HTTP 402 with "addon": "transactionBuilder". The read endpoints (quote, reverse-quote, tokens, supported-dexes, status) need only a market-data-eligible tier.
Base URL: https://nexus.gerowallet.io · Auth: X-Api-Key: nxs_…

Which key to use

There are two kinds of key on this surface and they are not interchangeable. A public partner key is for the <gero-swap> widget only: it is public by design, it works only from the browser origins registered on it, and it reaches only the swap endpoints the widget needs. Anything you call from your own server needs an ordinary nxs_ API key with the Transaction Builder add-on instead; the partner key will not work there, and the ordinary key will not pay you a partner fee. Everything below assumes the ordinary key.
The widget supports two embed topologies, both using the same partner key and the same origin rule. In mode="dapp" (browser-direct) the key sits in your page and the browser sets Origin for you. In mode="native" (server-proxied) your backend holds the key, and your proxy must forward the browser’s Origin header unchanged (Origin: https://your-registered-site) with that origin registered on the key. There is no separate server-side credential: the origin binding is what stops a leaked key being replayed from any site, so one rule covers both modes. Full details in the widget README.

Diagnosing a partner key

GET /api/aggregator/partner/self-check answers with everything wrong with the key you presented and the request you made, instead of refusing. It runs ahead of the gates that would refuse it, so it works when nothing else does:
An empty problems array means nothing is wrong. Each entry carries a code, a severity, a message about your own setup and the fix: Call it through the same path your integration uses. If you proxy Nexus through your own backend, call it through that proxy: that is what shows whether your proxy forwards Origin. The response is never cached, reports how many origins are registered but never which, and reports whether a payout address is set and payable but never the address, because in a browser-direct embed anyone can read the key out of your page source. From the Nexus dashboard the same diagnosis is at GET /api/keys/{keyId}/partner/self-check over a browser session, which additionally returns the full origins list and the payout address.

Your swaps as a feed

GET /api/partner/swaps lists every swap built through your keys, newest first, with its status, the pair, the input amount and which key built it. It is what a “someone just swapped” alert or a recent-swaps list on your own site reads. Call it with an ordinary nxs_ key from your server, or from the Nexus dashboard over your session. It does not answer to the public partner key, because a key that lives in a web page must not be able to enumerate your swaps. There is never a fee, share or revenue figure on it; your earnings are GET /api/partner/earnings.
A swap’s status is BUILT (the wallet was handed an unsigned transaction), SUBMITTED, CONFIRMED, FAILED or EXPIRED. swapId is the transaction hash and is null while the swap is only BUILT, because no transaction has been submitted yet. amountIn is an integer string in tokenIn’s base units (lovelace for ADA). ticker and name come from the token registry and are null for a token it does not know; unit is always present. Live alerts. Poll every 15 seconds (the response is cacheable for that long) with updatedSince set to the newest updatedAt you have already seen. You get back only the swaps that changed since then, in every status. Keep the latest row per swapId and react to the ones whose status became CONFIRMED, or SUBMITTED if you want to announce a little earlier. Recovering after downtime. Call with updatedSince set to the last updatedAt you stored before the outage and page through nextCursor until it is null. The filter is inclusive, so the boundary row comes back once more; it is the same upsert by swapId as above. A swap that changed status while you were down carries the later updatedAt and is returned, so nothing is lost. Browsing history. Omit updatedSince and page with cursor. Pages are newest first and nextCursor walks towards older swaps. If the swap engine cannot be reached the response is 503 with errorCode: AGGREGATOR_METRICS_UNAVAILABLE. Retry it; never treat it as an empty list.

A swap counter for your page

GET /api/partner/swaps/summary is the counts: swaps built, submitted and confirmed through the key that authenticates the call, over the last 24 hours, 7 days and 30 days, with the ADA volume that moved. It is counts and totals only, so it is the one /api/partner endpoint that also answers to the public partner key from a registered origin. A “swaps today” counter can therefore run directly in your page with the same key the widget uses, and no server of yours in between.
Called with an API key, public or ordinary, the figures are that key’s alone. Called from the Nexus dashboard over your session, they cover all of your keys. The 24-hour window is rolling; the 7-day and 30-day windows are whole UTC calendar days ending today, so 7d spans between six and seven days. Every count is bucketed by the time the swap was built, submitted means a transaction hash exists whatever happened afterwards, and volumeOrders below confirmed means the ADA volume covers only that fraction of the swaps, because the engine did not record an ADA notional on the rest. Poll it every 15 seconds at most: the response is cacheable for that long and the server answers from the same reading inside it. A 503 here means the engine could not be reached; show the last figure you had, never a zero. The same origin rule as the widget applies: from a browser the key works only from the origins registered on it, and a server-side proxy must forward the browser’s Origin header unchanged.

Recognising a payout on chain

Every revenue-share payout we send carries a CIP-20 message in the transaction’s metadata, under label 674:
The number is the payout’s id on GET /api/partner/earnings, whose payouts list carries each payout’s id, status, netLovelace, txHash, submittedAt and confirmedAt. Match on the message rather than on the sending address: the address can change, the tag does not. Any explorer that shows transaction metadata renders it, and GET /api/transactions/{txHash}/metadata returns it as ["674"].msg. Payouts sent before the tag existed have no message; match those on txHash.

Endpoints

The flow

  1. Quote — POST /api/aggregator/quote (exact-in) or /api/aggregator/reverse-quote (exact-out). You get the best route: expected output, price impact, the fee breakdown, and appliedFeeRate / discountApplied.
  2. Build — POST the chosen route to /api/aggregator/build-tx. You receive unsignedTxCbor and txBodyHash. The transaction already contains the DEX order, the aggregator fee output, and the aggregator’s key in requiredSigners.
  3. Sign — sign the CBOR client-side with CIP-30 signTx(unsignedTxCbor, true). Nexus never sees your keys. This produces your witness set.
  4. Submit — POST { unsignedTxCbor, userWitnessHex } to /api/aggregator/submit. Nexus validates the fee output, co-signs with the aggregator key, merges witnesses, and submits. You get a txHash.
  5. Track — poll /api/aggregator/status/{txHash}: PENDING | SUBMITTED | CONFIRMED | FAILED | EXPIRED.
Submission is co-signed: /build-tx puts the aggregator’s key in requiredSigners, so the transaction is only valid once Nexus adds its signature at /submit. This is what enforces the aggregator fee — a transaction Nexus did not build (or whose fee output was altered) is rejected with UNKNOWN_BUILD.

Fees

The aggregator fee is a separate output on the swap transaction, taken on the ADA side. Pass senderAddress on the quote request to see your effective rate (appliedFeeRate, discountApplied). The rate is pinned when the transaction is built and re-checked at submit with a small grace band, so price movement between build and submit cannot invalidate an honest swap.
Because the fee is a standalone ADA output it is subject to Cardano’s minimum-UTxO rule, so the effective minimum fee is ~1.2 ADA even though the percentage floor is 0.5 ADA. This only affects swaps whose proportional fee would otherwise fall below ~1.2 ADA (roughly, ADA notionals under ~1,200); above that the percentage dominates.

Exact-output quotes

/api/aggregator/reverse-quote returns the least input required to net a desired output. For token → ADA swaps, the response’s minimumOutput is the gross pool floor (amountOut + the DEX batcher fee), so it can be larger than expectedOutput — this is intentional: it guarantees you net the amount you asked for after the batcher takes its fee. The required input is reported in the route’s amountIn; maximumInput carries the slippage ceiling.

Submit error codes

/api/aggregator/submit returns structured errors as { "errorCode": …, "message": … }:

Supported DEXes

The routable set is returned live by GET /api/aggregator/supported-dexes (the txBuilding list), and that response is the authority: it changes as venues are verified. Swap building is currently routable on Minswap (V1 and V2), WingRiders (V1 and V2), Splash, and SaturnSwap. Other venues are indexed for market data and quoting but are not in the default build path. Always read supported-dexes at runtime rather than hardcoding a venue list.

Example

Full request/response schemas are in the API Reference.