Skip to main content
A webhook endpoint is an HTTPS URL that Flowsign POSTs to when something happens to a package or a recipient’s session. An endpoint belongs to the workspace it was created in and receives events only for that workspace’s packages. A workspace holds up to 20 endpoints.
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, .local and .internal names, 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.
After saving, the endpoint’s signing secret is shown once. Store it; you need it to verify deliveries and it cannot be read again. If it is lost or exposed, rotate it (see Rotating the secret). The same page lists each endpoint with its state (Active, Paused or Failing) and lets you pause, resume, edit or delete it, rotate its secret, send it a test event, and open its delivery log.

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 HTTP POST 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 the x-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.
The Python and C# receivers hand the payload to a background queue rather than processing it inline, so the response still goes out well inside the 10 second budget. Use 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 with POST /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, or POST /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 from GET /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.