{ "error": "...", "details"?: {...} }. Read error first: it names the cause. See Errors and rate limits for the full status table.
401 Unauthorized
The API could not accept the key. One of:- No
Authorizationheader, or a token that does not start withfsk_. - Unknown key. Keys are shown once; if the value is lost, create a new one at Settings > API keys.
- Revoked or expired key. Revocation is immediate, and a key with an expiry stops at the end of that day. Create a new key.
- The key’s role lost the API access permission. An administrator can restore it from Roles & Permissions.
- Wrong
X-Workspace-Id. The header may only repeat the key’s own workspace id. Omit it, or read the id fromGET /api/v1/workspaces. To act in another workspace, create a key for it.
402 Payment Required
- The plan does not include the API (or webhooks, on
/api/v1/webhooksroutes). Both are Enterprise plan features; the message names the missing one. - No credit left to send. Sending charges one package against the organisation’s allowance.
403 Forbidden
Missing permission: ...names the permission the key’s role lacks, such ascanSendPackages. Grant it from Roles & Permissions, or issue a key on a role that has it.IP address not allowed. The organisation has an IP allowlist (Settings > Security) and the request came from outside it. Check the address your request actually leaves from: a cloud function or a CI runner is not your office.This action requires a signed-in session, not an API key. The route is an admin route for signed-in users only, not part of the public API.
404 Not Found
The resource does not exist in the workspace the key acts in, or the key’s role cannot see it. A resource in another workspace is a404, not a 403: create a key for that workspace.
409 Conflict
The request conflicts with the resource’s current state:- Another member is editing the package or template in the app. Documents and fields cannot be changed through the API while that edit lock is held, and a locked draft cannot be sent. Try again once they are done.
- Void on a package that has already ended, on hold on one that is not
IN_PROGRESS, or resume on one that is notON_HOLD. - Send before every file has arrived.
PUTeach document’s bytes to itsuploadUrlbefore sending; a package with no documents is refused the same way. - Download before completion. Signed copies and the certificate exist only once the package has completed.
- 50 active keys. An organisation can hold at most 50; revoke one to make room.
413 Payload Too Large
POST /api/v1/templates/{templateId}/documents refuses a document whose fileSize is over the per-document limit. GET /api/v1/packages/{packageId}/download refuses documents too large to merge into one PDF; use GET /api/v1/packages/{packageId}/download/zip instead.
422 Unprocessable Entity
The JSON was well-formed but failed validation.details maps each failing field path to its messages: recipients.0.email is the email of the first recipient, and details.pageSize on a GET means a query parameter. Unknown merge field, metadata or role keys produce the same shape.
429 Too Many Requests
All/api/v1 routes share one limit of 120 requests per 60-second window, counted per source IP address. Wait at least the Retry-After seconds before retrying, and prefer webhooks over polling.
Upload URL expired
AnuploadUrl is single-use and expires after two hours. If the PUT fails, add the document again with POST /api/v1/packages/{packageId}/documents (or the template equivalent) and upload to the new URL.
Webhook not arriving
- The endpoint is Failing. After 10 consecutive failed deliveries the endpoint is skipped for new events. Resume it in Settings > Webhooks or with
PATCH /api/v1/webhooks/{endpointId}and{ "enabled": true }. A paused endpoint receives nothing either. - Signature mismatch. Compute the HMAC-SHA256 over the raw request bytes, not a re-serialised body: re-serialising changes whitespace and key order, so the digest no longer matches
x-flowsign-signature. - Private address refused. Endpoints must be public
https://URLs. A private, loopback or link-local address is refused at registration, and a delivery whose host resolves that way is exhausted without retries. - Slow or redirecting responses. Respond
2xxwithin 10 seconds; a3xxcounts as a failure because redirects are not followed.
GET /api/v1/webhooks/{endpointId}, shows each attempt’s status and error.

