Webhooks are included in the Enterprise plan. Managing endpoints, in the app or through the API, requires the manage webhooks permission, which owners and the Admin role hold.
Creating an endpoint
In the app
Open Settings > Webhooks (my.flowsign.app/settings/webhooks) and add an endpoint:- Endpoint URL: must use
https://and point at a publicly reachable host.localhost,.localand.internalnames, and private, loopback, link-local and multicast addresses are refused. - Description: optional, for your own reference.
- Events: tick the events to subscribe to. See Events.
With the API
secret is returned only in this response. GET, PATCH and DELETE /api/v1/webhooks/{endpointId} manage the endpoint afterwards; GET also returns its deliveries a page at a time. GET /api/v1/webhooks lists the workspace’s endpoints. Creating a 21st endpoint in a workspace returns 409.
What gets delivered
Each delivery is an HTTPPOST with a JSON body (Content-Type: application/json) and four Flowsign headers:
The body has the same envelope for every event:
data differs per event; see Events. Every event’s data carries metadata, the package’s custom field values.
Respond with any 2xx status within 10 seconds. Do the real work after you have responded; anything slower is treated as a failure and retried. Redirects are not followed, so a 3xx response also counts as a failure.
Verifying a delivery
Build the signed content from thex-flowsign-timestamp header, a ., and the raw request body (before any JSON parsing or re-serialisation). Compute its HMAC-SHA256 with the endpoint secret, hex-encode it, and compare it with a constant-time comparison to each v1= entry in x-flowsign-signature. Accept the delivery when any entry matches and the timestamp is within 5 minutes of your clock; refusing older timestamps stops a captured delivery being replayed.
x-flowsign-delivery-id as an idempotency key: a delivery can arrive more than once if your endpoint responded slowly the first time.
Rotating the secret
Rotate a secret from the endpoint’s actions in Settings > Webhooks, or withPOST /api/v1/webhooks/{endpointId}/rotate-secret. The new secret is returned once. For the next 24 hours every delivery is signed with both the new and the previous secret, so a receiver that still holds the old one keeps verifying while you switch over. After that only the new secret signs. Rotating again inside the 24 hours retires the older secret at once.
Sending a test event
Send test event in the endpoint’s actions, orPOST /api/v1/webhooks/{endpointId}/test with { "event": "PACKAGE_COMPLETED" }, sends a signed sample of any event the endpoint subscribes to and reports the outcome straight away. Asking for an event the endpoint is not subscribed to returns 422. The body carries "test": true and sample data in the event’s usual shape. A test is tried once, even while the endpoint is paused or failing, appears in the delivery log marked as a test, and never counts towards the endpoint failing.
Retries
If your endpoint returns a non-2xx status (including a 3xx redirect), times out, cannot be reached, or its host does not resolve, the delivery is retried with exponential backoff. The delays below are the minimum for each step: random jitter makes each real delay between one and two times the value shown.
After nine attempts, spread over roughly four and a quarter to eight and a half hours depending on the jitter, the delivery is marked exhausted and not retried. A delivery is also exhausted straight away, with no retries, if the endpoint’s host is refused at delivery time because it resolves to a private or loopback address. The connection then goes to the address that was checked, never to a second lookup.
Each exhausted delivery increments the endpoint’s failure counter; a successful delivery resets it to zero. Individual failed attempts that are still being retried do not count. At 10 exhausted deliveries in a row the endpoint is shown as Failing. A failing endpoint still records every new event but sends nothing until you resume it. Resuming it in Settings, or
PATCH /api/v1/webhooks/{endpointId} with { "enabled": true }, clears the counter and sends the held deliveries, oldest first.
Pausing an endpoint stops deliveries without counting failures. Events keep being recorded while it is paused, and retries already scheduled keep their place; resuming sends all of them, oldest first.
Delivery log
Every delivery is recorded with its event, status (Pending, Retrying, Delivered or Exhausted), attempt count, next attempt time, response status and any error; the response body is not exposed. Read it from the deliveries panel in Settings > Webhooks, which pages through 25 at a time and filters by status, or fromGET /api/v1/webhooks/{endpointId} with page, pageSize and status. The API reports the statuses as PENDING, FAILED (shown as Retrying in the app), DELIVERED and EXHAUSTED. Deliveries are kept for 30 days.
An exhausted delivery can be sent again with Retry now in the panel, or POST /api/v1/webhooks/{endpointId}/deliveries/{deliveryId}/retry. It keeps its delivery id and payload and starts a fresh round of attempts. Retrying a delivery in any other status returns 409.
