> ## Documentation Index
> Fetch the complete documentation index at: https://nexus.gerowallet.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# DEX Aggregator

> Best-execution swap routing across Cardano DEXes, with non-custodial co-signed submission

**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.

<Note>
  The **build** and **submit** endpoints require the **Transaction Builder** add-on. Without it they return [HTTP 402](/docs/addons/overview#how-access-is-enforced) with `"addon": "transactionBuilder"`. The read endpoints (`quote`, `reverse-quote`, `tokens`, `supported-dexes`, `status`) need only a market-data-eligible tier.
</Note>

Base URL: `https://nexus.gerowallet.io` · Auth: `X-Api-Key: nxs_…`

## Endpoints

| Method | Path                              | Description                                                 |
| ------ | --------------------------------- | ----------------------------------------------------------- |
| POST   | `/api/aggregator/quote`           | Best-execution quote for an exact input amount              |
| POST   | `/api/aggregator/reverse-quote`   | Exact-output quote — least input to obtain a desired output |
| POST   | `/api/aggregator/build-tx`        | Build the unsigned swap transaction (CBOR)                  |
| POST   | `/api/aggregator/submit`          | Co-sign and submit the signed swap transaction              |
| GET    | `/api/aggregator/status/{txHash}` | Order status                                                |
| GET    | `/api/aggregator/tokens`          | Tokens with at least one routable pool                      |
| GET    | `/api/aggregator/supported-dexes` | DEXes available for routing and building                    |

## 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`.

<Note>
  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`.
</Note>

## Fees

The aggregator fee is a separate output on the swap transaction, taken on the ADA side.

|                                                      | Rate      |
| ---------------------------------------------------- | --------- |
| Standard                                             | **0.10%** |
| GERO holders (≥ \$10 of GERO at the sending address) | **0.05%** |

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.

<Note>
  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.
</Note>

## 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": … }`:

| `errorCode`                   | HTTP | Meaning                                                                                |
| ----------------------------- | ---- | -------------------------------------------------------------------------------------- |
| `FEE_OUTPUT_MISSING`          | 400  | No output to the aggregator fee address                                                |
| `FEE_TOO_LOW`                 | 400  | Fee output below the minimum                                                           |
| `COSIGNER_PKH_MISSING`        | 400  | Aggregator key absent from `requiredSigners`                                           |
| `UNKNOWN_BUILD`               | 400  | Transaction body was not produced by `/build-tx`                                       |
| `DISCOUNT_NO_LONGER_ELIGIBLE` | 409  | GERO holdings dropped below the discount threshold since build — request a fresh quote |
| `REGISTRY_UNAVAILABLE`        | 503  | The build registry was unavailable — retry the build                                   |
| `COSIGNER_DISABLED`           | 503  | Co-signing not configured on the server                                                |
| `SUBMIT_REJECTED`             | 502  | The node/network rejected the transaction (reason included)                            |

## 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

```bash theme={null}
# 1. Quote an exact-in swap (50 ADA → MIN), with the GERO-holder discount check
curl -X POST "https://nexus.gerowallet.io/api/aggregator/quote" \
  -H "X-Api-Key: nxs_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "tokenIn": "lovelace",
    "tokenOut": "29d222ce763455e3d7a09a665ce554f00ac89d2e99a1a83d267170c6484d494e",
    "amountIn": "50000000",
    "slippageTolerance": 0.5,
    "senderAddress": "addr1q9..."
  }'
# → { "routes": [ { "dex": "MINSWAP_V2", "expectedOutput": "1234...", "appliedFeeRate": "0.0005", "discountApplied": true, ... } ], "bestRouteIndex": 0 }

# 2. Build the unsigned transaction (requires the Transaction Builder add-on)
curl -X POST "https://nexus.gerowallet.io/api/aggregator/build-tx" \
  -H "X-Api-Key: nxs_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "route": { ... }, "senderAddress": "addr1q9...", "utxos": [ ... ] }'
# → { "unsignedTxCbor": "84a4...", "txBodyHash": "ab12…", "aggregatorFeeLovelace": 1200000, "appliedFeeRate": "0.0005", "discountApplied": true }

# 3. Sign unsignedTxCbor client-side: CIP-30 signTx(cbor, true) → witness set

# 4. Co-sign + submit
curl -X POST "https://nexus.gerowallet.io/api/aggregator/submit" \
  -H "X-Api-Key: nxs_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "unsignedTxCbor": "84a4...", "userWitnessHex": "a100..." }'
# → { "txHash": "abc123...", "status": "SUBMITTED" }

# 5. Track
curl "https://nexus.gerowallet.io/api/aggregator/status/abc123..." \
  -H "X-Api-Key: nxs_your_api_key_here"
# → { "txHash": "abc123...", "status": "CONFIRMED" }
```

Full request/response schemas are in the [API Reference](/docs/api-reference).
