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

# Zapier

> Trigger Zaps from FlowSign events and create or send packages from a Zap.

You can automate FlowSign with Zapier using Zapier's own webhook and HTTP steps: trigger a Zap when a package completes, or create and send a package from another system through a Zap.

## Receiving events

Create a webhook endpoint in FlowSign at **Settings > Webhooks** ([my.flowsign.app/settings/webhooks](https://my.flowsign.app/settings/webhooks)), or with the API (see [Webhooks](/webhooks/overview)).

1. In your Zap, add **Webhooks by Zapier** as the trigger app and choose the **Catch Hook** event.
2. Zapier gives you a catch URL. Paste it into the endpoint's **URL** field in FlowSign.
3. Tick the events to subscribe to (for example **Package Completed**) and save. FlowSign shows the endpoint's signing secret once; store it.

Every delivery is a `POST` with three headers and a JSON body:

| Header                   | Value                                                                   |
| ------------------------ | ----------------------------------------------------------------------- |
| `X-FlowSign-Event`       | The event name, for example `PACKAGE_COMPLETED`                         |
| `X-FlowSign-Delivery-Id` | A stable id for this delivery; retries reuse it                         |
| `X-FlowSign-Signature`   | Hex-encoded HMAC-SHA256 of the raw body, keyed with the endpoint secret |

```json theme={null}
{
  "event": "PACKAGE_COMPLETED",
  "timestamp": "2026-09-17T03:40:11.000Z",
  "data": {
    "packageId": "pkg_9f3c2e",
    "packageTitle": "Employment agreement: Ana Reid",
    "completedAt": "2026-09-17T03:40:10.884Z"
  }
}
```

`data` differs per event. See [Events](/webhooks/events) for every event's shape.

## Verifying the signature

<Warning>
  Skipping verification means your Zap acts on any unauthenticated `POST` to its catch URL, not just genuine FlowSign deliveries.
</Warning>

Compute a hex HMAC-SHA256 of the raw body with the endpoint secret and compare it to `X-FlowSign-Signature`. The **Catch Hook** event parses the body into fields before your Zap sees it, so re-serialising those fields to JSON isn't guaranteed to match the exact bytes FlowSign signed (whitespace and key order can differ). For verification that has to match byte-for-byte, use the **Catch Raw Hook** event instead, which passes the unparsed body and headers through.

Add a **Code by Zapier** step (JavaScript) after the trigger:

```javascript theme={null}
const crypto = require("crypto");

const expected = crypto
  .createHmac("sha256", inputData.secret)
  .update(inputData.rawBody)
  .digest("hex");

output = { valid: expected === inputData.signature };
```

Map `inputData.rawBody` and `inputData.signature` from the raw hook's body and `X-FlowSign-Signature` header, and `inputData.secret` from a Zapier storage value or environment-style input holding the endpoint secret. Follow with a **Filter by Zapier** step that only continues when `valid` is `true`.

## Calling the API

Use **Webhooks by Zapier**'s **Custom Request** action for any FlowSign API call.

Base URL: `https://my.flowsign.app`. Every request needs:

| Header           | Value                                                                                |
| ---------------- | ------------------------------------------------------------------------------------ |
| `Authorization`  | `Bearer fsk_your_key_here`                                                           |
| `X-Workspace-Id` | Optional; the workspace to act in. Omit to use the organisation's default workspace. |

Create the key at **Settings > API keys**; see [Authentication](/api-reference/authentication).

### List packages

Method **GET**, URL `https://my.flowsign.app/api/v1/packages?status=IN_PROGRESS`.

```json theme={null}
{
  "data": {
    "packages": [
      {
        "id": "pkg_9f3c2e",
        "title": "Employment agreement: Ana Reid",
        "status": "IN_PROGRESS",
        "description": null,
        "recipients": [
          { "name": "Ana Reid", "email": "ana@example.com", "action": "Sign", "actionType": "SIGNER", "signed": false }
        ],
        "documentsCount": 1,
        "signingProgress": { "completed": 0, "total": 1 },
        "createdAt": "2026-09-17T01:12:44.000Z",
        "updatedAt": "2026-09-17T01:12:50.000Z",
        "expiresAt": null,
        "completedAt": null
      }
    ],
    "totalCount": 1,
    "page": 1,
    "pageSize": 25
  }
}
```

### Create a package from a template

Method **POST**, URL `https://my.flowsign.app/api/v1/packages/from-template`, with a JSON body:

```json theme={null}
{
  "templateId": "tmpl_abc123",
  "recipients": [
    { "role": "Employee", "name": "Ana Reid", "email": "ana@example.com" },
    { "role": "Manager", "name": "Ben Toa", "email": "ben@example.com" }
  ],
  "fields": { "start_date": "1 October 2026" },
  "externalId": "order_4471",
  "status": "sent"
}
```

`role` must match one of the template's role names and `fields` keys must match its merge field keys; a mismatch returns `422` with the unknown or missing names in `details`. `status` is `"draft"` (default) or `"sent"`, which sends immediately. `externalId` is optional and makes the call idempotent: retrying with the same value returns the existing package instead of creating a duplicate.

```json theme={null}
{ "data": { "packageId": "pkg_9f3c2e", "externalId": "order_4471", "status": "IN_PROGRESS" } }
```

Creating requires the key's user to have the send permission; see [Errors](/api-reference/errors) for the full status code list.

## Plan and cost notes

**Webhooks by Zapier** is a premium Zapier app, so both the **Catch Hook** trigger and the **Custom Request** action need a paid Zapier plan.
