> For the complete documentation index, see [llms.txt](https://support.pipefile.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://support.pipefile.com/api-reference/webhooks.md).

# Webhook events

Get a JSON POST to your URL when a request is sent, opened, uploaded to, reviewed, completed, exported or expires.

A webhook tells your system when something happens in Pipefile. You register a URL and an event, and Pipefile sends a `POST` with JSON to that URL each time the event happens. Webhooks are available on every plan. You create them through the API; there is no webhook screen in the dashboard. If you'd rather not write code, [Zapier](/api-reference/zapier.md) uses the same events.

## Events

| Event                        | Fires when                                                                                              |
| ---------------------------- | ------------------------------------------------------------------------------------------------------- |
| `file_request.created`       | A request is sent, from the dashboard, the API, a template, bulk send, a lead form or your profile page |
| `file_request.opened`        | Someone opens the request link. Fires on every open, not only the first                                 |
| `file_request.reminder_sent` | A reminder goes out, automatic or sent by hand                                                          |
| `file_request.file_uploaded` | A file finishes uploading. Fires once per file                                                          |
| `file_request.item_reviewed` | A checklist item is reviewed                                                                            |
| `file_request.responded`     | Every checklist item has a response                                                                     |
| `file_request.completed`     | The request is marked complete                                                                          |
| `file_request.exported`      | Files are exported to a connected cloud storage folder                                                  |
| `file_request.expired`       | The request expires before the recipient responds                                                       |
| `team_member.joined`         | Someone joins your team. Team admins only                                                               |
| `team_member.removed`        | Someone is removed from your team. Team admins only                                                     |

### Whose requests trigger your webhooks

Your webhooks fire for requests you own. They also fire for a teammate's request when any of these is true:

* your team uses a shared inbox
* you are a team admin
* the request is assigned to you

## Create a webhook

{% stepper %}
{% step %}

### Get an API key

Create one at [**Settings** › **API keys**](https://pipefile.com/dashboard/settings/api). See API overview.
{% endstep %}

{% step %}

### Register the URL

Send one call per event you want:

```bash
curl https://api.pipefile.com/v1/webhooks/ \
  -H "Authorization: Token YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"event": "file_request.completed", "target": "https://example.com/hooks/pipefile"}'
```

Pipefile replies `201` with the webhook:

```json
{
  "id": 3,
  "created": "2026-01-17T09:15:00Z",
  "updated": "2026-01-17T09:15:00Z",
  "event": "file_request.completed",
  "target": "https://example.com/hooks/pipefile",
  "user": 7
}
```

An event name not in the table above returns `400`. The target URL can be up to 255 characters.
{% endstep %}

{% step %}

### Check your webhooks

`GET /webhooks/` returns every webhook your account has registered.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
Revoking the API key you used does not remove its webhooks. They keep firing.
{% endhint %}

## What Pipefile sends

Every delivery is a `POST` with `Content-Type: application/json`. The body has two parts: `hook` names the webhook that fired, and `data` is the request as it is now.

```json
{
  "hook": {
    "id": 3,
    "event": "file_request.file_uploaded",
    "target": "https://example.com/hooks/pipefile"
  },
  "data": {
    "id": "b1f5e3f386f74da2b4493cf672cb58c0",
    "user": { "name": "John Doe", "email": "john@example.com" },
    "assigned_to": [],
    "status": "sent",
    "unread": true,
    "recipients": [
      {
        "id": "a2b3c4d5e6f74a8b9c0d1e2f3a4b5c6d",
        "name": "Jane Doe",
        "email": "jane@example.com",
        "phone": "",
        "email_bounced": false,
        "email_complained": false,
        "phone_unreachable": false,
        "client_link": "https://pipefile.com/request/b1f5e3f386f74da2b4493cf672cb58c0?contact=a2b3c4d5e6f74a8b9c0d1e2f3a4b5c6d"
      }
    ],
    "tags": ["urgent"],
    "subject": "Please upload your documents",
    "message": "We need the following documents for your application.",
    "contents": [
      {
        "id": 1,
        "type": "item",
        "name": "Identification",
        "instructions": "Please upload a valid government-issued ID.",
        "status": "pending_review",
        "required": true,
        "responded": true,
        "num_files": 2,
        "...": "..."
      }
    ],
    "unreviewed_files": 2,
    "file_pipe": { "id": "e5f6a7b8c9d04e1f8a9b0c1d2e3f4a5b", "num_files": 2, "...": "..." },
    "destination_link": null,
    "last_modified": "2026-01-17T10:30:00Z",
    "created_at": "2026-01-17T09:00:00Z"
  }
}
```

| Field in `data`    | What it holds                                                                     |
| ------------------ | --------------------------------------------------------------------------------- |
| `id`               | The request ID. Use it with `GET /file/request/{id}/detail/` for the full request |
| `status`           | `sent`, `responded`, `completed`, `archived` or `expired`                         |
| `recipients`       | Each recipient, with `client_link`, their personal link to the request            |
| `contents`         | The checklist: items, or sections holding items, each with its review `status`    |
| `unreviewed_files` | Uploaded files nobody has reviewed yet                                            |
| `destination_link` | The export folder link, when the request has one                                  |

Two events send something extra or different:

* `file_request.exported` adds `export_destination` to `data`, a link to where the files went.
* `team_member.joined` and `team_member.removed` send the team member in `data`: `id`, `team`, `name`, `email`, `is_admin`, `is_owner`, `is_active`, `totp_enabled`, `mfa_enabled` and `groups`.

The payload does not include the files themselves.

## Responding and retries

Reply with any `2xx` status as quickly as you can, and do slow work afterwards. Pipefile waits up to 5 seconds to connect and up to 30 seconds between bytes of your response.

Pipefile treats any status below `500` as delivered, including `4xx`. It retries a delivery up to 5 times, waiting 1, 2, 4, 8 and then 16 seconds, when:

* your server returns a `5xx` status
* the connection fails or times out

A target URL that is malformed, or that redirects in a loop, is not retried.

{% hint style="warning" %}
Deliveries are not signed. Treat the payload as a notification: use the request `id` to read the request back through the API before you act on it, and keep your target URL private.
{% endhint %}

## Related

* API overview
* [Zapier](/api-reference/zapier.md)
* [Cloud storage integrations and auto-export](https://app.gitbook.com/s/5FaOvSTk88hXbQhqEN0A/reviewing-and-exporting/cloud-storage-and-auto-export)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

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

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://support.pipefile.com/api-reference/webhooks.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
