# 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](https://help.distro.so/workflows/broken-reference)).
* `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>
