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

# Webhook payloads & data

> Reference for ButterCMS webhook JSON payloads — covers the structure of content change data and event metadata for each payload type.

## Payload structure

All webhook payloads follow a consistent structure with two main sections:

```json theme={null}
{
  "data": {
    // Content-specific data about the changed item
  },
  "webhook": {
    "event": "event.type",
    "target": "https://your-webhook-endpoint.com"
  }
}
```

{/* SOURCE: file_path="api-documentation/openapi/components/schemas/webhooks/WebhookMeta.yaml" section="Properties" */}

### Webhook metadata

The `webhook` object is included in all webhook payloads and contains:

| Field    | Type         | Description                                                         |
| -------- | ------------ | ------------------------------------------------------------------- |
| `event`  | string       | The event type that triggered this webhook (e.g., `page.published`) |
| `target` | string (URI) | The webhook endpoint URL that received this notification            |

## Page webhook payloads

### Data fields

| Field          | Type                   | Description                                                          | Required |
| -------------- | ---------------------- | -------------------------------------------------------------------- | -------- |
| `id`           | string                 | Page slug                                                            | Yes      |
| `buttercms_id` | integer                | Page numeric ID                                                      | Yes      |
| `page_type`    | string                 | Page type key, or `*` for single pages                               | Yes      |
| `editor`       | string                 | Full name of the editor who made the change                          | Yes      |
| `name`         | string                 | Human-readable page name                                             | Yes      |
| `timestamp`    | string                 | Timestamp when webhook was generated                                 | Yes      |
| `locale`       | string/null            | Locale code for localized content, null for default locale           | No       |
| `status`       | string                 | Current page status: `draft`, `published`, `scheduled`, or `deleted` | Yes      |
| `updated`      | string (datetime)      | Last updated timestamp in ISO 8601 format                            | Yes      |
| `published`    | string/null (datetime) | Published timestamp, null if not published                           | No       |
| `scheduled`    | string/null (datetime) | Scheduled publication timestamp, null if not scheduled               | No       |

{/* SOURCE: file_path="api-documentation/openapi/webhooks/pages/page-published.yaml" section="Examples" */}

### Example: Page published

```json theme={null}
{
  "data": {
    "id": "product-launch",
    "buttercms_id": 5678,
    "page_type": "landing",
    "editor": "Marketing Team",
    "name": "Product Launch Landing Page",
    "timestamp": "2024-01-15T14:30:00",
    "locale": null,
    "status": "published",
    "updated": "2024-01-15T14:30:00.123456Z",
    "published": "2024-01-15T14:30:00.123456Z",
    "scheduled": null
  },
  "webhook": {
    "event": "page.published",
    "target": "https://yourapp.com/webhooks/buttercms"
  }
}
```

{/* SOURCE: file_path="api-documentation/openapi/webhooks/pages/page-delete.yaml" section="Examples" */}

### Example: Page deleted

```json theme={null}
{
  "data": {
    "id": "old-promotion",
    "buttercms_id": 3456,
    "page_type": "promo",
    "editor": "Content Manager",
    "name": "Old Promotion Page",
    "timestamp": "2024-01-15T20:15:00",
    "locale": null,
    "status": "deleted",
    "updated": "2024-01-15T20:15:00.111222Z",
    "published": "2024-01-10T10:00:00.000000Z",
    "scheduled": null
  },
  "webhook": {
    "event": "page.delete",
    "target": "https://yourapp.com/webhooks/buttercms"
  }
}
```

## Blog Post webhook payloads

### Data fields

| Field | Type    | Description          | Required |
| ----- | ------- | -------------------- | -------- |
| `id`  | string  | Blog post slug       | Yes      |
| `_id` | integer | Blog post numeric ID | Yes      |

### Example: Blog Post published

```json theme={null}
{
  "data": {
    "id": "announcing-new-features",
    "_id": 5678
  },
  "webhook": {
    "event": "post.published",
    "target": "https://yourapp.com/webhooks/buttercms"
  }
}
```

<Info>
  Blog post webhook payloads are intentionally lightweight, containing only the post slug and ID. To get the full post content, use the slug to fetch the complete post data from the ButterCMS API.
</Info>

### Fetching full post data

```javascript theme={null}
// After receiving the webhook
const { data, webhook } = webhookPayload;

if (webhook.event === 'post.published') {
  // Fetch the full post using the slug
  const butter = require('buttercms')('your-api-token');
  const response = await butter.post.retrieve(data.id);
  const fullPost = response.data.data;

  // Now you have access to all post fields:
  // fullPost.title, fullPost.body, fullPost.author, etc.
}
```

## Collection item webhook payloads

### Data fields

| Field       | Type        | Description                                                | Required |
| ----------- | ----------- | ---------------------------------------------------------- | -------- |
| `id`        | string      | Collection key identifier                                  | Yes      |
| `itemid`    | string      | API URI for retrieving the specific collection item        | Yes      |
| `label`     | string      | Display label for the collection item                      | Yes      |
| `editor`    | string      | Full name of the editor who made the change                | Yes      |
| `timestamp` | string      | Timestamp when webhook was generated                       | Yes      |
| `locale`    | string/null | Locale code for localized content, null for default locale | No       |
| `status`    | string      | Current status: `draft`, `published`, or `deleted`         | Yes      |

{/* SOURCE: file_path="api-documentation/openapi/webhooks/collections/collectionitem-published.yaml" section="Examples" */}

### Example: collection item published

```json theme={null}
{
  "data": {
    "id": "products",
    "itemid": "/v2/content/?keys=products[_id=5678]",
    "label": "Wireless Headphones Pro",
    "editor": "Product Manager",
    "timestamp": "2024-01-15T13:45:00",
    "locale": null,
    "status": "published"
  },
  "webhook": {
    "event": "collectionitem.published",
    "target": "https://yourapp.com/webhooks/buttercms"
  }
}
```

### Fetching full collection item data

The `itemid` field contains the API path to fetch the specific item:

```javascript theme={null}
// After receiving the webhook
const { data } = webhookPayload;

// The itemid contains the API query path
// e.g., "/v2/content/?keys=products[_id=5678]"

// Fetch the full item using the ButterCMS client
const butter = require('buttercms')('your-api-token');

// Extract the collection key and item ID
const collectionKey = data.id;  // "products"
const itemFilter = `[_id=${extractId(data.itemid)}]`;

const response = await butter.content.retrieve([collectionKey], {
  [collectionKey]: itemFilter
});
```

## Localized content payloads

For organizations with localization enabled, the `locale` field indicates which locale triggered the event:

### Default locale

When content in the default locale is changed, `locale` is `null`:

```json theme={null}
{
  "data": {
    "id": "homepage",
    "locale": null,
    ...
  }
}
```

### Specific locale

When content in a specific locale is changed, `locale` contains the locale code:

```json theme={null}
{
  "data": {
    "id": "homepage",
    "locale": "es",
    ...
  }
}
```

### Handling localized webhooks

```javascript theme={null}
app.post('/webhooks/buttercms', (req, res) => {
  const { data, webhook } = req.body;

  // Check if this is for a specific locale
  if (data.locale) {
    // Handle locale-specific cache invalidation
    invalidateCache(data.id, data.locale);
  } else {
    // Handle default locale
    invalidateCache(data.id, 'default');
  }

  res.status(200).json({ received: true });
});
```

## Parsing webhook payloads

### TypeScript interface

Define types for webhook payloads to ensure type safety:

```typescript theme={null}
interface WebhookMeta {
  event: string;
  target: string;
}

interface PageWebhookData {
  id: string;
  buttercms_id: number;
  page_type: string;
  editor: string;
  name: string;
  timestamp: string;
  locale: string | null;
  status: 'draft' | 'published' | 'scheduled' | 'deleted';
  updated: string;
  published: string | null;
  scheduled: string | null;
}

interface BlogPostWebhookData {
  id: string;
  _id: number;
}

interface CollectionItemWebhookData {
  id: string;
  itemid: string;
  label: string;
  editor: string;
  timestamp: string;
  locale: string | null;
  status: 'draft' | 'published' | 'deleted';
}

interface WebhookPayload<T> {
  data: T;
  webhook: WebhookMeta;
}
```

### Event type detection

```javascript theme={null}
function handleWebhook(payload) {
  const { event } = payload.webhook;

  // Parse event type
  const [contentType, action] = event.split('.');

  switch (contentType) {
    case 'page':
      handlePageEvent(action, payload.data);
      break;
    case 'post':
      handlePostEvent(action, payload.data);
      break;
    case 'collectionitem':
      handleCollectionEvent(action, payload.data);
      break;
    case 'media':
      handleMediaEvent(action, payload.data);
      break;
  }
}
```
