# Webhook payloads

Sample webhook payloads for different sources in Distro Workflows.

Distro sends JSON to your configured webhook URL.

Payload shape depends on the **source type** and **trigger**.

{% hint style="info" %}
Payloads are examples. Distro may add fields over time.
{% endhint %}

### Basics

All webhooks use the same envelope:

```json
{
  "event": "meeting_booked",
  "timestamp": "2024-01-15T10:30:00Z",
  "data": {}
}
```

* `event`: the trigger that fired the webhook (see [Triggers](broken://spaces/QA3GQNrIYVrPQ90NBwRa/pages/rwqm2na0Wd8HhUud39fu#triggers)).
* `timestamp`: ISO 8601 time when Distro sent the webhook.
* `data`: the event payload. Shape depends on source type.

Conventions:

* Keys use `snake_case`.
* `data.source_type` is one of: `router`, `click_router`, `booking_link`, `group_meeting_link`.
* `data.booking` can be `null` for submission-only triggers.

### Payload examples

{% tabs %}
{% tab title="Router" %}
Triggered by **Form Routers**.

```json
{
  "event": "meeting_booked",
  "timestamp": "2024-01-15T10:30:00Z",
  "data": {
    "source_type": "router",
    "source_id": 123,
    "source_title": "Demo Request Router",
    "submission": {
      "id": 789,
      "uuid": "sub-xyz789-abc123",
      "form_data": {
        "email": "jane@example.com",
        "company": "Acme Corp",
        "employees": "50-100",
        "message": "Interested in enterprise plan"
      },
      "time_zone": "America/New_York",
      "source_url": "https://example.com/contact",
      "created_at": "2024-01-15T10:25:00Z"
    },
    "booking": {
      "id": 456,
      "uuid": "book-abc123-def456",
      "title": "Discovery Call with Acme Corp",
      "start_time": "2024-01-20T14:00:00Z",
      "end_time": "2024-01-20T14:30:00Z",
      "status": "scheduled",
      "meeting_url": "https://meet.google.com/abc-defg-hij",
      "time_zone": "America/New_York",
      "notes": "Looking forward to discussing your needs."
    },
    "assignee": {
      "id": 1,
      "email": "alex@yourcompany.com",
      "first_name": "Alex",
      "last_name": "Smith"
    },
    "attendees": [
      {
        "name": "Jane Doe",
        "email": "jane@example.com"
      }
    ]
  }
}
```

#### Submission-only events

For `form_submitted`, `prospect_disqualified`, and `prospect_no_booking`, `booking` is `null`.

```json
{
  "event": "form_submitted",
  "timestamp": "2024-01-15T10:30:00Z",
  "data": {
    "source_type": "router",
    "source_id": 123,
    "source_title": "Contact Form Router",
    "submission": {
      "id": 789,
      "uuid": "sub-xyz789-abc123",
      "form_data": {
        "email": "jane@example.com",
        "company": "Acme Corp",
        "employees": "50-100"
      },
      "time_zone": "America/New_York",
      "source_url": "https://example.com/contact",
      "created_at": "2024-01-15T10:30:00Z"
    },
    "booking": null,
    "assignee": {
      "id": 1,
      "email": "alex@yourcompany.com",
      "first_name": "Alex",
      "last_name": "Smith"
    },
    "attendees": []
  }
}
```

{% endtab %}

{% tab title="Click Router" %}
Triggered by **Click Routers**.

```json
{
  "event": "meeting_booked",
  "timestamp": "2024-01-15T10:30:00Z",
  "data": {
    "source_type": "click_router",
    "source_id": 456,
    "source_title": "Sales Team Round Robin",
    "booking": {
      "id": 789,
      "uuid": "book-def456-ghi789",
      "title": "Sales Call",
      "start_time": "2024-01-22T15:00:00Z",
      "end_time": "2024-01-22T15:30:00Z",
      "status": "scheduled",
      "meeting_url": "https://zoom.us/j/123456789",
      "time_zone": "America/Los_Angeles",
      "notes": null
    },
    "assignee": {
      "id": 5,
      "email": "sarah@yourcompany.com",
      "first_name": "Sarah",
      "last_name": "Johnson"
    },
    "attendees": [
      {
        "name": "John Smith",
        "email": "john@prospect.com"
      }
    ]
  }
}
```

{% endtab %}

{% tab title="Booking Link" %}
Triggered by **Personal Booking Links**.

```json
{
  "event": "meeting_booked",
  "timestamp": "2024-01-15T10:30:00Z",
  "data": {
    "source_type": "booking_link",
    "source_id": 101,
    "source_slug": "alex-30min",
    "booking": {
      "id": 1001,
      "uuid": "book-jkl012-mno345",
      "title": "30-min Meeting with Alex",
      "start_time": "2024-01-25T09:00:00Z",
      "end_time": "2024-01-25T09:30:00Z",
      "status": "scheduled",
      "meeting_url": "https://meet.google.com/xyz-abcd-efg",
      "time_zone": "Europe/London",
      "notes": "Want to discuss partnership opportunities"
    },
    "assignee": {
      "id": 1,
      "email": "alex@yourcompany.com",
      "first_name": "Alex",
      "last_name": "Smith"
    },
    "attendees": [
      {
        "name": "Emily Chen",
        "email": "emily@partner.com"
      }
    ]
  }
}
```

{% endtab %}

{% tab title="Group Meeting Link" %}
Triggered by **Group Meeting Links**.

```json
{
  "event": "meeting_booked",
  "timestamp": "2024-01-15T10:30:00Z",
  "data": {
    "source_type": "group_meeting_link",
    "source_id": 202,
    "source_slug": "sales-engineering-demo",
    "booking": {
      "id": 2001,
      "uuid": "book-pqr678-stu901",
      "title": "Sales + Engineering Demo",
      "start_time": "2024-01-28T16:00:00Z",
      "end_time": "2024-01-28T17:00:00Z",
      "status": "scheduled",
      "meeting_url": "https://teams.microsoft.com/l/meetup-join/...",
      "time_zone": "America/Chicago",
      "notes": "Technical deep-dive requested"
    },
    "assignee": {
      "id": 3,
      "email": "mike@yourcompany.com",
      "first_name": "Mike",
      "last_name": "Wilson"
    },
    "attendees": [
      {
        "name": "David Brown",
        "email": "david@enterprise.com"
      }
    ]
  }
}
```

{% endtab %}
{% endtabs %}

### Operational notes

<details>

<summary>HTTP headers and signatures</summary>

Every webhook request includes:

* `Content-Type: application/json`
* `User-Agent: Distro-Webhooks/1.0`
* `X-Distro-Delivery-ID`: unique delivery ID for tracking
* `X-Distro-Timestamp`: Unix timestamp of request (seconds)
* `X-Distro-Signature`: `t={timestamp},v1={signature}` (only if a signing secret is configured)
* `X-Distro-Test: true` (only for test webhooks)

Use `X-Distro-Delivery-ID` as an idempotency key if you store deliveries.

#### Verifying signatures

* Signature header: `X-Distro-Signature: t={timestamp},v1={signature}`
* Signed content: `{timestamp}.{raw_request_body}`
* Algorithm: HMAC-SHA256 using your signing secret
* Compare the computed hex digest with `v1`

{% hint style="warning" %}
Use the **raw** request body bytes for verification.

Don’t parse and re-serialize JSON before hashing.
{% endhint %}

</details>

<details>

<summary>Event-specific notes</summary>

#### Cancelled meetings

When `event` is `meeting_cancelled`, `booking.status` is `cancelled`.

```json
{
  "event": "meeting_cancelled",
  "timestamp": "2024-01-18T11:00:00Z",
  "data": {
    "booking": {
      "status": "cancelled"
    }
  }
}
```

#### No-show meetings

When `event` is `meeting_no_show`, `booking.status` is `no_show`.

```json
{
  "event": "meeting_no_show",
  "timestamp": "2024-01-18T11:00:00Z",
  "data": {
    "booking": {
      "status": "no_show"
    }
  }
}
```

</details>

<details>

<summary>Payload limits</summary>

* Maximum payload size: 1 MB
* Maximum `form_data` size: 100 KB

If limits are exceeded, Distro truncates data and includes a truncation marker:

```json
{
  "form_data": {
    "_truncated": true,
    "_original_size": 150000,
    "_message": "Form data exceeded 100KB and was truncated"
  }
}
```

</details>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://help.distro.so/workflows/webhook-payloads.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
