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

> ## Agent Instructions
> Flowsign is one word with a lowercase s.
> The REST API base URL is https://my.flowsign.app and every endpoint lives under /api/v1.
> When answering API questions, cite the HTTP method and endpoint path.
> API access needs the Enterprise plan and an API key with the API access permission.

# n8n

> Trigger n8n workflows from Flowsign events and create or send packages from a workflow.

You can automate Flowsign with n8n using its own **Webhook** and **HTTP Request** nodes: trigger a workflow when a package completes, or create and send a package from another system through a workflow.

## 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. Add a **Webhook** node, set it to accept `POST`, and activate the workflow so it gets a production URL.
2. Paste that URL into the endpoint's **Endpoint 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.

The endpoint receives events for the packages in the workspace it was created in.

Every delivery is a `POST` with four 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-timestamp`   | When this attempt was signed, in Unix seconds; every attempt gets a fresh one                                                                                                                    |
| `x-flowsign-signature`   | `v1=` followed by the hex HMAC-SHA256 of the timestamp, a `.`, and the raw body, keyed with the endpoint secret. During a secret rotation it carries one comma-separated `v1=` entry per 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",
    "metadata": { "employee_id": "E-1042" }
  }
}
```

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

## Verifying the signature

<Warning>
  Skipping verification means your workflow acts on any unauthenticated `POST` to its webhook URL, not just genuine Flowsign deliveries.
</Warning>

Build the signed content from the `x-flowsign-timestamp` header, a `.`, and the raw body. Compute its hex HMAC-SHA256 with the endpoint secret and accept the delivery when it matches any `v1=` entry in `x-flowsign-signature` and the timestamp is within 5 minutes of your clock (see [Webhooks](/webhooks/overview)). n8n parses the body into JSON by default, and re-serialising it back to a string isn't guaranteed to match the exact bytes Flowsign signed. In the **Webhook** node's options, turn on **Raw Body** so the unparsed body is available at `$json.rawBody` on the production URL.

Add a **Crypto** node next, with **Action** set to **Hmac**, **Type** set to **SHA256**, **Value** set to `{{ $json.headers["x-flowsign-timestamp"] }}.{{ $json.rawBody }}`, **Encoding** set to **hex**, and the secret in its **Crypto** credential. Follow it with an **IF** node checking that the Webhook node's `x-flowsign-signature` header contains `v1=` followed by the Crypto node's output, and stop the workflow on the false branch. The IF node does not check the timestamp; use the Code node below when you want that too.

To do the same in a **Code** node instead:

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

const timestamp = $json.headers["x-flowsign-timestamp"];

const expected = crypto
  .createHmac("sha256", $env.FLOWSIGN_WEBHOOK_SECRET)
  .update(`${timestamp}.${$json.rawBody}`)
  .digest("hex");

const signatures = ($json.headers["x-flowsign-signature"] || "")
  .split(",")
  .map((entry) => entry.trim())
  .filter((entry) => entry.startsWith("v1="))
  .map((entry) => entry.slice(3));

const fresh = Math.abs(Date.now() / 1000 - Number(timestamp)) <= 300;

return [{ json: { valid: fresh && signatures.includes(expected) } }];
```

## Calling the API

Use the **HTTP Request** node 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. A key always acts in the workspace it was issued for, and this header may only name that workspace. |

Create the key at **Settings > API keys** in the workspace you want to act in; see [Authentication](/api-reference/authentication). Store it in an n8n credential (Header Auth, with `Authorization` as the header name and `Bearer fsk_your_key_here` as the value) rather than pasting it into the node.

### 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": [
          { "id": "cmg4v8q2k0002s7xh6k4m1p9c", "name": "Ana Reid", "email": "ana@example.com", "action": "Sign", "actionType": "SIGNER", "delivery": "EMAIL", "roleName": "Employee", "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,
        "templateId": "tmpl_abc123",
        "metadata": { "employee_id": "E-1042" }
      }
    ],
    "totalCount": 1,
    "page": 1,
    "pageSize": 25
  }
}
```

### Create a package from a template

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

```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 every role must be filled; `fields` keys must be merge fields the template asks the sender for. 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": {
    "id": "pkg_9f3c2e",
    "externalId": "order_4471",
    "status": "IN_PROGRESS",
    "recipients": [
      { "id": "cmg4v8q2k0002s7xh6k4m1p9c", "name": "Ana Reid", "email": "ana@example.com", "role": "Employee" },
      { "id": "cmg4v8q2k0003s7xh2b7r5d1w", "name": "Ben Toa", "email": "ben@example.com", "role": "Manager" }
    ]
  }
}
```

Creating requires the key's role to have the send packages permission and Use access to templates. A key can use any template in its workspace; template sharing does not apply to keys. See [Errors](/api-reference/errors) for the full status code list.

## Plan and cost notes

The Flowsign API and webhooks are included in the Enterprise plan. Creating a webhook endpoint needs the manage webhooks permission.

The **Webhook**, **HTTP Request** and **Crypto** nodes are core n8n nodes with no premium gate, on n8n Cloud or self-hosted.
