---
title: "Webhooks"
description: "Receive real-time event notifications at your own HTTPS endpoints"
---

> **For AI agents:** the complete documentation index is at [llms.txt](/llms.txt). Append `.md` to any page URL for its markdown version.

AGG sends webhook events to your endpoints when key actions happen in your app — user signups,
wallet provisioning, trades, and market resolutions. Webhooks are delivered with cryptographic
signatures so you can verify authenticity.

```typescript
import { parseWebhookEvent } from "@agg-build/sdk/server";

const event = parseWebhookEvent(rawBody, req.headers, process.env.AGG_WEBHOOK_SECRET!);
```

## How it works

<Steps>
  <Step title="Register an endpoint">
    Create a webhook endpoint from the **admin dashboard**. Select a URL and the event types you
    want to receive. The dashboard displays your signing secret (`whsec_...`) — store it in your
    secrets manager immediately.
  </Step>
  <Step title="Receive events">
    AGG sends `POST` requests to your URL with a JSON payload and `Webhook-Signature` header.
    Events are delivered at least once with automatic retries on failure.
  </Step>
  <Step title="Verify the signature">
    Use `parseWebhookEvent` from the SDK to verify the signature and parse the event in one call.
    This prevents spoofed requests.
  </Step>
  <Step title="Return 2xx">
    Respond with any `2xx` status code within 30 seconds. Non-2xx responses or timeouts trigger
    automatic retries with exponential backoff.
  </Step>
</Steps>

## Event types

| Event | Trigger | Payload |
|-------|---------|---------|
| `accounts.created` | New user created in your app | `userId`, `appId`, `email` |
| `accounts.linked` | User linked to an external ID | `userId`, `externalId` |
| `wallets.ready` | Server wallet provisioned | `userId`, `evmAddress`, `svmAddress` |
| `trades.placed` | Trade order submitted | `orderId`, `userId`, `side` |
| `trades.filled` | Trade order filled | `orderId`, `userId`, `status` |
| `markets.resolved` | Market resolved (summary per app) | `venueMarketId`, `outcome`, `affectedUsersCount` |

<Info>
  Webhook payloads are intentionally minimal — they carry IDs and timestamps. Query the API for
  full details (e.g., order breakdown, fill amounts, market data). `accounts.created.email` is
  populated when AGG has an email from magic-link or OAuth sign-in; otherwise it is `null`.
</Info>

## Delivery guarantees

- **At-least-once delivery** — events may be delivered more than once. Use the `id` field to deduplicate.
- **Retry schedule** — failed deliveries retry at 5s, 5m, 30m, 2h, 5h, 10h, 10h intervals.
- **Endpoint disabling** — endpoints that fail continuously for 5 days are automatically disabled.
- **Ordering** — events for the same app are delivered in order, but no cross-app ordering is guaranteed.

## Signature headers

Every webhook delivery includes these headers:

| Header | Description |
|--------|-------------|
| `Webhook-Id` | Unique message ID (for deduplication) |
| `Webhook-Timestamp` | Unix timestamp of the delivery attempt |
| `Webhook-Signature` | HMAC-SHA256 signature for verification |

## Next steps

<Columns cols={2}>
  <Card title="Verifying signatures" icon="shield-check" href="/recipes/webhooks/verifying-signatures">
    Verify webhook authenticity with the SDK or manually
  </Card>
  <Card title="Managing endpoints" icon="gear" href="/recipes/webhooks/managing-endpoints">
    Rotate secrets and replay deliveries
  </Card>
  <Card title="Event reference" icon="list" href="/recipes/webhooks/event-reference">
    Full payload schemas for every event type
  </Card>
</Columns>
