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

# Webhook Event Reference

> Full payload schemas for every webhook event type

All webhook events share the same envelope format:

```json theme={null}
{
  "id": "evt_accounts.created:usr_abc123",
  "type": "accounts.created",
  "createdAt": "2026-04-09T18:15:03.000Z",
  "data": { ... }
}
```

| Field       | Type   | Description                             |
| ----------- | ------ | --------------------------------------- |
| `id`        | string | Unique event ID (use for deduplication) |
| `type`      | string | Event type (dot notation)               |
| `createdAt` | string | ISO 8601 timestamp                      |
| `data`      | object | Event-specific payload                  |

***

## accounts.created

Fired when a new user is created in your app (first authentication).

```json theme={null}
{
  "id": "evt_accounts.created:usr_abc123",
  "type": "accounts.created",
  "createdAt": "2026-04-09T18:15:03.000Z",
  "data": {
    "userId": "usr_abc123",
    "appId": "app_xyz",
    "createdAt": "2026-04-09T18:15:03.000Z",
    "email": "user@example.com"
  }
}
```

| Field       | Type           | Description                                                                          |
| ----------- | -------------- | ------------------------------------------------------------------------------------ |
| `userId`    | string         | The new user's ID                                                                    |
| `appId`     | string         | Your app's ID                                                                        |
| `createdAt` | string         | When the user was created                                                            |
| `email`     | string \| null | The user's email address when AGG has one from magic link or OAuth, otherwise `null` |

***

## accounts.linked

Fired when a user is linked to a partner external ID via the identity assertion flow.

```json theme={null}
{
  "id": "evt_accounts.linked:usr_abc123:partner_42",
  "type": "accounts.linked",
  "createdAt": "2026-04-09T18:15:03.000Z",
  "data": {
    "userId": "usr_abc123",
    "externalId": "partner_42",
    "linkedAt": "2026-04-09T18:15:03.000Z"
  }
}
```

| Field        | Type   | Description               |
| ------------ | ------ | ------------------------- |
| `userId`     | string | The user's AGG ID         |
| `externalId` | string | Your internal user ID     |
| `linkedAt`   | string | When the link was created |

***

## wallets.ready

Fired when a server-managed wallet is provisioned for a user (both EVM and Solana addresses
are available).

```json theme={null}
{
  "id": "evt_wallets.ready:usr_abc123",
  "type": "wallets.ready",
  "createdAt": "2026-04-09T18:15:03.000Z",
  "data": {
    "userId": "usr_abc123",
    "evmAddress": "0x1234...abcd",
    "svmAddress": "ABC123...xyz",
    "createdAt": "2026-04-09T18:15:03.000Z"
  }
}
```

| Field        | Type   | Description                           |
| ------------ | ------ | ------------------------------------- |
| `userId`     | string | The user's ID                         |
| `evmAddress` | string | EVM (Ethereum/Polygon) wallet address |
| `svmAddress` | string | Solana wallet address                 |
| `createdAt`  | string | When the wallet was provisioned       |

***

## trades.placed

Fired when a user submits a trade order. The payload contains the order ID — query the API for
the full breakdown (venue splits, amounts, prices).

```json theme={null}
{
  "id": "evt_trades.placed:quote_abc123",
  "type": "trades.placed",
  "createdAt": "2026-04-09T18:15:03.000Z",
  "data": {
    "orderId": "quote_abc123",
    "userId": "usr_abc123",
    "side": "yes",
    "timestamp": "2026-04-09T18:15:03.000Z"
  }
}
```

| Field       | Type   | Description                                |
| ----------- | ------ | ------------------------------------------ |
| `orderId`   | string | The order/quote ID (query API for details) |
| `userId`    | string | The user who placed the trade              |
| `side`      | string | Outcome side: `"yes"` or `"no"`            |
| `timestamp` | string | When the order was placed                  |

***

## trades.filled

Fired when a trade order reaches a terminal fill state. One event per venue-level order fill.

```json theme={null}
{
  "id": "evt_trades.filled:ord_abc123",
  "type": "trades.filled",
  "createdAt": "2026-04-09T18:15:03.000Z",
  "data": {
    "orderId": "ord_abc123",
    "userId": "usr_abc123",
    "status": "filled",
    "timestamp": "2026-04-09T18:15:03.000Z"
  }
}
```

| Field       | Type   | Description                                          |
| ----------- | ------ | ---------------------------------------------------- |
| `orderId`   | string | The individual order ID (query API for fill details) |
| `userId`    | string | The user who placed the trade                        |
| `status`    | string | `"filled"` or `"partial_fill"`                       |
| `timestamp` | string | When the fill was recorded                           |

***

## markets.resolved

Fired once per app when a prediction market resolves. Contains a summary — use the pull endpoint
for the full list of affected users.

```json theme={null}
{
  "id": "evt_markets.resolved:vm_123:app_xyz",
  "type": "markets.resolved",
  "createdAt": "2026-04-09T18:15:03.000Z",
  "data": {
    "venueMarketId": "vm_123",
    "externalIdentifier": "KXBTC-26APR09",
    "status": "resolved",
    "outcomes": [
      { "label": "Yes", "winner": true },
      { "label": "No", "winner": false }
    ],
    "affectedUsersCount": 1842,
    "detailsPath": "/apps/app_xyz/market-resolutions/vm_123/users"
  }
}
```

| Field                | Type   | Description                            |
| -------------------- | ------ | -------------------------------------- |
| `venueMarketId`      | string | The resolved market ID                 |
| `externalIdentifier` | string | Venue-specific market identifier       |
| `status`             | string | `"resolved"` or `"closed"`             |
| `outcomes`           | array  | Resolution outcome for each option     |
| `affectedUsersCount` | number | Users in your app with open positions  |
| `detailsPath`        | string | API path to paginate affected user IDs |

### Querying affected users

Use the SDK to paginate through affected users. Pass `includeEmails: true` to get email addresses
where available.

```typescript theme={null}
import { AggAdminClient } from "@agg-build/sdk/server";

const admin = new AggAdminClient({
  baseUrl: "https://api.agg.market",
  apiKey: process.env.AGG_API_KEY!,
});

// Paginate through all affected users
let cursor: string | undefined;
do {
  const page = await admin.listMarketResolutionUsers(
    appId,
    event.data.venueMarketId,
    { limit: 100, cursor, includeEmails: true },
  );
  for (const user of page.data) {
    console.log(user.userId, user.email);
  }
  cursor = page.nextCursor ?? undefined;
} while (cursor);
```

See the [List users affected by market resolution](/api-reference/app-management/list-users-affected-by-market-resolution)
API reference for full details.

<Info>
  This endpoint returns the current set of users with non-zero positions, not an immutable
  snapshot at resolution time. If positions are modified after resolution, the results may differ
  from the `affectedUsersCount` in the webhook.
</Info>
