Developers
API reference
Every endpoint in the FolioSign REST API, generated from the OpenAPI specification — so it always matches the running code. For concepts, auth and error shapes, start with the REST API guide.
Authentication
Send a bearer credential on every request — an org API key (dctr_live_…) for machine-to-machine access, or a session token for a signed-in user.
curl https://foliosign.com/api/v1/documents \
-H "Authorization: Bearer dctr_live_…"Base URL https://foliosign.com · spec version 1.0.0 · download openapi.json
Identity & session
GET/api/v1/meCurrent user, active org, and all memberships▾
Current user, active org, and all memberships
Responses
200The signed-in user401Not authenticated
DELETE/api/v1/meDelete the account (App Store requirement)▾
Delete the account (App Store requirement)
Deletes the user and everything keyed to them (sessions, memberships, device tokens). Refused while the user is the sole owner of a workspace that still has other members — ownership must be transferred first. Workspaces where they were the only member are left orphaned rather than destroyed: signed documents are legal artifacts with an audit chain that other parties rely on.
Responses
200Deleted400Sole owner of a shared workspace401Not authenticated
POST/api/v1/auth/send-verificationResend the email-verification link to the signed-in user▾
Resend the email-verification link to the signed-in user
Responses
200Sent401Not authenticated
GET/api/v1/organizationsList the organizations the user belongs to▾
List the organizations the user belongs to
Responses
200Memberships401Not authenticated
POST/api/v1/organizationsCreate a workspace and set it active (new-user onboarding)▾
Create a workspace and set it active (new-user onboarding)
Takes a JSON request body — see the schema in openapi.json.
Responses
200Created workspace400Invalid name401Not authenticated
POST/api/v1/organizations/{orgId}/switchSet the active organization for this session▾
Set the active organization for this session
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| orgId* | path | string |
Responses
200Switched401Not authenticated403Not a member of that organization
POST/api/v1/auth/sign-outRevoke the current session token▾
Revoke the current session token
Responses
200Signed out401Not authenticated
Devices & push
POST/api/v1/devicesRegister this device's APNs token for push notifications▾
Register this device's APNs token for push notifications
Takes a JSON request body — see the schema in openapi.json.
Responses
200Registered401Not authenticated
DELETE/api/v1/devices/{token}Unregister a device token▾
Unregister a device token
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| token* | path | string |
Responses
200Unregistered401Not authenticated
Dashboard
GET/api/v1/dashboard/pipelineValue-weighted pipeline KPIs for the active org▾
Value-weighted pipeline KPIs for the active org
Responses
200Pipeline analytics401Not authenticated
Documents
GET/api/v1/documentsList documents (cursor-paginated, newest first)▾
List documents (cursor-paginated, newest first)
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| status | query | DocumentStatus | |
| source | query | DocumentSource | |
| q | query | string | Free-text search over document title and recipient name/email |
| cursor | query | string | |
| limit | query | integer | |
| X-FolioSign-Org | header | string | Workspace to act on. Required when authenticating with an API key, which has no session and therefore no active workspace; ignored for session tokens, which use `POST /api/v1/organizations/{orgId}/switch` instead. A key may only name workspaces its own billing account parents — anything else is a 404. Omitting it on an API-key request is a 400 rather than a silent default, because a wrong-but-plausible default files one customer's signed documents under another. |
Responses
200A page of documents401Not authenticated
GET/api/v1/documents/{id}Document detail with recipients▾
Document detail with recipients
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string | |
| X-FolioSign-Org | header | string | Workspace to act on. Required when authenticating with an API key, which has no session and therefore no active workspace; ignored for session tokens, which use `POST /api/v1/organizations/{orgId}/switch` instead. A key may only name workspaces its own billing account parents — anything else is a 404. Omitting it on an API-key request is a 400 rather than a silent default, because a wrong-but-plausible default files one customer's signed documents under another. |
Responses
200The document401Not authenticated404Not found
GET/api/v1/documents/{id}/contentBuilder blocks + variables (the reduced mobile editor's read)▾
Builder blocks + variables (the reduced mobile editor's read)
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string | |
| X-FolioSign-Org | header | string | Workspace to act on. Required when authenticating with an API key, which has no session and therefore no active workspace; ignored for session tokens, which use `POST /api/v1/organizations/{orgId}/switch` instead. A key may only name workspaces its own billing account parents — anything else is a 404. Omitting it on an API-key request is a 400 rather than a silent default, because a wrong-but-plausible default files one customer's signed documents under another. |
Responses
200Blocks400Not a builder document401Not authenticated404Not found
PATCH/api/v1/documents/{id}/contentUpdate a draft's blocks (server re-validates; totals recomputed at render)▾
Update a draft's blocks (server re-validates; totals recomputed at render)
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string | |
| X-FolioSign-Org | header | string | Workspace to act on. Required when authenticating with an API key, which has no session and therefore no active workspace; ignored for session tokens, which use `POST /api/v1/organizations/{orgId}/switch` instead. A key may only name workspaces its own billing account parents — anything else is a 404. Omitting it on an API-key request is a 400 rather than a silent default, because a wrong-but-plausible default files one customer's signed documents under another. |
Takes a JSON request body — see the schema in openapi.json.
Responses
200Updated400Not a draft / invalid blocks401Not authenticated
GET/api/v1/documents/{id}/analyticsPer-recipient timeline and per-page view stats▾
Per-recipient timeline and per-page view stats
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string | |
| X-FolioSign-Org | header | string | Workspace to act on. Required when authenticating with an API key, which has no session and therefore no active workspace; ignored for session tokens, which use `POST /api/v1/organizations/{orgId}/switch` instead. A key may only name workspaces its own billing account parents — anything else is a 404. Omitting it on an API-key request is a 400 rather than a silent default, because a wrong-but-plausible default files one customer's signed documents under another. |
Responses
200Analytics401Not authenticated404Not found
PUT/api/v1/documents/{id}/recipientsReplace the recipients on a draft▾
Replace the recipients on a draft
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string | |
| X-FolioSign-Org | header | string | Workspace to act on. Required when authenticating with an API key, which has no session and therefore no active workspace; ignored for session tokens, which use `POST /api/v1/organizations/{orgId}/switch` instead. A key may only name workspaces its own billing account parents — anything else is a 404. Omitting it on an API-key request is a 400 rather than a silent default, because a wrong-but-plausible default files one customer's signed documents under another. |
Takes a JSON request body — see the schema in openapi.json.
Responses
200Recipients400Not a draft401Not authenticated
POST/api/v1/documents/{id}/sendSend a draft for signature▾
Send a draft for signature
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string | |
| X-FolioSign-Org | header | string | Workspace to act on. Required when authenticating with an API key, which has no session and therefore no active workspace; ignored for session tokens, which use `POST /api/v1/organizations/{orgId}/switch` instead. A key may only name workspaces its own billing account parents — anything else is a 404. Omitting it on an API-key request is a 400 rather than a silent default, because a wrong-but-plausible default files one customer's signed documents under another. |
Takes a JSON request body — see the schema in openapi.json.
Responses
200Sent or rendering400Not sendable401Not authenticated
POST/api/v1/documents/{id}/recipients/{rid}/resendRe-mint a recipient's signing link and re-email it▾
Re-mint a recipient's signing link and re-email it
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string | |
| rid* | path | string | |
| X-FolioSign-Org | header | string | Workspace to act on. Required when authenticating with an API key, which has no session and therefore no active workspace; ignored for session tokens, which use `POST /api/v1/organizations/{orgId}/switch` instead. A key may only name workspaces its own billing account parents — anything else is a 404. Omitting it on an API-key request is a 400 rather than a silent default, because a wrong-but-plausible default files one customer's signed documents under another. |
Responses
200Fresh link401Not authenticated404Not found
POST/api/v1/documents/{id}/recipients/{rid}/linkMint a recipient's signing link without emailing it▾
Mint a recipient's signing link without emailing it
For a partner that embeds the signing ceremony in its own product, where the signer is already on the page and needs a URL rather than a message. Sends no email and is not rate-limited as an expensive endpoint, which is what separates it from `resend` — use that one for "email it to them again". Tokens are stored hashed, so a link can only be minted and never fetched: this rotates the recipient's token, and any link previously emailed to them stops working. The recipient's own status is left as it stands.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string | |
| rid* | path | string | |
| X-FolioSign-Org | header | string | Workspace to act on. Required when authenticating with an API key, which has no session and therefore no active workspace; ignored for session tokens, which use `POST /api/v1/organizations/{orgId}/switch` instead. A key may only name workspaces its own billing account parents — anything else is a 404. Omitting it on an API-key request is a 400 rather than a silent default, because a wrong-but-plausible default files one customer's signed documents under another. |
Responses
200Fresh link400Not signable by that recipient401Not authenticated404Not found
POST/api/v1/documents/{id}/signing-linkMint a fresh signing link for the caller's own recipient row▾
Mint a fresh signing link for the caller's own recipient row
For a sender who is also a signer, so they can sign in-app without the email. Only ever returns the link for the recipient whose email matches the authenticated user; it cannot be used to obtain anyone else's link. Rotates the token, so any link previously emailed to that recipient stops working.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string | |
| X-FolioSign-Org | header | string | Workspace to act on. Required when authenticating with an API key, which has no session and therefore no active workspace; ignored for session tokens, which use `POST /api/v1/organizations/{orgId}/switch` instead. A key may only name workspaces its own billing account parents — anything else is a 404. Omitting it on an API-key request is a 400 rather than a silent default, because a wrong-but-plausible default files one customer's signed documents under another. |
Responses
200Fresh link400Not signable by the caller401Not authenticated404Not found
POST/api/v1/documents/{id}/voidVoid a draft or in-flight document▾
Void a draft or in-flight document
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string | |
| X-FolioSign-Org | header | string | Workspace to act on. Required when authenticating with an API key, which has no session and therefore no active workspace; ignored for session tokens, which use `POST /api/v1/organizations/{orgId}/switch` instead. A key may only name workspaces its own billing account parents — anything else is a 404. Omitting it on an API-key request is a 400 rather than a silent default, because a wrong-but-plausible default files one customer's signed documents under another. |
Takes a JSON request body — see the schema in openapi.json.
Responses
200Voided400Not voidable401Not authenticated
POST/api/v1/documents/{id}/remindManually nudge a recipient (or all outstanding signers)▾
Manually nudge a recipient (or all outstanding signers)
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string | |
| X-FolioSign-Org | header | string | Workspace to act on. Required when authenticating with an API key, which has no session and therefore no active workspace; ignored for session tokens, which use `POST /api/v1/organizations/{orgId}/switch` instead. A key may only name workspaces its own billing account parents — anything else is a 404. Omitting it on an API-key request is a 400 rather than a silent default, because a wrong-but-plausible default files one customer's signed documents under another. |
Takes a JSON request body — see the schema in openapi.json.
Responses
200Reminder(s) sent401Not authenticated404Not found
POST/api/v1/documents/from-pdfCreate a document from a PDF, place a signature field, add the signer, and send▾
Create a document from a PDF, place a signature field, add the signer, and send
One call that uploads a PDF, adds a single signer, places their signature field, and (unless `send:false`) sends it — returning the signing link. Ideal for machine integrations that supply a ready-made PDF (e.g. a Letter of Authorization).
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| X-FolioSign-Org | header | string | Workspace to act on. Required when authenticating with an API key, which has no session and therefore no active workspace; ignored for session tokens, which use `POST /api/v1/organizations/{orgId}/switch` instead. A key may only name workspaces its own billing account parents — anything else is a 404. Omitting it on an API-key request is a 400 rather than a silent default, because a wrong-but-plausible default files one customer's signed documents under another. |
Takes a JSON request body — see the schema in openapi.json.
Responses
200Created (and sent unless send=false)400Invalid PDF or field placement401Not authenticated403Missing scope
POST/api/v1/documents/uploadCreate a draft document from a PDF▾
Create a draft document from a PDF
Uploads a PDF and leaves it as a DRAFT with no recipients or fields. Returns per-page geometry so a client can render the pages and place fields, then call PUT /documents/{id}/fields and POST /documents/{id}/send.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| X-FolioSign-Org | header | string | Workspace to act on. Required when authenticating with an API key, which has no session and therefore no active workspace; ignored for session tokens, which use `POST /api/v1/organizations/{orgId}/switch` instead. A key may only name workspaces its own billing account parents — anything else is a 404. Omitting it on an API-key request is a 400 rather than a silent default, because a wrong-but-plausible default files one customer's signed documents under another. |
Takes a JSON request body — see the schema in openapi.json.
Responses
200Draft created400Invalid PDF401Not authenticated403Missing scope
GET/api/v1/documents/{id}/fieldsList the fields on a document▾
List the fields on a document
Every field with its id, placement and — where it carries one — the prefilled value currently stored. The ids are the point. `PATCH /documents/{id}/field-values` names the fields it corrects, and until now nothing handed them back except the response to the `PUT` that created them: an integration wanting to correct a value months later either had to have stored those ids at send time — a mapping of its own that goes stale the moment the fields are set again — or could not do it at all. Reading them back makes this resource the source of truth rather than something every caller keeps a copy of.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string | |
| X-FolioSign-Org | header | string | Workspace to act on. Required when authenticating with an API key, which has no session and therefore no active workspace; ignored for session tokens, which use `POST /api/v1/organizations/{orgId}/switch` instead. A key may only name workspaces its own billing account parents — anything else is a 404. Omitting it on an API-key request is a 400 rather than a silent default, because a wrong-but-plausible default files one customer's signed documents under another. |
Responses
200The fields401Not authenticated403API key is missing the documents:read scope404No such document
PUT/api/v1/documents/{id}/fieldsReplace the fields on a draft▾
Replace the fields on a draft
Coordinates are normalized 0..1 with a top-left origin, matching the signing ceremony's renderer. Drafts only.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string | |
| X-FolioSign-Org | header | string | Workspace to act on. Required when authenticating with an API key, which has no session and therefore no active workspace; ignored for session tokens, which use `POST /api/v1/organizations/{orgId}/switch` instead. A key may only name workspaces its own billing account parents — anything else is a 404. Omitting it on an API-key request is a 400 rather than a silent default, because a wrong-but-plausible default files one customer's signed documents under another. |
Takes a JSON request body — see the schema in openapi.json.
Responses
200Fields replaced400Not a draft, or invalid placement401Not authenticated404No such document
PATCH/api/v1/documents/{id}/field-valuesCorrect prefilled values on a document already out for signature▾
Correct prefilled values on a document already out for signature
Changes what the prefilled boxes say, and nothing else — not the placements, not the recipients, not which fields exist. This is the operation to reach for when the sender's own records move after the envelope has gone out: a name corrected, an address updated. Without it the only remedy is to void the document and send a second copy, which costs the signer a dead link and a duplicate email over a spelling. **Refused once anybody has signed.** A signature is a statement about the document as that person saw it, so changing a word on the page afterwards would make it evidence of something never displayed. The check is for a signer who has finished rather than the document's own status: a parallel envelope sits at `PENDING` with one of three already done, and that signature binds exactly as the last one would. Only fields that were ever the sender's to fill. Naming a SIGNATURE or INITIALS field is refused rather than ignored — a caller who believes they have updated a signature should be told they have not.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string | |
| X-FolioSign-Org | header | string | Workspace to act on. Required when authenticating with an API key, which has no session and therefore no active workspace; ignored for session tokens, which use `POST /api/v1/organizations/{orgId}/switch` instead. A key may only name workspaces its own billing account parents — anything else is a 404. Omitting it on an API-key request is a 400 rather than a silent default, because a wrong-but-plausible default files one customer's signed documents under another. |
Takes a JSON request body — see the schema in openapi.json.
Responses
200Values corrected400Unknown field, or a field that carries no prefilled value401Not authenticated403API key is missing the documents:write scope404No such document409Somebody has signed, or the document is no longer out for signature
POST/api/v1/documents/{id}/suggest-fieldsSuggest where fields belong on an uploaded PDF▾
Suggest where fields belong on an uploaded PDF
Reads the PDF's text layer and proposes signature/initials/date/text placements for a human to review. Nothing is saved — send what you accept to PUT /documents/{id}/fields. Costs 1 AI credit only when the model runs; the deterministic heuristics are free. A PDF with no text layer (a photo or flat scan) returns no suggestions.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string | |
| X-FolioSign-Org | header | string | Workspace to act on. Required when authenticating with an API key, which has no session and therefore no active workspace; ignored for session tokens, which use `POST /api/v1/organizations/{orgId}/switch` instead. A key may only name workspaces its own billing account parents — anything else is a 404. Omitting it on an API-key request is a 400 rather than a silent default, because a wrong-but-plausible default files one customer's signed documents under another. |
Responses
200Suggestions400No uploaded PDF, or out of AI credits401Not authenticated404No such document
GET/api/v1/documents/{id}/sourceDownload the document's current PDF▾
Download the document's current PDF
The rendered PDF for a builder document, or the uploaded file for an upload — what the signer sees, before any signatures are applied. For the executed copy, use `/documents/{id}/sealed`.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string | |
| X-FolioSign-Org | header | string | Workspace to act on. Required when authenticating with an API key, which has no session and therefore no active workspace; ignored for session tokens, which use `POST /api/v1/organizations/{orgId}/switch` instead. A key may only name workspaces its own billing account parents — anything else is a 404. Omitting it on an API-key request is a 400 rather than a silent default, because a wrong-but-plausible default files one customer's signed documents under another. |
Responses
200The PDF bytes401Not authenticated403API key is missing the documents:read scope404No such document here, or it has no PDF
GET/api/v1/documents/{id}/filledDownload the document as it currently stands, values and all▾
Download the document as it currently stands, values and all
The source PDF with every answer so far drawn onto it: the values the sender prefilled, and anything a signer has completed. This is what the signer is actually looking at. `/documents/{id}/source` hands back the blank file the document was built from, which is the right answer for re-rendering a ceremony and the wrong one for showing a human what went out — an integration displaying it sees an empty form and reasonably concludes the prefill did not work. **Not a substitute for `/sealed`.** Nothing here is certified: no certificate of completion, no digital signature, and it is generated fresh on each request rather than archived. It is a picture of an unfinished document, and it says so — a completed document is refused with a `409` pointing at the sealed copy, which is the one worth keeping and the only one that proves anything.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string | |
| X-FolioSign-Org | header | string | Workspace to act on. Required when authenticating with an API key, which has no session and therefore no active workspace; ignored for session tokens, which use `POST /api/v1/organizations/{orgId}/switch` instead. A key may only name workspaces its own billing account parents — anything else is a 404. Omitting it on an API-key request is a 400 rather than a silent default, because a wrong-but-plausible default files one customer's signed documents under another. |
Responses
200The PDF bytes, with current values drawn on401Not authenticated403API key is missing the documents:read scope404No such document here, or it has no PDF409Completed — use /documents/{id}/sealed
GET/api/v1/documents/{id}/sealedDownload the sealed, certified PDF▾
Download the sealed, certified PDF
The executed document: every signature applied, the certificate of completion appended, and the whole file digitally signed. This is the copy worth keeping — under a workspace-per-customer setup it is the only way the integration holds its customers' executed documents, since those workspaces have no sign-in of their own. Available once the document reaches `COMPLETED` and the seal job has run, which is shortly after the last signer finishes. Poll on `409`: it means not yet. A `404` means the document is not in this workspace, so stop. The response carries `X-Sealed-SHA256`, the same digest as `sealedSha256` on `GET /documents/{id}` — hash the bytes you received and compare, and you have proof the archived copy is the one that was signed.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string | |
| X-FolioSign-Org | header | string | Workspace to act on. Required when authenticating with an API key, which has no session and therefore no active workspace; ignored for session tokens, which use `POST /api/v1/organizations/{orgId}/switch` instead. A key may only name workspaces its own billing account parents — anything else is a 404. Omitting it on an API-key request is a 400 rather than a silent default, because a wrong-but-plausible default files one customer's signed documents under another. |
Responses
200The sealed PDF bytes401Not authenticated403API key is missing the documents:read scope404No such document in this workspace409Not sealed yet — still awaiting signatures or the seal job
AI
POST/api/v1/ai/generateGenerate a proposal from an intake and create a draft document▾
Generate a proposal from an intake and create a draft document
Takes a JSON request body — see the schema in openapi.json.
Responses
200Draft created400Out of AI credits or invalid intake401Not authenticated
Billing
GET/api/v1/billing/usagePlan + usage snapshot for the active org▾
Plan + usage snapshot for the active org
Responses
200Usage summary401Not authenticated
GET/api/v1/billing/plansThe plan catalog (display copy + prices)▾
The plan catalog (display copy + prices)
Responses
200Plans401Not authenticated
POST/api/v1/billing/checkoutStart a Stripe Checkout to upgrade; returns a URL to open externally▾
Start a Stripe Checkout to upgrade; returns a URL to open externally
Takes a JSON request body — see the schema in openapi.json.
Responses
200Checkout link400Invalid plan401Not authenticated403Insufficient role
POST/api/v1/billing/apple/transactionApply a verified App Store subscription transaction▾
Apply a verified App Store subscription transaction
Takes the signed transaction (JWS) from StoreKit and verifies Apple's signature server-side before granting anything — the client's own verification result is not trusted. Idempotent: StoreKit re-delivers transactions until they are finished, and renewals arrive unprompted.
Takes a JSON request body — see the schema in openapi.json.
Responses
200The plan now in force400Transaction failed verification401Not authenticated403Insufficient role
POST/api/v1/billing/portalOpen the Stripe customer portal; returns a URL to open externally▾
Open the Stripe customer portal; returns a URL to open externally
Responses
200Portal link400No billing account yet401Not authenticated403Insufficient role
Admin
GET/api/v1/admin/usersList users across all workspaces▾
List users across all workspaces
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| search | query | string | |
| limit | query | integer |
Responses
200Users401Not authenticated403Not a super-admin
POST/api/v1/admin/impersonateImpersonate a user — returns a session token to use as the bearer▾
Impersonate a user — returns a session token to use as the bearer
Takes a JSON request body — see the schema in openapi.json.
Responses
200Impersonation token401Not authenticated403Not a super-admin
POST/api/v1/admin/impersonate/stopStop impersonating — returns the original admin session token▾
Stop impersonating — returns the original admin session token
Responses
200Original token (may be null)401Not authenticated
API keys
GET/api/v1/apikeysList the active org's API keys (secrets never returned)▾
List the active org's API keys (secrets never returned)
Responses
200API keys401Not authenticated403Insufficient role / not available to API keys
POST/api/v1/apikeysCreate an API key; the full secret is returned exactly once▾
Create an API key; the full secret is returned exactly once
Takes a JSON request body — see the schema in openapi.json.
Responses
201Created key (with secret)400Invalid name or scopes401Not authenticated403Insufficient role / not available to API keys
DELETE/api/v1/apikeys/{id}Revoke an API key▾
Revoke an API key
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string |
Responses
200Revoked401Not authenticated403Insufficient role / not available to API keys404Not found
Workspaces
GET/api/v1/workspacesList the caller's workspaces and the plan's workspace allowance▾
List the caller's workspaces and the plan's workspace allowance
For a signed-in user, the workspaces they are a member of. For an API key, every workspace in its billing group — a key has no memberships, and the workspaces it provisions have no members either. Use the returned `id` as `X-FolioSign-Org` on the document endpoints.
Responses
200Workspaces401Not authenticated403API key is missing the workspaces:read scope
POST/api/v1/workspacesCreate a workspace under the same billing account▾
Create a workspace under the same billing account
It bills through the same subscription while documents, templates and members stay separate. Refused when the plan's workspace allowance is already used, which on every plan but Corporate is one. Send `externalId` — your own id for this customer — to make the call idempotent: a repeat returns the workspace the first call created rather than a second one with the same name. There is no delete endpoint, so a duplicate cannot be undone through the API. A signed-in owner or admin becomes the new workspace's owner. An API key needs the `workspaces:write` scope; the workspace it creates has no members, and is reached by passing its `id` as `X-FolioSign-Org`.
Takes a JSON request body — see the schema in openapi.json.
Responses
200Created, or the existing workspace for a repeated externalId400Allowance reached, or an invalid name401Not authenticated403Requires owner or admin, or the workspaces:write scope for an API key
DELETE/api/v1/workspaces/{id}Delete an empty workspace▾
Delete an empty workspace
For undoing a duplicate — a provisioning call that was retried before you started sending `externalId`, say. It is not a way to close an account. Refused when the workspace holds **any** document, even a draft: a sent document's audit trail is evidence, and a cascade would destroy it silently. Delete or void the documents first. Also refused for the account's main workspace, which holds the subscription the others bill through. An API key needs the `workspaces:delete` scope, which is separate from `workspaces:write` and never granted by default.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string |
Responses
200Deleted400It holds documents, or it is the account's main workspace401Not authenticated403Requires owner or admin, or the workspaces:delete scope for an API key404No such workspace in this billing account
GET/api/v1/workspaces/{id}/embed-originsOrigins allowed to embed this workspace's signing pages▾
Origins allowed to embed this workspace's signing pages
Signing pages refuse framing by default — the ceremony is where a signature is produced, and a page that can frame it can overlay it and collect a signature on a document the signer never read. Listing an origin here permits that origin, and only for documents this workspace sent. See https://foliosign.com/docs/embedding.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string |
Responses
200The allow-list401Not authenticated403API key is missing the workspaces:read scope404No such workspace in this billing account
PUT/api/v1/workspaces/{id}/embed-originsReplace the origins allowed to embed this workspace's signing pages▾
Replace the origins allowed to embed this workspace's signing pages
Signing pages refuse framing by default — the ceremony is where a signature is produced, and a page that can frame it can overlay it and collect a signature on a document the signer never read. Listing an origin here permits that origin, and only for documents this workspace sent. See https://foliosign.com/docs/embedding. The list is replaced wholesale, so send the full set every time and send `[]` to close it again. Origins take effect within a minute — they are read per request, not baked into signing links, so removing one revokes it for links already out there. A bare hostname is read as https. Wildcards are refused: `*.example.com` would re-open the clickjack the default exists to prevent, so a multi-tenant integration lists each customer hostname on that customer's own workspace.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string |
Takes a JSON request body — see the schema in openapi.json.
Responses
200The stored list400An entry isn't an https origin, or there are too many401Not authenticated403Requires owner or admin, or the workspaces:write scope for an API key404No such workspace in this billing account
GET/api/v1/workspaces/{id}/account-promptWhether this workspace's ceremonies offer the signer an account▾
Whether this workspace's ceremonies offer the signer an account
Whether a signer who finishes a ceremony in this workspace is offered a free FolioSign account. On by default, which is right for a link FolioSign sent. Turn it off where the ceremony is embedded inside your own flow — the panel ends that flow on our call to action rather than yours, at the moment the signer should be moving on to your next step.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string |
Responses
200The setting401Not authenticated403API key is missing the workspaces:read scope404No such workspace in this billing account
PUT/api/v1/workspaces/{id}/account-promptTurn the end-of-ceremony account panel on or off▾
Turn the end-of-ceremony account panel on or off
Whether a signer who finishes a ceremony in this workspace is offered a free FolioSign account. On by default, which is right for a link FolioSign sent. Turn it off where the ceremony is embedded inside your own flow — the panel ends that flow on our call to action rather than yours, at the moment the signer should be moving on to your next step. Read per request rather than baked into signing links, so a change reaches links already out there.
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
| id* | path | string |
Takes a JSON request body — see the schema in openapi.json.
Responses
200The stored setting401Not authenticated403Requires owner or admin, or the workspaces:write scope for an API key404No such workspace in this billing account
Settings
GET/api/v1/settings/brandingThe workspace's brand colour▾
The workspace's brand colour
Responses
200Branding401Not authenticated
PATCH/api/v1/settings/brandingSet the workspace's brand colour▾
Set the workspace's brand colour
Send null to clear it back to the FolioSign default. Owner or admin only.
Takes a JSON request body — see the schema in openapi.json.
Responses
200Updated400Not a valid hex colour401Not authenticated403Requires owner or admin
oauth
GET/api/v1/oauth/grantHealth of the OAuth grant this token belongs to▾
Health of the OAuth grant this token belongs to
Reports whether the calling token's grant is live, what it was granted, which billing account it acts on, and when each half of the credential expires. Intended to be polled (hourly is plenty) so an integration can surface connection health to its own operators rather than discovering a lapsed grant through documents silently not being sent. Requires an OAuth access token; an API key has no grant and gets a 403. No scope is required — a grant whose scopes have been narrowed must still be able to report that.
Responses
200Grant health401Missing, expired (`token_expired`) or revoked (`grant_revoked`) credential403Authenticated with an API key, which has no grant