The API and webhooks are available on the Enterprise plan. Calls from other plans return
402.https://my.flowsign.app. Every success response is wrapped as { "data": ... }; every error is { "error": "...", "details"?: {...} }. See Errors.
1
Create an API key
In the app, open Settings > API keys (my.flowsign.app/settings/api-keys) and create a key. Give it a name, choose the role it acts as and the workspace it works in, and optionally set an expiry date. The key is shown once; copy it now.Only an owner can create keys. The role you choose must have the API access permission; the Admin profile has it by default, and an administrator can grant it to other profiles from Roles & Permissions. The key acts with that role’s permissions in that workspace, not as the person who issued it.
2
Check the key works
List the workspaces the key can act in. A key is bound to one workspace, so the response lists that one and names it as the active workspace.You can send
X-Workspace-Id: <id> on any request to be explicit, but it may only name the key’s own workspace; any other value is refused with 401. To work in another workspace, create a key for it. See Workspaces.3
Build a template in the app
The quickest route to a sent package is a template: it already holds the documents, roles and fields, so the API only needs the recipients. Create one in the app with at least one document, one role and the fields each role must complete, then set it to Each template in the response lists its
ACTIVE. See Building a workflow. (The API can also upload documents and place fields itself; see Creating a package without a template.)Find its id with the API:roles. You map recipients onto roles by role name in the next step.4
Create a package from the template
POST /api/v1/packages/from-template creates a DRAFT package from an ACTIVE template; a template still in DRAFT is refused with 409 until it is published in the app. Supply one recipient per role, naming the role with role; roles are matched by name, not by position, and every role in the template must be given a recipient. Merge field values go in fields, keyed by merge field key; a blank value takes the field’s default, and keys the template does not ask the sender for are rejected with 422. Pass an externalId of your own to make the call idempotent: repeating it returns the existing package instead of creating another."status": "sent" to send the package in the same call (the response then reports IN_PROGRESS), or scheduledAt (an ISO 8601 timestamp) to create a SCHEDULED package that Flowsign sends at that time. Do not call send on a scheduled package.5
Send it
Sending is an action on the package. Only With parallel signing, every Signer and Viewer now receives their invitation email; with a signing order on, only the first turn is invited and the rest follow as each turn completes. Sending charges one package against your allowance. A
DRAFT packages can be sent, and the key’s role needs the send permission.402 means the organisation has run out of packages (or its plan no longer includes the feature), and a 409 means a document’s file has not finished uploading.6
Follow progress
Poll the package, or register a webhook and react to The response includes
SESSION_COMPLETED and PACKAGE_COMPLETED instead.status, each recipient’s session with sentAt, openedAt, completedAt and declinedAt, the documents, and the last 100 audit events.The same flow in code
The steps above are the cURL walkthrough. Here is the whole run in one file, in three of the languages the endpoint reference also shows.Other package actions
PATCH /api/v1/packages/{packageId} also accepts:
Custom fields
Custom fields are the organisation’s own reference values on a package, such as an employee ID or a cost centre. They are defined in the app under Settings > Custom fields (the API reads their values but does not create or edit the definitions); each one has akey that never changes. GET /api/v1/custom-fields lists them.
Packages carry their values as metadata, an object keyed by custom field key. GET /api/v1/packages, GET /api/v1/packages/{packageId} and every webhook event include it, as {} when nothing is set. GET /api/v1/templates/{templateId} returns the template’s defaults the same way; they are set in the app, and POST or PATCH on /api/v1/templates refuses metadata with 400.
Set values with metadata on POST /api/v1/packages/from-template or POST /api/v1/packages. A package from a template starts with the template’s defaults, and each key you send replaces one; an empty string clears it.
422 and details.metadata when a key is not a live custom field that applies to the package, and when a required custom field is empty on a call that sends or schedules the package. Sending a draft with PATCH checks its required custom fields the same way.
Creating a package without a template
POST /api/v1/packages creates a DRAFT package from a title, recipients and document descriptors (fileName, pageCount, nonce), or a SCHEDULED one when you pass scheduledAt. Each document comes back with an uploadUrl: PUT the PDF bytes to it to attach the file. The URL is single-use and expires after two hours, and sending is refused with 409 while any document’s file has not arrived.
Documents can also be added later with POST /api/v1/packages/{packageId}/documents, or taken from the library with POST /api/v1/packages/{packageId}/library-documents, and fields are placed with PUT /api/v1/packages/{packageId}/fields. Templates accept documents the same way through POST /api/v1/templates/{templateId}/documents and PUT /api/v1/templates/{templateId}/fields. Use a template when the same documents go out repeatedly; build the package directly when every send carries its own files.
Release labels
Parts of the app carry a label such as Experimental or Coming soon, explained in Release labels. Those labels describe the app, not this API: an experimental feature is not part of the public API unless an endpoint says so.Next
Authentication
Key lifecycle, permissions, plan requirements and the IP allowlist.
Errors and rate limits
Status codes, validation details and the 120 requests per minute limit.
Webhooks
Signed event deliveries with retries.
Endpoint reference
Every request and response field, with copyable code samples.

