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

# Webhooks Overview

> Get notified in real time when affiliate, conversion, and payout events happen in your programs.

Webhooks let your backend react to AgentRef events without polling the API. When something interesting happens – an affiliate joins, a conversion is created, a payout completes – AgentRef sends an HTTP POST to your endpoint with a signed JSON payload.

## How it works

1. You register an HTTPS endpoint (your server URL)
2. You choose which event types to subscribe to
3. AgentRef sends a signed `POST` request to your URL every time a matching event fires
4. Your server responds with a `2xx` status to acknowledge receipt
5. If delivery fails, AgentRef retries automatically on an exponential backoff schedule

## Webhook envelope

Every webhook delivery shares the same outer envelope regardless of event type:

```json theme={null}
{
  "id": "msg_01jq2k3n4p5q6r7s8t9u0v1w2x",
  "type": "conversion.created",
  "schemaVersion": 2,
  "createdAt": "2026-03-15T14:22:00.000Z",
  "merchantId": "mch_01jq2abc",
  "programId": "prg_01jq2def",
  "environment": "production",
  "data": {
    "id": "conv_01jq2ghi",
    "affiliateId": "aff_01jq2jkl",
    "saleAmount": 9900,
    "currency": "usd",
    "status": "pending"
  }
}
```

| Field           | Description                                                          |
| --------------- | -------------------------------------------------------------------- |
| `id`            | Unique message ID. Use this for idempotency.                         |
| `type`          | Event type string, e.g. `conversion.created`                         |
| `schemaVersion` | Always `2` for current payloads                                      |
| `createdAt`     | ISO 8601 timestamp when the event was created                        |
| `merchantId`    | Your merchant ID                                                     |
| `programId`     | Program ID the event belongs to (omitted for merchant-scoped events) |
| `environment`   | `production`, `preview`, or `development`                            |
| `data`          | Event-specific payload (see [Events](/webhooks/events))              |

## Registering a webhook endpoint

<Tabs>
  <Tab title="Dashboard">
    1. Go to **Settings → Webhooks** in your dashboard
    2. Click **Add endpoint**
    3. Enter your endpoint URL and a descriptive name
    4. Select the event types you want to receive
    5. Optionally scope the endpoint to a specific program
    6. Click **Create** – your signing secret is shown once; copy it now
  </Tab>

  <Tab title="API">
    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST https://www.agentref.co/api/v1/webhooks \
        -H "Authorization: Bearer ak_live_..." \
        -H "Content-Type: application/json" \
        -d '{
          "name": "Production webhook",
          "url": "https://your-app.com/webhooks/agentref",
          "subscribedEvents": [
            "conversion.created",
            "payout.completed"
          ]
        }'
      ```

      ```typescript Node.js theme={null}
      import { AgentRef } from 'agentref';

      const client = new AgentRef({ apiKey: 'ak_live_...' });

      const { endpoint, signingSecret } = await client.webhooks.create({
        name: 'Production webhook',
        url: 'https://your-app.com/webhooks/agentref',
        subscribedEvents: ['conversion.created', 'payout.completed'],
      });

      // Store signingSecret securely – it is only returned once
      console.log(signingSecret);
      ```

      ```python Python theme={null}
      from agentref import AgentRef

      client = AgentRef(api_key='ak_live_...')

      result = client.webhooks.create(
          name='Production webhook',
          url='https://your-app.com/webhooks/agentref',
          subscribed_events=['conversion.created', 'payout.completed'],
      )

      # Store result.signing_secret securely – it is only returned once
      print(result.signing_secret)
      ```
    </CodeGroup>

    <Warning>
      The signing secret is only returned in the creation response. Store it in your secrets manager immediately. You cannot retrieve it again – only rotate it.
    </Warning>

    The response includes:

    ```json theme={null}
    {
      "data": {
        "endpoint": {
          "id": "wh_01jq2k3n...",
          "name": "Production webhook",
          "url": "https://your-app.com/webhooks/agentref",
          "status": "active",
          "programId": null,
          "schemaVersion": 2,
          "subscribedEvents": ["conversion.created", "payout.completed"],
          "secretLastFour": "a3f9",
          "createdAt": "2026-03-15T14:00:00.000Z",
          "updatedAt": "2026-03-15T14:00:00.000Z",
          "disabledAt": null
        },
        "signingSecret": "whsec_..."
      }
    }
    ```
  </Tab>
</Tabs>

## Event type filtering

You must subscribe to at least one event type per endpoint. You can subscribe to any subset of the [13 available events](/webhooks/events). Only events in your subscription list will be delivered to that endpoint.

<Info>
  Marketing Resources lifecycle changes do not currently emit webhook events.
</Info>

To update subscriptions on an existing endpoint:

```bash cURL theme={null}
curl -X PATCH https://www.agentref.co/api/v1/webhooks/wh_01jq2k3n \
  -H "Authorization: Bearer ak_live_..." \
  -H "Content-Type: application/json" \
  -d '{"subscribedEvents": ["conversion.created", "conversion.refunded", "payout.completed"]}'
```

## Program scoping

By default, a webhook endpoint receives events from **all** your programs. If you have multiple programs and want to isolate events, you can scope an endpoint to a specific program by passing `programId` when creating or updating the endpoint.

A scoped endpoint only receives events where `programId` matches. Unscoped endpoints receive events from every program.

```bash cURL theme={null}
curl -X POST https://www.agentref.co/api/v1/webhooks \
  -H "Authorization: Bearer ak_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Program A only",
    "url": "https://your-app.com/webhooks/program-a",
    "subscribedEvents": ["affiliate.joined"],
    "programId": "prg_01jq2def"
  }'
```

## Endpoint requirements

* **HTTPS only** – HTTP endpoints are rejected in production (localhost HTTP is allowed during development)
* **Respond within 30 seconds** – requests that time out are treated as failed deliveries
* **Return a 2xx status** – any non-2xx response triggers a retry, including 3xx redirects
* **No authentication required on your side** – verify the request using the [signature](/webhooks/signature-verification) instead

## Managing endpoints via API

| Method   | Path                                  | Scope required   | Description                        |
| -------- | ------------------------------------- | ---------------- | ---------------------------------- |
| `GET`    | `/api/v1/webhooks`                    | `webhooks:read`  | List all endpoints                 |
| `POST`   | `/api/v1/webhooks`                    | `webhooks:write` | Create an endpoint                 |
| `GET`    | `/api/v1/webhooks/{id}`               | `webhooks:read`  | Get a single endpoint              |
| `PATCH`  | `/api/v1/webhooks/{id}`               | `webhooks:write` | Update name, URL, or subscriptions |
| `DELETE` | `/api/v1/webhooks/{id}`               | `webhooks:write` | Disable an endpoint                |
| `POST`   | `/api/v1/webhooks/{id}/rotate-secret` | `webhooks:write` | Rotate the signing secret          |

<Note>
  Deleting an endpoint marks it as `disabled`. Disabled endpoints stop receiving deliveries and cannot be re-enabled via API – create a new endpoint instead.
</Note>

## Next steps

<CardGroup cols={2}>
  <Card title="Signature Verification" icon="shield-check" href="/webhooks/signature-verification">
    Verify incoming requests are genuinely from AgentRef
  </Card>

  <Card title="Events Reference" icon="list" href="/webhooks/events">
    Full payload examples for all 13 event types
  </Card>

  <Card title="Retry & Delivery" icon="arrows-rotate" href="/webhooks/retry-delivery">
    Understand retries, idempotency, and failure handling
  </Card>

  <Card title="Testing" icon="flask" href="/webhooks/testing">
    Test your endpoint locally before going to production
  </Card>
</CardGroup>
