Receiving events
Create a webhook endpoint in FlowSign at Settings > Webhooks (my.flowsign.app/settings/webhooks), or with the API (see Webhooks).- Add a Webhook node, set it to accept
POST, and activate the workflow so it gets a production URL. - Paste that URL into the endpoint’s URL field in FlowSign.
- Tick the events to subscribe to (for example Package Completed) and save. FlowSign shows the endpoint’s signing secret once; store it.
POST with three headers and a JSON body:
data differs per event. See Events for every event’s shape.
Verifying the signature
Compute a hex HMAC-SHA256 of the raw body with the endpoint secret and compare it toX-FlowSign-Signature. 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.rawBody }}, Encoding set to hex, and the secret in its Crypto credential. Follow it with an IF node comparing the Crypto node’s output to {{ $json.headers["x-flowsign-signature"] }}, and stop the workflow on the false branch.
To do the same in a Code node instead:
Calling the API
Use the HTTP Request node for any FlowSign API call. Base URL:https://my.flowsign.app. Every request needs:
Create the key at Settings > API keys; see 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, URLhttps://my.flowsign.app/api/v1/packages?status=IN_PROGRESS.
Create a package from a template
Method POST, URLhttps://my.flowsign.app/api/v1/packages/from-template, body type JSON:
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.

