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

> ## Agent Instructions
> To integrate AGG, start with Quickstart: REST (https://docs.agg.market/quickstart/rest), then Order lifecycle & statuses (https://docs.agg.market/concepts/order-lifecycle).
> Track every trade until it reaches a terminal status. Before retrying a failed or timed-out call, read Errors, retries & idempotency (https://docs.agg.market/concepts/errors).
> The API reference is generated from https://docs.agg.market/openapi/openapi.json.

# Base URL, app IDs & API keys

> The API base URL, where your app ID and server API key come from, and which headers go on each call

## Base URL

| | URL |
| - | - |
| REST API | `https://api.agg.market` |
| WebSocket | `wss://ws.agg.market/ws` |
| Admin dashboard | `https://admin.agg.market` |

There is one environment. Orders route to the real venues, so a live fill spends real funds. Use
[paper trading](/recipes/paper-trading) to test without them.

## Your app ID

Every request carries your app ID in the `x-app-id` header. Find it in the admin dashboard: pick
your app, then open **API** under **Develop**. The same page lists your API keys.

## Allowed origins

Your app's allowed origins are the sites your browser code runs on. Manage them in the admin
dashboard under **Domains**. Enter bare origins such as `https://app.example.com`, with no path,
query, or wildcard.

They are used in three places:

* A request that sends an `Origin` header must match one of them, or it gets
  `403 Origin not allowed for this app`. Server requests usually send no `Origin` and skip this
  check.
* A SIWE or SIWS sign-in message names a domain. It must match an allowed origin, or sign-in
  fails with `401` and `code: "unregistered_domain"`.
* OAuth and magic-link `redirectUrl` values must be on an allowed origin.

An app with no allowed origins cannot complete wallet sign-in.

## Headers

Each route has an auth tier. The API Reference shows it on every endpoint.

| Tier | Headers | Used for |
| - | - | - |
| app | `x-app-id` | Market data, discovery, starting sign-in, and quotes without a user |
| user | `x-app-id` and `Authorization: Bearer <accessToken>` | Balances, deposits, quotes the user can fill, trading, withdrawals, profile |

Where the call comes from decides what else to send:

| Caller | Send |
| - | - |
| Browser or mobile app | `x-app-id`, plus the user's `Authorization` header on user-tier calls. Never an API key. |
| Your backend | `x-app-id` and `x-app-api-key`, plus the user's `Authorization` header on user-tier calls. |

Users sign in on the client, and your backend includes that user's access token on trading calls.
See [Authentication & sessions](/concepts/authentication).

## Server API keys

Send `x-app-api-key` from your backend. It is always accepted and never required unless you turn
on **Require API key**. A validated key gives your backend its own rate-limit budget and unlocks
server-only options such as per-trade `appFeeBips`, referral fields, and `skipQuote`.

<Warning>
  An API key is a secret. Never put it in browser bundles, source maps, public repositories, or
  logs.
</Warning>

### Create a key

In the admin dashboard, pick your app, open **API**, and create a key. Pick a scope:

| Scope | Can do |
| - | - |
| `read` | Read your app's endpoints. |
| `read_write` | Read, plus partner-admin writes on your app such as members and settings, excluding security settings. |

The key is shown once. Store it in your secret manager right away. AGG keeps only a hash and
cannot show it again.

Keys look like `agg_<appId>_<64 hex characters>`. A key only works with its own app's `x-app-id`.
A key that is missing, malformed, unknown, revoked, expired, or for another app is rejected with
`401` or `403`. Unknown and wrong-app keys return the same `"Invalid API key"` message.

### Send it

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.agg.market/app/config \
    -H "x-app-id: your-app-id" \
    -H "x-app-api-key: agg_your-app-id_<64 hex>"
  ```

  ```ts SDK theme={null}
  import { createAggClient } from "@agg-build/sdk";

  const client = createAggClient({
    baseUrl: "https://api.agg.market",
    appId: process.env.AGG_APP_ID!,
    apiKey: process.env.AGG_API_KEY!, // server-side only
  });
  ```
</CodeGroup>

### Require a key for every request

Turn on **Require API key** in the dashboard's **Settings** for a server-only app. Then every
request without a valid key returns `401` with
`"This app requires x-app-api-key for all requests."`. Browser calls stop working, because they
carry no key, so leave it off for any app with browser users. Only a signed-in dashboard admin can
change this setting. A `read_write` key cannot.

### Rotate a key

1. Create a new key.
2. Deploy your backend with it.
3. Check traffic moved to it (`lastUsedAt` in the dashboard).
4. Revoke the old key. Revoked and expired keys fail at once with `401`.

## Rate limits

A validated key gets its own per-key budget, by default 18,000 requests per minute, and skips
browser IP limits. AGG can change a key's budget on request. Route-specific caps still apply, see
[Market data API](/api/market-data). A limited request returns `429` with a `Retry-After` header in
seconds. See [Errors, retries & idempotency](/concepts/errors).

## Testing mode

New apps start in testing mode, with two caps:

| Limit | Cap | Counts |
| - | - | - |
| Users | 20 | Unique users who sign in to your app |
| Trades | 100 | Orders placed, not counting failed orders |

Existing users can always sign in. Past the user cap, `POST /auth/verify` returns `403` for new
users. Past the trade cap, trading calls return `403`. Both carry a readable `message`:

```json theme={null}
{
  "statusCode": 403,
  "message": "This app has reached its testing limit of 100 trades. Sign the partner agreement to enable live mode and continue placing trades."
}
```

OAuth and magic-link sign-in report the user cap on the redirect URL as a `message` query
parameter with `error=testing_user_limit_reached`.

To lift the caps, sign the partner agreement in the admin dashboard (**Go Live**). It takes effect
at once and cannot be undone from the dashboard. Existing users and trades are kept.

## Route families

The API Reference groups endpoints in the order a trade flows:

* **Authentication**: start sign-in, verify wallet signatures, exchange redirect codes, refresh
  tokens, sign out, bot protection.
* **Markets**: venue events, venue markets, outcome lookup, categories, search, recurring crypto
  markets.
* **Market Data**: orderbooks, outcome snapshots, midpoints, chart bars, live sports scores,
  crypto reference prices.
* **Trading**: quote, execute, submit self-custody signatures, direct and limit orders, cancel,
  execution status, redeem, venue geo policy.
* **Portfolio**: orders, positions, balances, activity, leaderboard.
* **Funding**: deposit addresses, withdrawals, balance refill policies, fiat on-ramp.
* **Users**: current user, profile, linked accounts, KYC, venue API keys.
* **Hosted Venue Accounts**: accounts AGG hosts for the user on a venue.
* **Webhooks**: create, update, test, and replay webhook endpoints.
* **Partner Admin**: server-side reads across your app's users, orders, and analytics.
* **Paper Trading**: simulated accounts and orders.
* **News** and **Correlated Markets**: market-aware articles and related markets.
