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

# Setup Guide

> Wire up AGG for your app — client setup, provider stack, auth, and WebSocket

# Setup Guide

Choose your integration path and follow the setup for your layer. See the
[Packages overview](/packages/overview) for installation, package descriptions, and peer dependencies.

<Info>
  Need sign-in flows? Start with [Authentication](/recipes/authentication). For wire-level streaming details,
  see [WebSocket Protocol](/api/websocket). For end-to-end implementations, see
  [Real-Time Orderbook](/recipes/websocket-orderbook) and
  [Real-Time Charts](/recipes/websocket-charts). For theming and partner branding, see
  [Customize UI](/components/customization).
</Info>

<Tabs>
  <Tab title="SDK (vanilla JS/TS)">
    No framework dependency. Works in browsers, Node.js, and React Native.

    ```typescript theme={null}
    import { createAggClient, CandleBuilder } from "@agg-build/sdk";

    const client = createAggClient({
      baseUrl: "https://api.agg.market",
      appId: "your-app-id",
      wsUrl: "wss://ws.agg.market/ws",
    });

    // REST: fetch events, orderbooks, charts
    const events = await client.getVenueEvents({ limit: 10 });
    const books = await client.getOrderbooks({
      venueMarketIds: ["your-market-id"],
      depth: 20,
    });
    const bars = await client.getChartBars({
      venueMarketOutcomeId: "...",
      resolution: "5m",
      to: Date.now(),
      countBack: 200,
    });
    const route = await client.getSmartRoute({ venueMarketId: "...", maxSpend: 50, side: "yes" });

    const book = books.data[0];
    if (book?.status !== "ok") {
      throw new Error(book?.error?.message ?? "No live orderbook available");
    }

    // WebSocket: real-time orderbook + trades
    const builder = new CandleBuilder();
    const ws = client.createWebSocket({
      onSnapshot: (id, book) => {
        if (book.midpoint != null) builder.addMidpoint(book.midpoint, book.timestamp);
      },
      onDelta: (id, book) => {
        if (book.midpoint != null) builder.addMidpoint(book.midpoint, book.timestamp);
      },
      onTrade: (trade) => {
        builder.addTrade(trade.price, trade.size, trade.timestamp);
      },
    });

    ws.subscribe("your-market-id");

    // Read candles for any chart library
    builder.onChange(() => {
      const candles = builder.getClosed("5m");
      const forming = builder.getForming("5m");
      yourChart.update(candles, forming);
    });
    ```
  </Tab>

  <Tab title="React (hooks)">
    Bring your own UI. Hooks handle WS subscriptions, caching, and cleanup.

    ```tsx theme={null}
    import { AggProvider, QueryClient, QueryClientProvider } from "@agg-build/hooks";
    import { createAggClient } from "@agg-build/sdk";

    const client = createAggClient({
      baseUrl: "https://api.agg.market",
      appId: "your-app-id",
      wsUrl: "wss://ws.agg.market/ws",
    });

    const queryClient = new QueryClient();

    function App() {
      return (
        <QueryClientProvider client={queryClient}>
          <AggProvider client={client}>
            <MyApp />
          </AggProvider>
        </QueryClientProvider>
      );
    }
    ```

    Then use hooks in any component:

    ```tsx theme={null}
    import { useLiveMarket, useMarketChart, useSmartRoute } from "@agg-build/hooks";

    function MarketView({ venueMarketId, venueMarketOutcomeId }) {
      const { orderbook } = useLiveMarket(venueMarketId);
      const { data: chart } = useMarketChart({
        marketId: venueMarketOutcomeId,
        interval: "5m",
        startTs: Date.now() - 86_400_000,
        endTs: Date.now(),
      });
      const { data: route } = useSmartRoute({
        venueMarketId,
        maxSpend: 50,
        side: "yes",
      });

      const primaryVenue = chart?.primaryVenue;
      const candles = primaryVenue ? chart.venues[primaryVenue]?.candles ?? [] : [];

      return <YourChart data={candles} orderbook={orderbook} route={route} />;
    }
    ```

    | Hook                                                                | What it does                                                                         |
    | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
    | `useLiveMarket(id)`                                                 | Live orderbook via WS                                                                |
    | `useMarketChart({ marketId, interval, startTs, endTs, countBack })` | Outcome-id chart history, exposed under `data.primaryVenue`                          |
    | `useSmartRoute({ venueMarketId, maxSpend, side })`                  | User-scoped route quote across available liquidity                                   |
    | `useLiveTrades(id)`                                                 | Real-time trade feed                                                                 |
    | `useMarketOrderbook({ marketId })`                                  | Aggregated orderbook + venue breakdown                                               |
    | `useMarketArb(marketId)`                                            | Live cross-venue arbitrage return for one market                                     |
    | `useArbFeed()`                                                      | Live arbitrage returns for many markets (`byMarket` map + event-level `byEvent` max) |
  </Tab>

  <Tab title="React (UI components)">
    Pre-built, themed components. Drop in and go.

    ```tsx theme={null}
    import "@agg-build/ui/styles.css";
    import { AggProvider, QueryClient, QueryClientProvider } from "@agg-build/hooks";
    import { createAggClient } from "@agg-build/sdk";

    const client = createAggClient({
      baseUrl: "https://api.agg.market",
      appId: "your-app-id",
      wsUrl: "wss://ws.agg.market/ws",
    });

    const queryClient = new QueryClient();

    function App() {
      return (
        <QueryClientProvider client={queryClient}>
          <AggProvider
            client={client}
            config={{
              general: {
                locale: "en-US",
                theme: "light",
              },
              features: {
                enableAnimations: true,
                enableLiveUpdates: true,
              },
            }}
          >
            <MyApp />
          </AggProvider>
        </QueryClientProvider>
      );
    }
    ```

    Then use components:

    ```tsx theme={null}
    import { EventMarketPage } from "@agg-build/ui/pages";
    import { MarketDetails } from "@agg-build/ui/events";
    import { LineChart } from "@agg-build/ui/primitives";

    // Full event page — hero chart, market cards, orderbooks, all live
    <EventMarketPage eventId="..." />

    // Or individual components
    <MarketDetails event={event} marketId={marketId} defaultTab="graph" />
    <LineChart series={series} chartType="candlestick" height={320} live />
    ```

    Browse the live [Event Market Page reference](/components/pages/event-market-page) and
    [Market Details reference](/components/events/market-details). Use
    [Customize UI](/components/customization) for fonts, colors, copy, formatting, and slot
    overrides.
  </Tab>

  <Tab title="React (with auth)">
    Full stack with connect/sign-in UI. See [Authentication](/recipes/authentication) for detailed flow examples.

    ```tsx theme={null}
    import "@agg-build/ui/styles.css";
    import { AggProvider, QueryClient, QueryClientProvider } from "@agg-build/hooks";
    import { createAggClient } from "@agg-build/sdk";
    import { AggAuthProvider, ConnectButton, createGoogleAuthMethod } from "@agg-build/auth";
    import { useSiweAuthMethod } from "@agg-build/auth/siwe";
    import { WagmiProvider } from "wagmi";
    import { wagmiConfig } from "./wagmi-config";

    const client = createAggClient({
      baseUrl: "https://api.agg.market",
      appId: "your-app-id",
      wsUrl: "wss://ws.agg.market/ws",
    });

    const queryClient = new QueryClient();

    function AuthButton() {
      const siwe = useSiweAuthMethod({ statement: "Sign in" });
      return (
        <AggAuthProvider methods={[siwe, createGoogleAuthMethod()]}>
          <ConnectButton />
        </AggAuthProvider>
      );
    }

    function App() {
      return (
        <WagmiProvider config={wagmiConfig}>
          <QueryClientProvider client={queryClient}>
            <AggProvider client={client}>
              <AuthButton />
            </AggProvider>
          </QueryClientProvider>
        </WagmiProvider>
      );
    }
    ```

    Browse the live [Connect Button reference](/components/auth/connect-button).
  </Tab>
</Tabs>

## WebSocket endpoint

If you create raw sockets yourself, connect to:

```
wss://ws.agg.market/ws?appId=YOUR_APP_ID
```

The SDK and hooks manage connection, reconnection, resnapshot requests, and orderbook integrity checks automatically.

## Testing mode limits

All new partner apps start in **testing mode** — a sandboxed state that lets you build and
verify your integration without committing to the full live-mode agreement. Two hard caps apply
while an app is in testing mode:

| Limit  | Cap | Applies to                              |
| ------ | --- | --------------------------------------- |
| Users  | 20  | Unique users who sign in to your app    |
| Trades | 100 | Orders placed (excluding failed orders) |

<Note>
  Existing users can always sign in — the user cap only blocks new account creation once the
  limit is reached. No data is lost when the cap is hit.
</Note>

### How the limits work

When a new user tries to sign in and the app has already registered 20 users, the sign-in
endpoint (`POST /auth/verify`) returns a `403` with a plain-language message explaining the
situation. Likewise, when a new trade is submitted after 100 trades have been placed, the
execution endpoint returns a `403`. Both error responses use the `message` field of the standard
`{ message: string }` error body — you can surface this text directly in your UI without any
special-casing.

```json theme={null}
// POST /auth/verify — over the user cap
{
  "statusCode": 403,
  "message": "This app has reached its testing limit of 20 users. Sign the partner agreement to enable live mode and continue adding users."
}

// POST /execution/fill — over the trade cap
{
  "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."
}
```

For OAuth and magic-link sign-in flows, the same error is surfaced as a `message` query
parameter on the redirect URL (alongside an `error=testing_user_limit_reached` param your
frontend can key off).

### Lifting the limits — signing the partner agreement

Once you are ready to go live, sign the partner agreement from the admin dashboard
(**Apps → your app → Go Live**). Signing sets `partnerAgreementSigned = true` on your app and
immediately removes both caps — no restart or config change needed. The agreement is a one-time
action; it cannot be reversed from the dashboard.

After signing:

* New users can sign in without restriction.
* New trades can be placed without restriction.
* Existing testing-mode users and trades are preserved; the historical counts are not reset.

## Next steps

<CardGroup cols={2}>
  <Card title="Authentication" icon="key" href="/recipes/authentication">
    Add wallet, OAuth, or email sign-in on top of the base client setup.
  </Card>

  <Card title="WebSocket Protocol" icon="brackets-curly" href="/api/websocket">
    Review the wire format, auth upgrade flow, heartbeat, and reconnection behavior.
  </Card>

  <Card title="Real-Time Orderbook" icon="code" href="/recipes/websocket-orderbook">
    SDK, hooks, and UI recipes for live orderbook rendering.
  </Card>

  <Card title="Real-Time Charts" icon="cube" href="/recipes/websocket-charts">
    Build live OHLCV charts from REST history and WebSocket updates.
  </Card>

  <Card title="Customize UI" icon="paintbrush" href="/components/customization">
    Brand AGG components with CSS variables, labels, formatting, and slots.
  </Card>
</CardGroup>
