Developers
API reference
Every endpoint, generated from the server's router.
310 operations in 28 areas, generated from the server's router. Paths are relative to your server (for example https://procera.example.com); authenticate as described in the API overview. The OpenAPI 3.1 document has the same paths and summaries for tools. Request and response bodies are described in words until typed schemas land.
Sign-in and account
Signing in with a password and a second step, refreshing and ending sessions, two-step verification and passkeys. Browser flows; automation uses API tokens.
POST
/api/v1/auth/loginSigns in with
emailandpassword. Returns an access token and sets the refresh cookie, or answersmfa_required(withmfa_token) orpassword_change_required. 429 when rate-limited.Audited as
login.password_change_required,login.password_ok_mfa_required,login.succeeded,password.reset_requestedPOST
/api/v1/auth/mfaCompletes sign-in with the
mfa_tokenand exactly one ofcode(TOTP or recovery code) orcredential(passkey assertion); 422 otherwise. Returns an access token and the refresh cookie.Audited as
login.succeededPOST
/api/v1/auth/mfa/webauthn/optionsPasskey challenge for the second sign-in step (after the password).
POST
/api/v1/auth/refreshA new access token from the refresh cookie (rotating it). Requires the
X-Requested-With: proceraheader (403 without it); 401 without a valid cookie.POST
/api/v1/auth/logoutEnds the session behind the refresh cookie and clears it; 204. Requires the
X-Requested-With: proceraheader.Audited as
logoutGET
/api/v1/meThe signed-in user's account and the current token's facts (methods used, auth time, plane, workspace, expiry).
POST
/api/v1/me/sign-out-everywhereRevokes every session of the caller's account and invalidates its outstanding access tokens, then clears the refresh cookie; 204.
Audited as
sessions.revoked_allPOST
/api/v1/me/mfa/totpStarts authenticator-app enrolment and returns the secret to scan; confirm it with
POST /me/mfa/totp/confirm.Audited as
mfa.totp_enrollment_startedPOST
/api/v1/me/mfa/totp/confirmConfirms TOTP enrolment with a
code; returns the recovery codes (shown once) and an upgraded access token for this session.Audited as
mfa.totp_enabledGET
/api/v1/me/mfa/webauthnThe caller's registered passkeys.
POST
/api/v1/me/mfa/webauthnRegisters a passkey (
name,credential) answering the challenge from/me/mfa/webauthn/options; 201. Recovery codes are returned once when it is the first second factor.Audited as
mfa.webauthn_addedPOST
/api/v1/me/mfa/webauthn/optionsA WebAuthn registration challenge for adding a passkey.
DELETE
/api/v1/me/mfa/webauthn/{id}Removes one of the caller's passkeys; 204. Needs a sign-in within the last 5 minutes (401
step_up_required).Audited as
mfa.webauthn_removed
Email approvals
The confirm page behind Approve and Reject links in approval emails: read the request, then decide once. The link is the credential; no session.
GET
/api/v1/email-actions/{token}What the confirm page shows (no session; the link is the key):
{state: open|used|expired|closed, deciding_as, workspace, step, outcomes, request {display_id, title, type_name, initiator, submitted_at, due_at}, answers [{label, type, value}], expires_at}. Answers marked confidential or restricted are left out. 404 for an unknown link.POST
/api/v1/email-actions/{token}Decides once through the link:
outcomeapproved, orrejectedwith acomment. Candidacy, separation of duties and "one decision wins" apply as in My work. 409 when the link was used or expired or the step is already decided. Returns{outcome, display_id, status}.Audited as
instance.advanced,instance.completed,webhook.created,work.decided_by_email,work_item.decided
Outgoing webhooks
Endpoints that receive signed events, their delivery log, replay, test events and secret rolling, and the event catalogue.
GET
/api/v1/webhook-eventsThe event types a webhook can receive, with what each means.
GET
/api/v1/webhooksThe workspace's endpoints with their last delivery (
connector:view).POST
/api/v1/webhooksA new endpoint (
urlhttps,eventstypes or["*"],description;connector:configure; at most 20). 201 with the endpoint and itssecret(shown only here). 422 for a URL inside a private network or a port other than 443/80/8443/8080.GET
/api/v1/webhooks/{id}One endpoint (
connector:view), with anETagof its revision.PATCH
/api/v1/webhooks/{id}Changes the URL, events, description or on/off (
connector:configure; honoursIf-Match). Turning an endpoint back on clears why it was turned off.Audited as
webhook.updatedDELETE
/api/v1/webhooks/{id}Removes an endpoint and its delivery log (
connector:configure). 204.Audited as
webhook.deletedPOST
/api/v1/webhooks/{id}/rotate-secretA new signing secret (
connector:manage_secrets); the previous one also signs for 24 hours. Returns{secret, previous_valid_until}.Audited as
webhook.secret_rotatedPOST
/api/v1/webhooks/{id}/testQueues a
webhook.testevent for the endpoint (connector:configure); the next delivery pass sends it. 202 with the delivery.Audited as
webhook.testedGET
/api/v1/webhooks/{id}/deliveriesThe endpoint's deliveries, newest first (at most 200), each with its state, attempts, last status, error and duration, a response excerpt and the event body (
connector:view).POST
/api/v1/webhooks/deliveries/{id}/replaySends a delivery again from the start of its retry schedule, with the same event id (
connector:configure).Audited as
webhook.replayed
API tokens
Personal API tokens: create, list and revoke your own; security admins list and revoke everyone's.
GET
/api/v1/me/api-tokensMy tokens in this workspace, newest first.
POST
/api/v1/me/api-tokensA new token with some of my own permissions; the secret is shown once.
Audited as
api_token.createdDELETE
/api/v1/me/api-tokens/{id}Revoke one of my tokens (repeating it is a no-op).
Audited as
api_token.revokedGET
/api/v1/api-tokensEvery token in the workspace (
api_token:manage).DELETE
/api/v1/api-tokens/{id}Revoke anyone's token (
api_token:manage).Audited as
api_token.revoked
Workspace and members
Your workspaces and permissions, switching workspace and step-up, invitations, members, deactivation and reactivation.
GET
/api/v1/me/workspacesThe workspaces I belong to, and which one my current token is for (
active).POST
/api/v1/session/workspaceIssues an access token for the chosen workspace (or none, for the home view).
Audited as
session.workspace_selectedPOST
/api/v1/session/step-upRe-authenticates within the current sign-in and returns an access token with a fresh
auth_time.Audited as
session.stepped_upPOST
/api/v1/session/step-up/webauthn/optionsPasskey challenge for step-up.
GET
/api/v1/invitations/previewPublic: what the invitation page shows to the holder of the link.
POST
/api/v1/invitations/acceptAccepts an invitation (body
{token}) for the signed-in user and returns the newworkspace_idandmembership_id.Audited as
member.joinedPOST
/api/v1/invitations/registerCreates an account from an invitation (
token,display_name,password) and joins the workspace; 201. Sign in afterwards to get a workspace token.Audited as
member.joined,user.createdGET
/api/v1/permission-catalogEvery permission and the built-in role templates with their permissions.
GET
/api/v1/me/permissionsMy effective permissions in this workspace, and whether I manage a team (
manages: I have direct reports or holdwork:view_teamon a department).GET
/api/v1/membersEvery member of the workspace (
member:view).GET
/api/v1/members/invitationsThe workspace's invitations (
member:invite). Links are never included.POST
/api/v1/members/invitationsInvites an email address with a set of
roles(member:invite); 201. The invitation link is sent by email only and is never returned here.Audited as
member.invitedDELETE
/api/v1/members/invitations/{id}Revokes a pending invitation so its link stops working (
member:invite); 204.Audited as
member.invitation_revokedPOST
/api/v1/members/invitations/{id}/linkA fresh one-time link for a pending invitation, for the inviter to hand over when email isn't set up. The earlier link stops working. Only this response carries the token; lists never do.
Audited as
member.invitation_link_copiedPOST
/api/v1/members/{id}/deactivateDeactivates a member, ending their access to the workspace (
member:deactivate); 204.Audited as
member.deactivatedPOST
/api/v1/members/{id}/reactivateBrings a deactivated member back with the roles they had. Restoring access is treated like granting it: step-up, and no restoring roles the caller could not grant.
Audited as
member.reactivatedGET
/api/v1/rolesThe workspace's roles with their permissions (
role:view).POST
/api/v1/rolesA custom role (
key,name,permissions, optionalcloned_fromtemplate);role:manageplus a recent step-up (401step_up_requiredotherwise); 201.Audited as
role.createdPATCH
/api/v1/roles/{id}Replaces a role's
permissions(role:manageplus a recent step-up); 204. The audit entry records what was added, removed and how many members it affects.Audited as
role.updatedPOST
/api/v1/roles/{id}/previewShows what a role change would do before saving it.
GET
/api/v1/role-grantsRole grants in the workspace, optionally for one
?membership_id=(role:view).POST
/api/v1/role-grantsGrants
role_keyto exactly one ofmembership_idorgroup_id(else 422), with an optional scope,expires_atandreason;member:manage_rolesplus a recent step-up; 201{id}.Audited as
role.grantedDELETE
/api/v1/role-grants/{id}Revokes a role grant (
member:manage_rolesplus a recent step-up); 204.Audited as
role.revoked
Directory
Departments, groups, positions, managers and the CSV import that keeps them in step with your HR system.
GET
/api/v1/departmentsEvery department in the workspace (
directory:view).POST
/api/v1/departmentsA new department (
name, optionalparent_id);directory:manage; 201.PATCH
/api/v1/departments/{id}Renames a department, moves it (
parent_id,nullfor the root) or sets its head (head_membership_id);directory:manage; 204.Audited as
department.updatedDELETE
/api/v1/departments/{id}Deletes an empty department (
directory:manage); 204. A department that still has sub-departments, members or positions is refused with 409.Audited as
department.deletedGET
/api/v1/departments/{id}/usageWhat refers to a department, shown before deleting it: role grants scoped to it, and active or draft campaigns, announcements and policies whose audience names it. Titles only, and only for people who manage the directory.
GET
/api/v1/groupsEvery group in the workspace (
directory:view).POST
/api/v1/groupsA new group (
name, optionaldescription);directory:manage; 201.Audited as
group.createdDELETE
/api/v1/groups/{id}Deletes a group (
directory:manage); 204.Audited as
group.deletedGET
/api/v1/groups/{id}/membersThe membership ids in a group (
directory:view).POST
/api/v1/groups/{id}/membersAdds a member (
membership_id) to a group (directory:manage); 204.Audited as
group.member_addedDELETE
/api/v1/groups/{id}/members/{membership_id}Removes a member from a group (
directory:manage); 204.Audited as
group.member_removedGET
/api/v1/positionsEvery position in the workspace (
directory:view).POST
/api/v1/positionsPositions are off unless
directory.positions.enabled.Audited as
position.createdGET
/api/v1/locationsThe directory locations in use, with how many active members each has (audience pickers).
DELETE
/api/v1/positions/{id}Deletes a position (
directory:manage); 204.Audited as
position.deletedPATCH
/api/v1/members/{id}Sets a member's directory fields (
title,department_id,manager_membership_id,location;nullclears one);directory:manage. Returns{changed}.Audited as
member.directory_updatedGET
/api/v1/members/{id}/directoryA member's directory fields, groups and resolved manager (explicit, department head or none);
directory:view.GET
/api/v1/members/{id}/holdingsWhat a member holds, for the leaving flow (docs/design/ia-competitive-analysis.md §8.3): documents they own, drafts and reviews they started, campaigns they run, groups, direct reports, role grants and open acknowledgements, plus the workspace's hand-over default. Titles and counts only.
POST
/api/v1/members/importCSV directory import.
mode=plan(default) reports what would change and rolls back;mode=applycommits.Audited as
member.directory_imported
Library (SOPs and policies)
Controlled documents: drafts, review and approval, publishing as major or minor versions, retirement, review cadence, verification and change requests.
GET
/api/v1/artifactsThe SOPs and policies the caller may view, filtered by
kind,stateandcollection(sub-collections included). Drafts and restricted ones show only to authors of the kind.POST
/api/v1/artifactsA new SOP or policy (
kind,key,title, optionalcriticality,content) with its first draft (<kind>:create). 201 with the artifact and version; 409key_taken.Audited as
artifact.createdGET
/api/v1/artifacts/{id}One document, the versions the caller may see and
my_actions(what the caller may do with it, scoped grants included). Returns anETagof its revision.POST
/api/v1/artifacts/{id}/versionsStarts a new draft from the latest version's content (
<kind>:edit_draft). 201; 409 when a draft or review is already open.Audited as
version.createdGET
/api/v1/versions/{id}One version with its content and review state (
<kind>:view; drafts only for authors of the kind). Returns anETagof its revision.PATCH
/api/v1/versions/{id}Replaces a draft's
content(<kind>:edit_draft). SendIf-Match: "<revision>"to guard against overwrites (412 when stale); 409 when the version is not a draft.Audited as
version.editedGET
/api/v1/versions/{a}/diff/{b}Semantic diff between two versions of the same artifact: block-level added/removed/changed with word-level changes inside changed blocks.
PUT
/api/v1/artifacts/{id}/review-cadenceSets the document's review cadence in
days, ornullfor the workspace default (<kind>:publish).Audited as
artifact.review_cadence_setPOST
/api/v1/artifacts/{id}/recertifyThe owner confirms the published content is still correct, with an optional
comment; a new review period starts now (<kind>:publish).Audited as
artifact.recertifiedPOST
/api/v1/artifacts/{id}/verificationVerifying a controlled artifact needs a recent authentication, like approving it.
Audited as
artifact.verifiedDELETE
/api/v1/artifacts/{id}/verificationRemoves the document's verification badge (
<kind>:approve).Audited as
artifact.verification_removedGET
/api/v1/artifacts/{id}/change-requestsChange requests proposed for a document, optionally filtered by
state(<kind>:view).POST
/api/v1/artifacts/{id}/change-requestsProposes a change to a document with a
titleand optionalbody; any reader may (<kind>:view). 201.Audited as
change_request.openedGET
/api/v1/change-requests/{id}One change request (
<kind>:viewon its document).POST
/api/v1/change-requests/{id}/resolvedecisionaccepted,declined(needs aresolution) orimplemented(needs aversion_idof the same document);<kind>:publish. 409 from a wrong state.Audited as
change_request.resolvedPUT
/api/v1/artifacts/{id}/applicabilitySets a document's
category, who it applies to (applicabilityaudience,null= everyone) and therestrictedflag (<kind>:publish). 422 for an empty audience.Audited as
artifact.applicability_setGET
/api/v1/me/policiesThe policies that apply to the caller, with what changed since the previous version.
GET
/api/v1/collectionsThe collections the caller may see, or all of them with
collection:manage(collection:view).can_managesays which.POST
/api/v1/collectionsA new collection with a
name, optionally underparent_id(collection:manage). 201.Audited as
collection.createdPATCH
/api/v1/collections/{id}Renames a collection and/or moves it (and its subtree) under
parent_id(null= top level);collection:manage. A collection cannot move under itself.Audited as
collection.updatedDELETE
/api/v1/collections/{id}Deletes an empty collection (
collection:manage). 204; 409 while it still holds documents or sub-collections.Audited as
collection.deletedPUT
/api/v1/collections/{id}/visibilitySets who may see a collection (
visibilityaudience,null= everyone);collection:manage. 422 for an empty audience.Audited as
collection.visibility_setPUT
/api/v1/artifacts/{id}/collectionFiling a document needs
publishon its kind (the people who control where it lives).Audited as
artifact.collection_setPUT
/api/v1/artifacts/{id}/ownerChanges a document's accountable owner to an active member (
membership_id);<kind>:publish.Audited as
artifact.owner_setGET
/api/v1/artifacts/{id}/raciA document's RACI assignments (
<kind>:view).PUT
/api/v1/artifacts/{id}/raciReplaces a document's RACI, with at most one accountable assignee (
<kind>:publish).Audited as
artifact.raci_setGET
/api/v1/raci/exportRACI of every document the caller may see, as CSV. Audited.
GET
/api/v1/versions/{id}/exportA self-contained, print-ready HTML document (browsers print it as a tagged PDF), Markdown, or a Word document with real headings, lists and tables. Superseded and retired versions carry a "not the current version" banner. Audited.
POST
/api/v1/versions/{id}/submitSends a draft for review (
<kind>:edit_draft); when the workspace requires no review for it, it is approved at once.Audited as
version.approved,version.submitted,version.withdrawnPOST
/api/v1/versions/{id}/withdrawTakes a version out of review back to draft (
<kind>:edit_draft).POST
/api/v1/versions/{id}/reviewsRecords a
decision(approve,reject,changes_requested; the last two need acomment). Authors cannot review their own (403); controlled approvals need step-up.Audited as
campaign.activated,campaign.created,version.approved,version.published,version.retired,version.reviewed,version.scheduledPOST
/api/v1/versions/{id}/publishPublishes an approved version now or at
effective_at, as amajororminorchange(<kind>:publish; controlled needs step-up).reacksays who must re-acknowledge.GET
/api/v1/versions/{id}/publish-previewWhat publishing a version would do: its number as a major or minor change, whether each asks for a re-acknowledgement, how many people that reaches and by when.
POST
/api/v1/versions/{id}/retireRetires a published or deprecated version with a
reason; it is read-only afterwards (<kind>:publish).
Acknowledgement campaigns
Ask people to acknowledge a published document by a deadline, with reminders, escalation to managers and evidence exports.
GET
/api/v1/campaignsEvery acknowledgement campaign in the workspace, optionally filtered by
?state=. Needscampaign:view.POST
/api/v1/campaignsA draft campaign for a published SOP or policy version (
version_id,audience, optionaltitle,due_at,audience_snapshot,ack_text). Needscampaign:manage; 201.Audited as
campaign.createdGET
/api/v1/campaigns/{id}One campaign with an
ETag; a draft also carriesaudience_preview, the number of active members its audience reaches now. Needscampaign:view.GET
/api/v1/campaigns/{id}/recipientsThe campaign's assignments, optionally
?state=pending|completed|overdue(422 otherwise). Needscampaign:view.GET
/api/v1/campaigns/{id}/evidenceEvidence export as CSV. The export itself is audited (
campaign.evidence_exported).POST
/api/v1/campaigns/{id}/activateLaunches a draft, snapshotting its audience into assignments and notifying every assignee. Needs
campaign:manage; 409 unless it is a draft.Audited as
campaign.activatedPOST
/api/v1/campaigns/{id}/closeCloses an active campaign (optional
reason), freezing it as evidence; open assignments stay as the record. Needscampaign:manage; 409 in any other state.Audited as
campaign.closedPOST
/api/v1/campaigns/{id}/cancelCancels a draft or active campaign; a
reasonis required (422). Needscampaign:manage; 409 in any other state.Audited as
campaign.cancelledPOST
/api/v1/campaigns/{id}/remindSends a reminder now to every open assignment of active members and returns
{reminded}. Needscampaign:manage; 409 unless the campaign is active.Audited as
campaign.remindedGET
/api/v1/me/acknowledgementsThe caller's own acknowledgements (
?state=pending|completed; default: open and completed), limited to the kinds they may acknowledge.POST
/api/v1/acknowledgements/{id}/completeAcknowledges the caller's own assignment, optionally checking
content_hash(409content_changed). 409already_acknowledgedon repeat; needssop:acknowledgefor SOPs orpolicy:viewfor policies (announcements are acknowledged on the announcement).Audited as
acknowledgement.completed
Announcements
Official messages with audiences, approval before publishing, scheduling, read receipts and required acknowledgements.
GET
/api/v1/announcementsAnnouncements the caller composes or decides on, optionally filtered by
?state=; managers see all. Each item says whether publishing itneeds_approval. Needsannouncement:createorannouncement:publish.POST
/api/v1/announcementsA new draft announcement (title, content, audience, priority, ack and timing fields). Needs
announcement:create; 201 with anETag. 409 when announcements are turned off.Audited as
announcement.createdGET
/api/v1/announcements/feedThe published, unexpired announcements sent to the caller, with read and acknowledgement receipts;
?unread=truekeeps only unread ones. Needsannouncement:view.GET
/api/v1/announcements/{id}One announcement the caller may see (author, publisher once submitted, or recipient), with an
ETag. Anyone else gets 404.PATCH
/api/v1/announcements/{id}Replaces a draft's content; author with
announcement:create, or a manager. OptionalIf-Match: "<revision>"(412 if stale); 409 unless the announcement is a draft.Audited as
announcement.editedPOST
/api/v1/announcements/{id}/submitSends the author's draft for approval; approvers are notified when the workspace's approval rule applies to its audience. 409 unless it is a draft.
Audited as
announcement.submittedPOST
/api/v1/announcements/{id}/approveApproves a pending announcement and publishes it now, or schedules it for
publish_at. Needsannouncement:publish; 403sod_violationif the approver is the author.Audited as
announcement.approved,announcement.published,announcement.rejected,announcement.scheduled,campaign.activated,campaign.createdPOST
/api/v1/announcements/{id}/rejectReturns a pending announcement to draft with a required
comment(422 if empty). Needsannouncement:publish; 409 unless it is pending approval.POST
/api/v1/announcements/{id}/publishPublishes a draft now, or schedules it for its
publish_at, when no approval applies (409 otherwise). Author holdingannouncement:publish, or a manager; 422 if expired.Audited as
announcement.archived,announcement.published,announcement.read,announcement.scheduled,campaign.activated,campaign.closed,campaign.createdPOST
/api/v1/announcements/{id}/archiveWithdraws a scheduled or published announcement with a
reasonand closes its acknowledgement campaign. Needsannouncement:publishor authorship; 409 otherwise.POST
/api/v1/announcements/{id}/readsRecords that the caller read it (first read only; repeats change nothing) and returns the receipt. Needs
announcement:view.POST
/api/v1/announcements/{id}/acksAcknowledges the announcement and completes the caller's campaign assignment with it: one acknowledgement, one audit record (
announcement.acknowledged, citing the assignment).Audited as
announcement.acknowledgedGET
/api/v1/announcements/{id}/analyticsReach, read and acknowledgement counts, overall and by department. Author with
announcement:create, orannouncement:manage.
Requests
Request types you may start, starting a request, your and all requests, request details with steps, timeline and why each step went to whom, comments and watching.
GET
/api/v1/request-typesThe request types the caller may start (enabled in this workspace, and the caller is in the type's audience), with their start forms priced in the workspace currency.
?scope=alllists every built-in withenabledandaudience, for Settings › Requests (workspace:settings.view).GET
/api/v1/requestsRequests by
scope:mine(default,request:view_own) orall(request:view_all), optionally filtered bystatus.POST
/api/v1/requestsStarts a request of
typewithinputanswers (201, withLocation). Requires anIdempotency-Key(a repeat replays the first response; 409 if reused for another body). Needsrequest:start.Audited as
instance.started,request.startedPOST
/api/v1/requests/preview"Who approves this" before sending (
request:start): a dry run of the routing for the answers so far. A read: nothing is written, nothing is audited, the transaction rolls back.GET
/api/v1/requests/{id}One request in full, plus
can_cancel(whether you may cancel it). 404 unless you may see it (view-all, involved, or in your team).POST
/api/v1/requests/{id}/cancelCancels an open request with a
reason. Only the requester or a holder ofrequest:cancel; 404 if you can't see it.Audited as
instance.cancelled,request.cancelledGET
/api/v1/requests/{id}/commentsThe conversation on a request (internal notes hidden from the requester) and its watchers.
POST
/api/v1/requests/{id}/commentsPosts a comment (
request:commentand able to see the request). Each mentioned member must be able to see the request too (422 on/mentionsnaming who can't). Auditedrequest.commented.Audited as
request.commentedPUT
/api/v1/requests/{id}/watchFollows a request: new comments and its outcome reach the caller. Audited
request.watched.Audited as
request.watchedDELETE
/api/v1/requests/{id}/watchStops following a request. Audited
request.unwatched.Audited as
request.unwatched
My work
Your approvals, tasks and acknowledgements: decide, reassign and delegate work items, and team workload for managers.
GET
/api/v1/workWork items by
state:open(default) anddoneare yours (work:view_assigned);unassignedandoverdueare workspace-wide and needwork:reassign.GET
/api/v1/work/workloadWorkload per person:
scope=team(default) is the caller's reporting line, for a manager in the directory orwork:view_team;scope=allis everyone and needs workspace oversight.GET
/api/v1/work/workload/{member}The open steps one person holds: visible for someone in the caller's reporting line, or anyone with workspace oversight. Others get 404.
GET
/api/v1/operations/incidentsTechnical incidents:
monitoring:view_dashboardsorrequest:retry.POST
/api/v1/operations/incidents/{source}/{id}/retryRuns an incident again (audited
incident.retried, a reason required).Audited as
incident.retriedPOST
/api/v1/operations/incidents/{source}/{id}/dismissGives up on an incident (audited
incident.dismissed, a reason required).Audited as
incident.dismissedPOST
/api/v1/work/{id}/decisionsRecords your decision (
outcome,comment,fields,files). RequiresIf-Matchwith the item's revision (428 without) andwork:complete; 409 when already decided. An optionalIdempotency-Keyreplays the first response.Audited as
instance.advanced,instance.completed,work_item.decided,work_item.reassignedPOST
/api/v1/work/{id}/reassignMoves an open step to one member (admin oversight).
Idempotency-Keyoptional: a replay of the same key returns the first answer.POST
/api/v1/work/{id}/delegateHands a step the caller holds to a colleague. Separation of duties is re-checked (422
sod_excludedon/membership_id); auditedwork_item.delegated.
Processes (Guided Studio)
Design processes: templates, drafts saved with If-Match, validation in plain language, test runs, who a step will go to, and publishing.
GET
/api/v1/processesEvery process in the workspace, with its draft and published versions.
POST
/api/v1/processesA new process with its first draft from a template.
Audited as
artifact.createdGET
/api/v1/process-templatesA blank process and every built-in request type.
POST
/api/v1/processes/validateThe problems publishing would report, in plain language.
POST
/api/v1/processes/test-runWhat a draft does for these answers and choices, worked out in memory (nothing is stored, nobody is told).
POST
/api/v1/processes/whoWho each candidate of a step reaches in the directory today.
GET
/api/v1/processes/{id}GET /processes/{id}.PUT
/api/v1/processes/{id}/draftPUT /processes/{id}/draftwithIf-Match: "<revision>": saves the open draft, or opens a new draft from the published version first (then If-Match is not needed).Audited as
version.approved,version.created,version.edited,version.published,version.submitted,work_item.delegatedPOST
/api/v1/processes/{id}/publishSubmits the draft and, when no review is needed, publishes it. A process that does not compile is refused with its problems (422
{problems}).
Out of office and delegation
Set and clear out of office, for yourself or (as an admin) someone else, with a delegate who decides on your behalf.
GET
/api/v1/me/out-of-officeYour current out-of-office period and delegate, if any, and
can_set: whether you may change it (work:delegateand the self-service setting). Membership only.PUT
/api/v1/me/out-of-officeSets your out-of-office from
starts_ontoends_on(dates) with adelegateand optionalnote. Needswork:delegate; 403 when self-service is turned off.Audited as
member.ooo_setDELETE
/api/v1/me/out-of-officeClears your out-of-office (204). Same checks as setting it.
Audited as
member.ooo_clearedGET
/api/v1/members/{id}/out-of-officeSomeone's out-of-office. Needs
work:delegateand eitherwork:reassignover that person or being their manager; 404 if they are not in the workspace.PUT
/api/v1/members/{id}/out-of-officeSets someone's out-of-office (
starts_on,ends_on,delegate,note). Needswork:delegateand eitherwork:reassignor being their manager.Audited as
member.ooo_setDELETE
/api/v1/members/{id}/out-of-officeClears someone's out-of-office (204). Needs
work:delegateand eitherwork:reassignor being their manager.Audited as
member.ooo_cleared
Files
Resumable uploads, virus scanning, previews and short-lived download links.
GET
/api/v1/filesThe workspace Files view (
file:view_all), or the caller's own uploads.POST
/api/v1/filesStarts a resumable upload from
name,sizeand optionalcontent_type(file:upload). 201 with the file and thechunk_sizeto send it in.GET
/api/v1/files/usageStorage usage for the workspace Files view (
file:view_all).GET
/api/v1/files/orphansCompleted files nothing links to, older than
files.orphan_purge_after(file:view_all).POST
/api/v1/files/orphans/purgeDeletes every orphaned file and returns how many (
file:delete).Audited as
file.orphans_purgedPOST
/api/v1/files/retentionBulk retention change (E2E-R1-12): sets or clears the class of the chosen files, with a reason.
Audited as
file.retention_changedGET
/api/v1/files/{id}One file and the records it is linked to, for anyone who may see it (its uploader,
file:view_all, or a reader of what it is attached to); otherwise 404.DELETE
/api/v1/files/{id}Deletes a file (204). Uploaders may delete their own unattached files; anything else needs
file:delete. Your own file attached to a record without it is 409file_linked.PUT
/api/v1/files/{id}/contentOne chunk at
offset(raw bytes). Resume by readingreceivedfromGET /files/{id}.POST
/api/v1/files/{id}/completeFinishes the caller's own upload once every byte has arrived; the file is hashed, type-sniffed and scanned. 409 when the upload is not open or bytes are still missing.
Audited as
file.deleted,file.quarantined,file.rejected,file.scan_failed,file.uploadedGET
/api/v1/files/{id}/download-urlA signed, single-member download link valid for 5 minutes.
GET
/api/v1/files/{id}/preview-urlA signed preview link for a clean previewable file (
kind: image|pdf|docx|xlsx|csv), orkind: noneand no URL. Same permission rules asdownload-url.POST
/api/v1/files/{id}/linksAttaches a file the caller can see to a draft document version (
object_type: artifact_version,object_id); needsedit_drafton its kind. 204; 409 past draft.Audited as
file.linkedDELETE
/api/v1/files/{id}/links/{object_type}/{object_id}Detaches a file from a draft document version (
edit_drafton its kind). 204; 409 once the version is past draft.Audited as
file.unlinkedGET
/api/v1/versions/{id}/attachmentsFiles attached to a document version (readers of the version see them).
GET
/api/v1/files/download/{token}Serves a file for a valid token; re-checks membership, permission and file state every time.
GET
/api/v1/files/preview/{token}Serves a previewable file for a valid preview token, re-authorized on every request, under a strict sandboxing CSP. Anything not on the preview allow-list is 415.
Notifications
Your in-app notifications and how you are notified.
GET
/api/v1/notificationsYour in-app notifications, newest first, with the unread count. Query:
unread=truefor unread only,limit(default 50).POST
/api/v1/notifications/read-allMarks all your notifications read; returns how many were marked.
POST
/api/v1/notifications/{id}/readMarks one of your notifications read (204).
GET
/api/v1/me/notification-preferencesYour delivery preferences (digests, quiet hours), with your overrides applied over the workspace defaults.
PUT
/api/v1/me/notification-preferencesReplaces the caller's overrides;
nullfields follow the workspace defaults. Audited.Audited as
notification_preferences.changed
Profile
Your name, time zone and language.
GET
/api/v1/me/profileYour email, display name, time zone and language, plus the languages offered. Shared by every workspace you belong to.
PATCH
/api/v1/me/profileChanges any of
display_name,timezone(IANA name) andlocale; omitted fields are kept. 422 for an invalid value. Audited; returns the updated profile.Audited as
user.profile_updated
Saved views and exports
Saved table views (personal, shared, by role) and recorded CSV and XLSX exports.
GET
/api/v1/viewsMy views and the views shared with me for a list (mine first, then by name).
POST
/api/v1/viewsSaves a view of a list (
list,name,state), private or shared with everyone (shared) or one role (shared_role);is_defaultmakes it your default for that list. 201.Audited as
view.createdGET
/api/v1/views/rolesThe roles a view can be shared with.
PATCH
/api/v1/views/{id}Only the owner changes a view (shared views included).
Audited as
view.updatedDELETE
/api/v1/views/{id}Deletes one of your saved views (204). 403 for a shared view you don't own.
Audited as
view.deletedPOST
/api/v1/exportsRecords that the member exported a grid view. CSV: the browser builds the file from rows it was already allowed to see, and gets 204. XLSX: the browser sends exactly those cells and gets the workbook back; text cells stay text (no formulas).
Audited as
data.exported
Settings
Workspace settings with layered defaults, department overrides, floors and configuration profiles.
GET
/api/v1/brandingThe workspace look for every member: the accent with its contrast-safe shades, the default theme, the logo and the effective terminology (every term, workspace label or product default). Readable without settings permissions: it is what the UI paints.
PATCH
/api/v1/workspaceRenames the workspace (owners and admins:
workspace:settings.manage). Recorded on the workspace chain, and on the system chain by the platform service.Audited as
workspace.renamedGET
/api/v1/branding/logoThe workspace logo for every member: the image bytes (metadata stripped, as previews), served inline only as an image, never sniffed, never cached across workspaces.
GET
/api/v1/settingsThe effective value of every workspace setting (
workspace:settings.view).GET
/api/v1/settings/effectiveThe explainer: final value and every contributing layer.
GET
/api/v1/settings/{key}One setting's effective value and the layers behind it, with its revision as the ETag (
workspace:settings.view); 404 for an unknown key.PUT
/api/v1/settings/{key}Sets a workspace setting (
value, optionalreason) under the key's own permission (some also need step-up); optionalIf-Match: "<revision>"(412 if stale), 422 if invalid.Audited as
setting.changedGET
/api/v1/settings/{key}/historyThe last 100 changes to one setting, newest first (
workspace:settings.view).GET
/api/v1/settings/departments/{id}Department-scopable keys resolved for one department, with its own overrides.
PUT
/api/v1/settings/departments/{id}/{key}Sets a department override (
value, optionalreason) under the key's permission on that department; optionalIf-Match(412 if stale), 422 if not scopable.Audited as
setting.override_setDELETE
/api/v1/settings/departments/{id}/{key}Removes a department's override so the workspace value applies again; optional
If-Match(412 if stale), 404 if there is no override.Audited as
setting.override_clearedGET
/api/v1/settings/profile/planPreview of a profile switch: every key that would change. The ETag is the plan basis.
POST
/api/v1/settings/profile/applyApplies the plan whose basis is in
If-Match(required): step-up, a reason, and the permission of every key it changes. One audit event (settings.profile_switched).Audited as
settings.profile_switched
Audit trail
The hash-chained audit trail: search events, object timelines, chain verification, saved queries and exports.
GET
/api/v1/audit/eventsAudit events filtered by time,
actorormember, action, category, object and result, in keyset pages (page[size],page[cursor]).audit:viewsees the workspace chain;audit:view_ownsees only the caller's own events.GET
/api/v1/audit/objects/{object_type}/{id}/timelineEvery event for one object, oldest first.
artifactspans all of the artifact's versions (the library records lifecycle events per version).GET
/api/v1/audit/verifyRecomputes the workspace chain and reports the first sequence that does not verify.
GET
/api/v1/audit/saved-queriesThe caller's saved audit queries. Needs
audit:vieworaudit:view_own.POST
/api/v1/audit/saved-queriesSaves a named set of audit
filtersfor the caller; 201. Needsaudit:vieworaudit:view_own.Audited as
audit.query_savedDELETE
/api/v1/audit/saved-queries/{id}Deletes one of the caller's saved audit queries; 204 (404 if not theirs). Needs
audit:vieworaudit:view_own.Audited as
audit.query_deletedGET
/api/v1/audit/exportsThe caller's background exports, newest first.
POST
/api/v1/audit/exportsSynchronous export of up to 10 000 events (newest first).
Procera-Export-Truncated: truemeans more matched; narrow the filters. Larger exports move to the export job later.Audited as
audit.export_requested,audit.exportedGET
/api/v1/audit/exports/{id}The state of one of the caller's background audit exports (rows, file, error). Needs
audit:export; 404 for anyone else's.POST
/api/v1/audit/queryPOST /audit/query: AND/OR filter tree, sorted on the chain, keyset pages.
Encryption keys
The workspace's encryption keys and their rotation.
GET
/api/v1/security/encryptionThe active key version, every key version with how many values it still wraps, and how many await rewrap. Needs
workspace:settings.view.POST
/api/v1/security/encryption/rotateRotates to a new key version; existing values are rewrapped in the background. Needs
workspace:settings.manage, a recent sign-in and areason(422 if empty).Audited as
key.rotated
Templates
The template gallery.
GET
/api/v1/templatesThe packs, what each creates and, for members who may install it, which of its documents already exist in the workspace (by key).
POST
/api/v1/templates/{key}/installCreates a pack's documents as drafts (
documentsto pick some,on_conflictskiporcopy,campaignfor a suggested plan). 201 when anything was created. Needstemplate:installand<kind>:createfor each kind installed.Audited as
artifact.created,department.created,template.installed
Password recovery
Forgotten passwords, reset links, changing your password and admin account controls.
POST
/api/v1/auth/password/forgotAlways 202 with the same body, whether or not the account exists (no enumeration). The email is queued in the background so the answer takes the same time either way.
GET
/api/v1/auth/password/reset/checkWhether a reset link still works, so the page can say so before the person types a password.
POST
/api/v1/auth/password/resetSets a new password from a reset link (
token,password); 204, and the account owner is emailed. An invalid, expired or used link is refused with 400. Rate-limited per IP.Audited as
password.resetPOST
/api/v1/auth/password/expiredAfter
password_change_required: sets the new password and continues the sign-in (two-step verification next when the account has it).Audited as
login.password_ok_mfa_required,login.succeeded,password.changedPOST
/api/v1/me/passwordAccount › Security: change the password. Other sessions end; this one continues with the returned access token.
POST
/api/v1/members/{id}/security/reset-linkEmails the member a password reset link. Needs
member:security.manageon the member, a recent step-up and areason; 204, 409 if deactivated.Audited as
member.mfa_reset,member.password_change_required,member.password_reset_link_sent,member.signed_out_everywhere,mfa.reset,password.change_required,password.reset_requested,sessions.revoked_allPOST
/api/v1/members/{id}/security/require-password-changeMakes the member choose a new password at next sign-in (
member:security.manage, step-up,reason); 204. 409 if deactivated or used in other workspaces.POST
/api/v1/members/{id}/security/sign-out-everywhereEnds all of the member's sessions (
member:security.manage, step-up,reason); 204. 409 if deactivated or used in other workspaces.POST
/api/v1/members/{id}/security/reset-mfaRemoves the member's two-step verification (
member:security.manage, step-up,reason); 204. 409 if deactivated or used in other workspaces.
System plane: workspaces
For system administrators: create, rename, suspend, restore and schedule deletion of workspaces, and quotas. Never reads workspace content.
POST
/sysapi/v1/bootstrapOne-time creation of the first system owner from the bootstrap
token, withemail,display_nameandpassword(201). 401 for a bad or used token, 409 once bootstrapped.Audited as
platform.bootstrapped,user.createdGET
/sysapi/v1/meYour user id and system roles. Like every system route, needs a system role and MFA.
GET
/sysapi/v1/workspacesThe console's workspace grid (
?state=&profile=&q=): metadata, quotas and usage counts.POST
/sysapi/v1/workspacesCreates a workspace (201, with
LocationandETag); 409 if the slug is taken. Needssystem.ownerorsystem.admin.Audited as
member.invited,workspace.createdGET
/sysapi/v1/workspaces/{id}One workspace with its quotas and usage counts, as the console lists it, with an
ETagof its revision. Any system role.PATCH
/sysapi/v1/workspaces/{id}Renames a workspace (
name). HonoursIf-Match(412 when stale). Needssystem.ownerorsystem.admin.Audited as
workspace.renamedPOST
/sysapi/v1/workspaces/{id}/suspendSuspends a workspace,
moderead_onlyorlocked, with areason. Needssystem.owner/system.adminand a recent sign-in;If-Matchhonoured (412).Audited as
workspace.suspendedPOST
/sysapi/v1/workspaces/{id}/restoreReturns a suspended or deletion-scheduled workspace to active (409 otherwise). Needs
system.owner/system.adminand a recent sign-in;If-Matchhonoured (412).Audited as
workspace.restoredPOST
/sysapi/v1/workspaces/{id}/schedule-deletionSchedules deletion after
grace_days, with areason. Needssystem.owner/system.adminand a recent sign-in;If-Matchhonoured (412).Audited as
workspace.deletion_scheduledPUT
/sysapi/v1/workspaces/{id}/quotasReplaces a workspace's quotas; returns the workspace with usage. Needs
system.ownerorsystem.adminand a recent sign-in.Audited as
workspace.quotas_changedPOST
/sysapi/v1/workspaces/{id}/owner-invitation/linkA fresh one-time link to the owner's pending invitation (for when email isn't set up). Handing over a credential needs a recent authentication; the earlier link stops working.
Audited as
member.invitation_link_copied,platform.floor_changed,workspace.owner_invitation_link_copiedGET
/sysapi/v1/settingsThe platform floors every workspace's settings are held to. Any system role.
PUT
/sysapi/v1/settings/{key}Sets a platform floor. Raising it never rewrites workspace values; looser ones resolve as clamped. Floors bind every workspace's security, so this needs a recent authentication (step-up) and, when
If-Matchcarries the listed revision, refuses a stale edit (412).
System plane: console
For system administrators: platform health and configuration.
GET
/sysapi/v1/quota-defaultsThe quota bundle each configuration profile starts with. Any system role.
PUT
/sysapi/v1/quota-defaults/{profile}Replaces one profile's default quotas for new workspaces. Needs
system.ownerorsystem.adminand a recent sign-in;If-Matchhonoured (412).Audited as
platform.quota_defaults_changedGET
/sysapi/v1/healthPlatform health.
statusisok,degraded(something needs a look) ordown.GET
/sysapi/v1/system-audit/eventsThe system chain through the shared explorer, newest first. System administrators' names are resolved; every other actor keeps its pseudonymous subject reference.
GET
/sysapi/v1/system-audit/verifyRecomputes the system chain and reports the first sequence that does not verify.
System plane: email
For system administrators: the outgoing email (SMTP) settings.
GET
/sysapi/v1/emailThe email relay in use (
source: environment, database or none), the stored settings without the password, and the mail queue, with anETag. Needs owner, admin or auditor.PUT
/sysapi/v1/emailSaves the SMTP relay settings. Requires
If-Match(428 without;"0"when none stored), a recent sign-in andsystem.owner/system.admin; 409 when set by the environment.Audited as
platform.email_changedPOST
/sysapi/v1/email/testSends one test message to
tothrough the relay in use and returns whether it was sent (or a safe error category); audited either way. 409 if email is not set up.Audited as
platform.email_testedGET
/sysapi/v1/platformRead-only deployment facts: nothing here is configurable from the console yet.
Hr
HR time and attendance, slice 1: work locations, holiday calendars and holidays (read directory:view, change calendar:manage), a member's HR record (change directory:manage) and a person's own holidays.
GET
/api/v1/work-locationsLocations with their time zone, work week, holiday calendar and active member count (
directory:view).POST
/api/v1/work-locationsA new location (
calendar:manage). 201. Auditedwork_location.created.Audited as
work_location.createdGET
/api/v1/work-locations/{id}One location, with an
ETagof its revision (directory:view).PATCH
/api/v1/work-locations/{id}PATCH /work-locations/{id}(the full location, as for create, plusarchived): changes it (calendar:manage; honoursIf-Match); a rename renames it on members' profiles; a location people work at can't be archived (409). Auditedwork_location.updated.Audited as
work_location.updatedGET
/api/v1/holiday-calendarsCalendars with the locations using them and the years they have holidays in (
directory:view).POST
/api/v1/holiday-calendarsA new calendar, empty or a copy of another's holidays (
calendar:manage). 201. Auditedholiday_calendar.created.Audited as
holiday_calendar.createdGET
/api/v1/holiday-calendars/{id}One calendar, with an
ETagof its revision (directory:view).PATCH
/api/v1/holiday-calendars/{id}Renames a calendar (
calendar:manage; honoursIf-Match). Auditedholiday_calendar.updated.Audited as
holiday_calendar.updatedDELETE
/api/v1/holiday-calendars/{id}Deletes a calendar and its holidays when no location uses it (409 otherwise;
calendar:manage). 204. Auditedholiday_calendar.deleted.Audited as
holiday_calendar.deletedGET
/api/v1/holiday-calendars/{id}/holidaysThe year's holidays
[{date, name, optional}](directory:view).PUT
/api/v1/holiday-calendars/{id}/holidays/{date}Adds the holiday on that date or renames it (
calendar:manage). 201 when new, 200 when changed. Auditedholiday.set.Audited as
holiday.setDELETE
/api/v1/holiday-calendars/{id}/holidays/{date}Removes it (
calendar:manage). 204. Auditedholiday.removed.Audited as
holiday.removedPOST
/api/v1/holiday-calendars/{id}/importImports CSV (
date,name[,optional]) or iCal text, at most 400 holidays and 1 MB (calendar:manage) →{added, updated, skipped: [{line, text, reason}]}. Auditedholiday_calendar.imported.Audited as
holiday_calendar.importedPOST
/api/v1/holiday-calendars/{id}/copy-yearCopies a year's holidays to the same month and day of another year, skipping dates already taken (
calendar:manage) → as import. Auditedholiday_calendar.year_copied.Audited as
holiday_calendar.year_copiedGET
/api/v1/members/{id}/hr{employee_no, employment_type, work_location_id, start_date, probation_end}(directory:view).PUT
/api/v1/members/{id}/hrPUT /members/{id}/hr(the whole record): sets it (directory:manage); the work location also becomes the profile's location; 409 for a duplicate employee number. Auditedmember.hr_updated.Audited as
member.hr_updatedGET
/api/v1/me/holidaysThe caller's work location (or
null) and its holidays in the range (default: today and the next 366 days; at most 2 years).GET
/api/v1/leave-typesThe workspace's leave types (
directory:view).POST
/api/v1/leave-typesPOST /leave-types {key?, name, colour?, paid?, limited?, sensitive?, half_days?, needs_attachment_after_days?, min_notice_days?, max_consecutive_days?, negative_limit_days?, counts_non_working_days?, optional_holidays_only?}→ 201 (time_off:manage_policies). Auditedleave_type.created.Audited as
leave_type.createdPOST
/api/v1/leave-types/defaultsFor a workspace without leave types, the common ones (annual, sick, casual, optional holiday, unpaid) and a "Standard" policy for everyone → 201
{types, policy}(409 when types exist;time_off:manage_policies). Auditedleave_type.defaults_created.Audited as
leave_type.defaults_createdPATCH
/api/v1/leave-types/{id}PATCH /leave-types/{id}(the whole type, plusarchived; the key never changes): honoursIf-Match(time_off:manage_policies). Auditedleave_type.updated.Audited as
leave_type.updatedGET
/api/v1/leave-policiesPolicies with their rules and how many people each applies to (
time_off:manage_policiesortime_off:view_all).POST
/api/v1/leave-policiesPOST /leave-policies {name, audience, priority?, year_start_month?, rules: [{leave_type_id, yearly_days, accrual upfront|monthly, prorate?, probation_waits?, carry_over_max_days?, carry_over_expiry_months?}]}→ 201 (time_off:manage_policies). Auditedleave_policy.created.Audited as
leave_policy.createdGET
/api/v1/leave-policies/{id}One policy with an
ETag(as the list).PATCH
/api/v1/leave-policies/{id}PATCH /leave-policies/{id}(the whole policy, plusarchived): honoursIf-Match; new rules apply from the next grant or accrual (time_off:manage_policies). Auditedleave_policy.updated.Audited as
leave_policy.updatedGET
/api/v1/leave-policies/{id}/membersWho it applies to now
{count, items: [{id, name}]}(25 at most; as the list).PUT
/api/v1/members/{id}/leave-policyGives one person a policy regardless of audiences, or goes back to audiences (
time_off:manage_policies) →{policy: {id, name, via}}. Auditedleave_policy.assigned.Audited as
leave_policy.assignedGET
/api/v1/me/time-offMy policy and balances for the leave year containing
on(default today): per type{leave_type, year_start, year_end, yearly_days, accrual, granted, carried, taken, pending, adjusted, expired, available, entries}, and my leaverequests. Procera writes due grants first.GET
/api/v1/members/{id}/time-offSomeone's policy and balances, as
/me/time-off(themselves, ortime_off:view_all).POST
/api/v1/members/{id}/time-off/adjustmentsA correction in the current leave year (
time_off:adjust_balances, step-up) → 201 entry. Auditedtime_off.adjusted.Audited as
time_off.adjustedGET
/api/v1/time-off/balancesEveryone's current-year balances by type
{types, items: [{id, name, email, policy, balances: {type_id: {available, taken, pending}}}]}(time_off:view_all).POST
/api/v1/time-off/quoteHow many days a leave request would take for me, date by date, my balance before and after, and any problems (
[{field, code, message}]) the request would be refused for. Changes nothing.GET
/api/v1/team-calendarWho's out between two dates (≤ 92 days) →
{from, to, people [{id, name, title, department, location_id, me}], absences [{membership_id, start_date, start_half, end_date, end_half, state, label, colour, request_id?, days?}], holidays [{location_id, date, name, optional}], work_weeks}.team(default) is me, my manager, my manager's other reports and my reports;department/locationdefault to mine. Colleagues see approved time off as "Out"; the person, their manager chain and HR (time_off:view_all) see the type and pending requests.everyoneneedstime_off:view_all.GET
/api/v1/org-chartEveryone active with their manager, title, department and location, and whether they're out today (approved leave, never why) →
{items: [{id, name, title, department, location, manager_id, out_today}]}(directory:view).
Signing
Employee e-signing: envelopes from a PDF, recipients, fields, send and void for senders (document:send_for_signature; everyone's with document:view_all, voiding anyone's with document:void), and the signing ceremony for recipients: open it, sign (consent, a typed or drawn signature, their fields) or decline. strong envelopes need a recent sign-in to sign. API tokens never reach /signing/*. The document is served from here.
GET
/api/v1/envelopesEnvelopes I sent (default), or every envelope with
document:view_all; newest first, at most 500, without fields.POST
/api/v1/envelopesA draft envelope for an uploaded, clean PDF (
title, optionalmessage,file_id,ordersequential|parallel,modesimple|strong,expires_in_days1–365, default 30,bulkto send a copy to each person in a group;document:send_for_signature). 201 with the envelope; 422 for a PDF that can't be signed.Audited as
envelope.created,file.linkedGET
/api/v1/envelopes/{id}An envelope with its recipients and fields, for its sender, its recipients (once sent) or
document:view_all.PUT
/api/v1/envelopes/{id}/recipientsReplaces a draft's recipients in signing order (
[{membership_id, role: signer|cc}], at most 50, active members). HonoursIf-Match.Audited as
envelope.recipients_setPUT
/api/v1/envelopes/{id}/fieldsReplaces a draft's fields (
kindsignature|initials|date_signed| name|text|checkbox,recipient_idof a signer,page,x/y/w/has fractions of the page from its top-left corner,required,label). HonoursIf-Match.Audited as
envelope.fields_setPOST
/api/v1/envelopes/{id}/sendSends a draft (every signer needs a signature field); the document and fields are frozen and the signers whose turn it is are notified. Honours
If-Match.Audited as
envelope.sentPOST
/api/v1/envelopes/{id}/voidCancels a sent envelope with a
reason(its sender, or anyone withdocument:void); signers who were asked are told.Audited as
envelope.voidedPOST
/api/v1/envelopes/{id}/send-bulkSends a bulk draft to everyone in
audience(all,departments,groups,roles,locations): one copy each, signed by that person, grouped in a batch (at most 2,000 people). HonoursIf-Match. 201 with the batch.Audited as
envelope.bulk_sentPOST
/api/v1/envelopes/{id}/remindReminds the signer whose turn it is now (its sender; at most once an hour per signer). Returns
{reminded}.Audited as
envelope.remindedGET
/api/v1/envelope-batchesGroup sends I made (or everyone's with
document:view_all), newest first, with their counts.GET
/api/v1/envelope-batches/{id}A group send with each person's progress (its sender or
document:view_all):counts {total, signed, waiting, viewed, declined, cancelled, expired},rows.POST
/api/v1/envelope-batches/{id}/remindReminds everyone in a group send who hasn't signed yet (its sender; at most once an hour each). Returns
{reminded}.Audited as
envelope.batch_remindedPOST
/api/v1/envelope-batches/{id}/voidCancels every copy still waiting for a signature, with a
reason(its sender, ordocument:void). Returns{cancelled}.Audited as
envelope.batch_voidedGET
/api/v1/envelopes/{id}/documentThe PDF (
application/pdf): the original the signers review, or the signed copy with its certificate once everyone has signed (409 before).GET
/api/v1/me/signaturesThe envelopes I'm on:
to_signwhen it's my turn, then the rest (waiting, signed, declined, completed copies).GET
/api/v1/signing/{recipient}The signing ceremony for my recipient row: the envelope, my fields, whether it's my turn, everyone's progress, and the consent text. The first open is recorded.
POST
/api/v1/signing/{recipient}/signSigns on my turn with
document_hash(the one shown),consent: true,adopted {kind: typed|drawn, text, image?}andvaluesfor my text and checkbox fields.strongenvelopes need a recent sign-in (401step_up_required). The last signature completes the envelope.Audited as
envelope.completed,envelope.declined,envelope.signed,file.linked,file.uploadedPOST
/api/v1/signing/{recipient}/declineDeclines with a
reason; the envelope ends for everyone and the sender is told.
Sso
Single sign-on: finding the workspaces whose provider vouches for an email, starting a sign-in (redirect to the provider) and finishing it (the provider redirects back; a session opens in that workspace and the browser returns to the app), and the workspace's provider settings for admins (workspace:settings.manage, step-up to change).
POST
/api/v1/auth/sso/discoverThe workspaces whose identity provider vouches for this email's domain (
{items: [{id, slug, name}]}); empty when none do. No session needed.GET
/api/v1/auth/sso/startRedirects (303) to the workspace's identity provider with a one-time state, a nonce and a PKCE challenge. 404 when the workspace has no provider.
GET
/api/v1/auth/sso/callbackThe provider's redirect. Verifies the sign-in, opens a session in the workspace (refresh cookie) and redirects (303) into the app; any problem redirects to the sign-in page with
sso_error(refusals are logged). Auditedlogin.sso_succeeded.GET
/api/v1/ssoThe workspace's provider settings (never the secret:
has_secret), ornull(workspace:settings.view).PUT
/api/v1/ssoSets the provider (
issuer,client_id,client_secret(absent keeps it, empty clears it),domains,enabled,required); the issuer's discovery document must answer first (workspace:settings.manage, step-up; honoursIf-Match).Audited as
sso.configuredDELETE
/api/v1/ssoRemoves the provider; everyone signs in with passwords again (
workspace:settings.manage, step-up). 204.Audited as
sso.removed