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

# Connection webhooks quickstart

> Register a connection webhook, test it, and receive your first connection event.

# Connection webhooks quickstart

This quickstart walks you through registering a webhook, test-firing it, and receiving a real event about an **app connection** (an end user's authenticated link to a third-party app). By the end, you will have a registered endpoint and a stored signing secret ready for [signature verification](/white-label/connection-webhooks/verify-signatures). For brevity, the steps below call an app connection a **connection**.

## Prerequisites

* A White Label (partner) account that manages at least one connection.
* An OAuth 2.0 access token with the `connection:webhook:write` and `connection:webhook:read` scopes. To obtain one, go to [Token exchange: Connection Webhooks API](/white-label/implementation/token-exchange#c-connection-webhooks-api-embedded).
* An HTTPS endpoint that can accept POST requests. The `callback_url` must use HTTPS.

<Note>
  While this API is in early access, partners need a separate, dedicated client
  ID and secret to obtain an access token for the connection webhooks endpoints.
  Reach out to [whitelabel@zapier.com](mailto:whitelabel@zapier.com) to set it
  up. For the exchange, go to [Token exchange: Connection Webhooks
  API](/white-label/implementation/token-exchange#c-connection-webhooks-api-embedded).
</Note>

Set your token and endpoint as environment variables so the examples below can reuse them.

```bash theme={null}
export ACCESS_TOKEN="YOUR_ACCESS_TOKEN"
export CALLBACK_URL="https://your-app.com/webhooks/zapier"
```

## Step 1: Register a webhook

Create a webhook subscribed to the `connection.expiry_scheduled` event. The response includes the signing `secret`. This is the only time the secret is returned, so store it securely.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.zapier.com/connections/v1/webhooks \
    -H "Authorization: Bearer $ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "event_type": "connection.expiry_scheduled",
      "callback_url": "https://your-app.com/webhooks/zapier"
    }'
  ```

  ```typescript TypeScript theme={null}
  const res = await fetch("https://api.zapier.com/connections/v1/webhooks", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.ACCESS_TOKEN}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      event_type: "connection.expiry_scheduled",
      callback_url: process.env.CALLBACK_URL,
    }),
  });

  const webhook = await res.json();
  // Store webhook.secret securely: it is returned only once.
  console.log(webhook.id, webhook.secret);
  ```

  ```python Python theme={null}
  import os
  import requests

  res = requests.post(
      "https://api.zapier.com/connections/v1/webhooks",
      headers={"Authorization": f"Bearer {os.environ['ACCESS_TOKEN']}"},
      json={
          "event_type": "connection.expiry_scheduled",
          "callback_url": os.environ["CALLBACK_URL"],
      },
  )
  webhook = res.json()
  # Store webhook["secret"] securely: it is returned only once.
  print(webhook["id"], webhook["secret"])
  ```
</CodeGroup>

The response returns `201 Created`:

```json theme={null}
{
  "id": "8e9b4d0a-3f1a-4b8c-9e5d-2f7c1a6e8d3b",
  "event_type": "connection.expiry_scheduled",
  "callback_url": "https://your-app.com/webhooks/zapier",
  "is_active": true,
  "created_at": "2026-07-23T18:00:00Z",
  "updated_at": "2026-07-23T18:00:00Z",
  "secret": "whsec_C2FVsBQIhrscChlQIMV+b5sSYspob7oD"
}
```

<Warning>
  The `secret` is returned only in this create response. Store it before you
  move on. If you lose it, delete the webhook and create a new one to get a new
  secret.
</Warning>

## Step 2: Confirm the webhook is registered

List your webhooks to confirm the new one is present and active. The `secret` is never returned on list or retrieve, only on create.

```bash theme={null}
curl https://api.zapier.com/connections/v1/webhooks \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

```json theme={null}
{
  "results": [
    {
      "id": "8e9b4d0a-3f1a-4b8c-9e5d-2f7c1a6e8d3b",
      "event_type": "connection.expiry_scheduled",
      "callback_url": "https://your-app.com/webhooks/zapier",
      "is_active": true,
      "created_at": "2026-07-23T18:00:00Z",
      "updated_at": "2026-07-23T18:00:00Z"
    }
  ],
  "meta": { "count": 1 },
  "links": {}
}
```

## Step 3: Test the webhook

Before you wait for a real event, test-fire the webhook to confirm your endpoint receives and verifies deliveries. Send a POST to the webhook's `test` endpoint:

```bash theme={null}
curl -X POST https://api.zapier.com/connections/v1/webhooks/$WEBHOOK_ID/test \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

The API responds `202 Accepted` and enqueues the delivery. Zapier then delivers a sample `connection.expiry_scheduled` event to your `callback_url`. A test delivery is identical to a real one, except it carries a `webhook-test: true` header so you can tell them apart. Use it to skip side effects during testing (for example, do not email a real user), while still exercising your [signature verification](/white-label/connection-webhooks/verify-signatures).

```http theme={null}
POST /webhooks/zapier HTTP/1.1
Host: your-app.com
webhook-id: msg_2abc...
webhook-timestamp: 1753293600
webhook-signature: v1,g0hM9SsE...
webhook-test: true
Content-Type: application/json
```

## Step 4: Receive an event

When one of the connections you manage is scheduled to expire, Zapier POSTs a signed `connection.expiry_scheduled` event to your `callback_url`:

```json theme={null}
{
  "type": "connection.expiry_scheduled",
  "expires_at": "2026-08-01T00:00:00Z",
  "data": {
    "connection_id": "8e9b4d0a-3f1a-4b8c-9e5d-2f7c1a6e8d3b",
    "account_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
    "app": "SlackCLIAPI@1.0.0",
    "title": "My Slack workspace"
  }
}
```

Return a `2xx` status quickly to acknowledge receipt. A `429` or any `5xx` response triggers a retry, so the same event can arrive more than once. For retry and `Retry-After` behavior, go to [Error handling](/white-label/connection-webhooks/error-handling). Before you trust the payload, verify the signature. For the steps, go to [Verify signatures](/white-label/connection-webhooks/verify-signatures).

## Step 5: Prompt the user to reconnect

Use the `connection_id` from the payload to tell the user to start a reconnection flow, so they reauthorize before the connection expires. For the reconnection parameters, go to [Connection flow](/white-label/implementation/connection-flow#reconnecting).

## Manage a webhook

Pause a webhook without deleting it by setting `is_active` to `false`, or update its `callback_url`:

```bash theme={null}
curl -X PATCH https://api.zapier.com/connections/v1/webhooks/$WEBHOOK_ID \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "is_active": false }'
```

Delete a webhook when you no longer need it:

```bash theme={null}
curl -X DELETE https://api.zapier.com/connections/v1/webhooks/$WEBHOOK_ID \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

## Next steps

1. [Verify signatures](/white-label/connection-webhooks/verify-signatures): confirm each delivery is authentic.
2. [Event payload reference](/white-label/connection-webhooks/payload-reference): the fields in a delivered event.
3. [Error handling](/white-label/connection-webhooks/error-handling): API error codes and delivery retry behavior.
4. [Connections API reference](/api-reference/connections/connection-webhooks/create-a-connection-webhook): the full CRUD endpoints.
