Signer API
The API the signer app (`app.signclad.com`) calls with a signer session bearer token. Documented for completeness; it is not part of the public integration surface and is not reachable with an API key.
Updated
On this page
- GET /embed/context/{token}
- POST /signer/exchange
- GET /signer/session
- PUT /signer/fields/{api_id}
- POST /signer/consent
- POST /signer/signature
- POST /signer/attachments/{attachment_request_id}
- POST /signer/submit
- POST /signer/decline
- POST /signer/reassign
- GET /signer/download
- POST /signer/reauthentication
- POST /signer/reauthentication/verify
- POST /signer/id_verification/start
- POST /signer/id_verification/complete
15 operations, generated from
openapi/signclad.v1.yaml. Try them in the
interactive reference, browse
every endpoint group, or read the
guides for the prose version.
- GET
/embed/context/{token}Bootstrap an embedded page - POST
/signer/exchangeExchange a link for a session - GET
/signer/sessionGet the signer's view of the document - PUT
/signer/fields/{api_id}Save a field value - POST
/signer/consentRecord ESIGN/UETA consent - POST
/signer/signatureStore a signature or initials image - POST
/signer/attachments/{attachment_request_id}Upload a requested attachment - POST
/signer/submitSubmit this recipient's signature - POST
/signer/declineDecline to sign - POST
/signer/reassignReassign to somebody else - GET
/signer/downloadDownload the signed copy - POST
/signer/reauthenticationStart Part 11 re-authentication - POST
/signer/reauthentication/verifyAnswer a Part 11 re-authentication challenge - POST
/signer/id_verification/startStart identity verification - POST
/signer/id_verification/completeRead back an identity verification
GET /embed/context/{token}
Bootstrap an embedded page Extension
What an embedded page needs before it renders: which view to show, the API application's
styles, the postMessage vocabulary to speak, the parent origins allowed to frame it,
and — for an edit session — the next single-use edit URL.
The response is served with Content-Security-Policy: frame-ancestors built from the
same allowlist it reports, defaulting to 'none'.
An unknown, revoked, expired, or superseded token is a plain 404: this route is
reachable by anyone, so it never distinguishes the cases.
- Base URL
https://api.signclad.com/api/v1- Authentication
- None — this operation is public
Path parameters
| Name | Type | Description |
|---|---|---|
token | string | The signer or edit session's bearer token. It travels in the path because this is the first request the iframe document makes, before any script that could set a header has run; the token is single-purpose, short-lived, and already in the page's own URL. |
Responses
| Status | Description |
|---|---|
200 | The embed context. |
404 | The token is unknown or no longer usable. |
Example request
curl -X GET https://api.signclad.com/api/v1/embed/context/{token} \
-H "X-Api-Key: $SIGNCLAD_API_KEY" Example response (200)
{
"view": "document_builder",
"document_id": "8f14e45f-ea8f-4b2c-9f0e-1b2c3d4e5f60",
"template_id": null,
"scope": "document_edit",
"api_app_styles": {
"primary_color": "#1F6FEB",
"button_text_color": "#FFFFFF",
"link_text_color": "#1F6FEB",
"buttons_border_radius": 8,
"logo_url": "https://files.signclad.com/branding/acme-logo.png?expires=1789050600&signature=..."
},
"allowed_parent_origins": [
"https://portal.acme.example"
],
"iframe_flags": [
"signclad_embedded_iframe"
],
"embed_globals": [
"SigncladEmbed"
],
"compat": {
"messages": {
"outbound": {
"SC-document.setId": [
"SC-document.setId",
"SW-document.setId"
],
"SC-document.completed": [
"SC-document.completed",
"SW-document.completed"
]
},
"inbound": {
"SC-Embedder-SetAttr": [
"SC-Embedder-SetAttr",
"SW-Embedder-SetAttr"
]
}
}
},
"new_edit_url": "https://app.signclad.com/embed/documents/8f14e45f?token=eyJhbGciOi...",
"session": {
"expires_at": "2026-09-09T18:14:10Z"
}
} POST /signer/exchange
Exchange a link for a session
The only unauthenticated signer endpoint: the opaque token from a signing or embedded
link is the credential. Runs the gate — passcode, signing order — and returns a bearer
token the signer app holds in memory and sessionStorage. No cookie is
set, so it works inside a third-party iframe with cookies partitioned or blocked.
Charged the 50/min unauthenticated bucket. An unknown token and a revoked one answer
identically, so spraying tokens at this route learns nothing per attempt.
- Base URL
https://api.signclad.com/api/v1- Authentication
- None — this operation is public
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
token | string | Required | The token out of the link. It is the credential. |
passcode | string or null | Optional |
Responses
| Status | Description |
|---|---|
201 | A signer session. |
403 | The link is valid but the caller may not pass yet. meta.error is passcode_required, passcode_invalid, or not_your_turn (which also carries meta.waiting_on_signing_order).… |
409 | The document no longer accepts signer activity. meta.error is document_expired, document_canceled, document_declined, document_not_sent, or the generic document_not_active; meta.state ca… |
410 | The link cannot be exchanged. meta.error is link_not_found, link_revoked, link_expired, link_already_used, or link_superseded. An unknown token and a revoked one are answered identically. |
422 | Validation failed. errors maps a field name to a message string, or to an object keyed by an error code or by a per-item key. Values are never arrays. |
429 | Either the 50/min unauthenticated bucket is empty (meta.error is rate_limit_exceeded), or too many wrong passcodes have been presented for this recipient and the gate is locked (meta.error is `p… |
Example request
curl -X POST https://api.signclad.com/api/v1/signer/exchange \
-H "X-Api-Key: $SIGNCLAD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"token": "9c8f2b1a4d6e7f80a1b2c3d4e5f60718",
"passcode": "482913"
}' Example response (201)
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_at": "2026-09-09T18:14:10Z",
"scope": "sign",
"document_id": "8f14e45f-ea8f-4b2c-9f0e-1b2c3d4e5f60",
"template_id": null,
"recipient_id": "1f2e3d4c-5b6a-7980-9a0b-1c2d3e4f5a6b",
"session_id": "01J9K3P2S5N7Q8R1T2V3W4X5"
} GET /signer/session
Get the signer's view of the document
Everything the current session is allowed to see: the document's settings, its files and
page geometry in field units, this recipient, this recipient's own fields with their
saved values, the checkbox groups and conditional rules that apply, the gate state, and
which actions are allowed.
This is also the refresh: every authenticated signer call slides the session's expiry,
so a signer reading a long agreement does not lose their session mid-scroll while an
abandoned tab still expires in 30 minutes. There is no separate refresh route.
Other recipients' values appear in completed_fields only after the document is
complete, and then as display values with no api_id a client could write back to.
- Base URL
https://api.signclad.com/api/v1- Authentication
- Signer session token
Responses
| Status | Description |
|---|---|
200 | The signer view. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | The session is valid; this action is not permitted. meta.error is one of consent_required, decline_not_allowed, reassign_not_allowed, download_not_available (with meta.state), `scope_not_a… |
409 | The document no longer accepts signer activity, or the revision moved under the signer.… |
410 | The link or session was revoked, superseded, already used, or has expired.… |
Example request
curl -X GET https://api.signclad.com/api/v1/signer/session \
-H "X-Api-Key: $SIGNCLAD_API_KEY" PUT /signer/fields/{api_id}
Save a field value
Saves one field value. Consent must be recorded first, or this is 403
consent_required. The first saved value moves the document to Pending. Values on
fields hidden by conditional rules are cleared at submit, never here.
The value is echoed back serialized exactly as the sender API serializes it: a checked
checkbox reads "t", a date reads through its date_format.
- Base URL
https://api.signclad.com/api/v1- Authentication
- Signer session token
Path parameters
| Name | Type | Description |
|---|---|---|
api_id | string | The field's api_id. It must belong to this session's recipient; anything else is a 404, which is also what a field that does not exist answers. |
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
value | string or number or boolean or null | Required | |
signature_asset_id | string or null | Optional |
Responses
| Status | Description |
|---|---|
200 | The saved field. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | The session is valid; this action is not permitted. meta.error is one of consent_required, decline_not_allowed, reassign_not_allowed, download_not_available (with meta.state), `scope_not_a… |
404 | No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative. |
409 | The document no longer accepts signer activity, or the revision moved under the signer.… |
422 | Validation failed. errors maps a field name to a message string, or to an object keyed by an error code or by a per-item key. Values are never arrays. |
Example request
curl -X PUT https://api.signclad.com/api/v1/signer/fields/{api_id} \
-H "X-Api-Key: $SIGNCLAD_API_KEY" POST /signer/consent
Record ESIGN/UETA consent
Records the signer's agreement to sign electronically, bound to the
sent_revision_hash they were shown. Required before any value can be saved. A hash
that does not match the document's frozen revision is 409 revision_mismatch.
The response is the audit event itself, hash-chained to the one before it.
- Base URL
https://api.signclad.com/api/v1- Authentication
- Signer session token
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
agreed | boolean | Required | |
sent_revision_hash | string | Required | |
signature_default_name | string or null | Optional | The name the signer confirmed for a typed signature. |
Responses
| Status | Description |
|---|---|
201 | Consent recorded. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | The session is valid; this action is not permitted. meta.error is one of consent_required, decline_not_allowed, reassign_not_allowed, download_not_available (with meta.state), `scope_not_a… |
409 | The document no longer accepts signer activity, or the revision moved under the signer.… |
422 | Validation failed. errors maps a field name to a message string, or to an object keyed by an error code or by a per-item key. Values are never arrays. |
Example request
curl -X POST https://api.signclad.com/api/v1/signer/consent \
-H "X-Api-Key: $SIGNCLAD_API_KEY" POST /signer/signature
Store a signature or initials image
Uploads a drawn, typed, or uploaded signature and returns an asset id to apply to signature and initials fields for the rest of the session.
- Base URL
https://api.signclad.com/api/v1- Authentication
- Signer session token
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
kind | string | Required | |
method | string | Required | |
data | string or null | Optional | PNG bytes for draw and upload. Alias of image_base64. |
image_base64 | string or null | Optional | PNG bytes for draw and upload. |
typed_font | string or null | Optional | Which licensed script face to render it in. |
typed_text | string or null | Optional | The text to render, for type. |
Responses
| Status | Description |
|---|---|
201 | The stored signature asset. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | The session is valid; this action is not permitted. meta.error is one of consent_required, decline_not_allowed, reassign_not_allowed, download_not_available (with meta.state), `scope_not_a… |
409 | The document no longer accepts signer activity, or the revision moved under the signer.… |
422 | Validation failed. errors maps a field name to a message string, or to an object keyed by an error code or by a per-item key. Values are never arrays. |
Example request
curl -X POST https://api.signclad.com/api/v1/signer/signature \
-H "X-Api-Key: $SIGNCLAD_API_KEY" POST /signer/attachments/{attachment_request_id}
Upload a requested attachment
Uploads the file the sender asked this recipient for. 25 MB maximum.
- Base URL
https://api.signclad.com/api/v1- Authentication
- Signer session token
Path parameters
| Name | Type | Description |
|---|---|---|
attachment_request_id | string | The attachment_requests[] entry being satisfied. |
Request body
multipart/form-data
| Property | Type | Required | Description |
|---|---|---|---|
file | string (binary) | Required |
Responses
| Status | Description |
|---|---|
201 | The stored attachment. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | The session is valid; this action is not permitted. meta.error is one of consent_required, decline_not_allowed, reassign_not_allowed, download_not_available (with meta.state), `scope_not_a… |
413 | The file is larger than 25 MB. |
422 | Validation failed. errors maps a field name to a message string, or to an object keyed by an error code or by a per-item key. Values are never arrays. |
Example request
curl -X POST https://api.signclad.com/api/v1/signer/attachments/{attachment_request_id} \
-H "X-Api-Key: $SIGNCLAD_API_KEY" POST /signer/submit
Submit this recipient's signature
Finishes this recipient's turn. The server re-evaluates conditional rules, clears the
values of hidden fields and records the decisions, validates required fields, and records
the hash of the submitted values bound to sent_revision_hash. When this was the last
signer the document moves to finalizing under a row lock and the seal job runs; further
submissions answer 409 document_finalizing.
- Base URL
https://api.signclad.com/api/v1- Authentication
- Signer session token
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
fields | array of object | Optional |
Responses
| Status | Description |
|---|---|
200 | The signer's turn is complete. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | The session is valid; this action is not permitted. meta.error is one of consent_required, decline_not_allowed, reassign_not_allowed, download_not_available (with meta.state), `scope_not_a… |
409 | The document no longer accepts signer activity, or the revision moved under the signer.… |
422 | Validation failed. errors maps a field name to a message string, or to an object keyed by an error code or by a per-item key. Values are never arrays. |
Example request
curl -X POST https://api.signclad.com/api/v1/signer/submit \
-H "X-Api-Key: $SIGNCLAD_API_KEY" POST /signer/decline
Decline to sign
Declines with a reason. The document becomes Declined, the reason is stored as
decline_message, document_declined fires, and every link on the document is revoked —
including this session. Allowed only while allow_decline is true, otherwise 403
decline_not_allowed.
- Base URL
https://api.signclad.com/api/v1- Authentication
- Signer session token
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
reason | string | Required |
Responses
| Status | Description |
|---|---|
200 | Declined. This session is no longer valid. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | The session is valid; this action is not permitted. meta.error is one of consent_required, decline_not_allowed, reassign_not_allowed, download_not_available (with meta.state), `scope_not_a… |
409 | The document no longer accepts signer activity, or the revision moved under the signer.… |
Example request
curl -X POST https://api.signclad.com/api/v1/signer/decline \
-H "X-Api-Key: $SIGNCLAD_API_KEY" POST /signer/reassign
Reassign to somebody else
Hands this turn to another person: a new recipient row is created, this recipient's
fields move to it, recipient_reassigned is recorded, the replacement is notified, and
the old links — this session included — are revoked. Allowed only while allow_reassign
is true and nothing has been signed, otherwise 403 reassign_not_allowed.
- Base URL
https://api.signclad.com/api/v1- Authentication
- Signer session token
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
email | string (email) | Required | |
name | string or null | Optional | |
reason | string or null | Optional |
Responses
| Status | Description |
|---|---|
200 | Reassigned. This session is no longer valid. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | The session is valid; this action is not permitted. meta.error is one of consent_required, decline_not_allowed, reassign_not_allowed, download_not_available (with meta.state), `scope_not_a… |
409 | The document no longer accepts signer activity, or the revision moved under the signer.… |
422 | Validation failed. errors maps a field name to a message string, or to an object keyed by an error code or by a per-item key. Values are never arrays. |
Example request
curl -X POST https://api.signclad.com/api/v1/signer/reassign \
-H "X-Api-Key: $SIGNCLAD_API_KEY" GET /signer/download
Download the signed copy
A short-lived link to the canonical completed artifact — stamped pages plus the audit
page, sealed — once the document is complete and sealed.
Before then this is 403 download_not_available with meta.state, not a 404: no
third-party client keys on a status code here, and the signer app has a real page to
show for "not finished yet".
- Base URL
https://api.signclad.com/api/v1- Authentication
- Signer session token
Responses
| Status | Description |
|---|---|
200 | The download link and the artifact's hash. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | The session is valid; this action is not permitted. meta.error is one of consent_required, decline_not_allowed, reassign_not_allowed, download_not_available (with meta.state), `scope_not_a… |
410 | The link or session was revoked, superseded, already used, or has expired.… |
Example request
curl -X GET https://api.signclad.com/api/v1/signer/download \
-H "X-Api-Key: $SIGNCLAD_API_KEY" Example response (200)
{
"url": "https://files.signclad.com/signed/8f14e45f.pdf?expires=1789050600&signature=...",
"kind": "completed",
"sha256": "7d3f9a1c5b8e2046d1f3a5c7e9b0d2f4a6c8e0b2d4f6a8c1e3b5d7f9a0c2e4b6",
"size": 284310,
"expires_in": 600
} POST /signer/reauthentication
Start Part 11 re-authentication Extension
The second identification component 21 CFR Part 11 §11.200(a)(1) requires: having opened the
document with a link, the signer proves who they are again before signing. start issues a
challenge — an emailed code, or the account password when the signer is a Signclad user —
and verify answers it.
In streamlined mode one challenge covers the session. In per_signature mode
field_api_id is required and names the signature or initials field about to be signed.
The Part 11 check runs before validation, so a document that is not in Part 11 mode answers
403 not_a_cfr_part11_document even for a malformed body.
- Base URL
https://api.signclad.com/api/v1- Authentication
- Signer session token
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
field_api_id | string or null | Optional | Required in per_signature mode, ignored in streamlined. |
Responses
| Status | Description |
|---|---|
201 | The challenge. Keys that do not apply are absent: field_api_id in streamlined mode, and code unless this is a test-mode document, where the code is returned so a test can complete without read… |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | meta.error is not_a_cfr_part11_document, reauthentication_unavailable (a recipient with no email address and no account), reauthentication_required (no or unknown field_api_id in per-signatu… |
409 | The document no longer accepts signer activity, or the revision moved under the signer.… |
422 | Validation failed. errors maps a field name to a message string, or to an object keyed by an error code or by a per-item key. Values are never arrays. |
Example request
curl -X POST https://api.signclad.com/api/v1/signer/reauthentication \
-H "X-Api-Key: $SIGNCLAD_API_KEY" POST /signer/reauthentication/verify
Answer a Part 11 re-authentication challenge Extension
Send the emailed code, or the password when the challenge asked for one. The reply
carries a challenge_token to present with the signature.
A wrong code and an unknown challenge id answer identically — reauthentication_invalid —
so a wrong guess reveals nothing about which ids exist. Running out of attempts reads as
reauthentication_expired, the same as running out of time.
- Base URL
https://api.signclad.com/api/v1- Authentication
- Signer session token
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
id | string | Required | |
code | string or null | Optional | |
password | string or null | Optional |
Responses
| Status | Description |
|---|---|
200 | Verified. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | meta.error is reauthentication_invalid (unknown id, already used, or wrong answer), reauthentication_expired (out of time or out of attempts), or not_a_cfr_part11_document. |
409 | The document no longer accepts signer activity, or the revision moved under the signer.… |
422 | Validation failed. errors maps a field name to a message string, or to an object keyed by an error code or by a per-item key. Values are never arrays. |
Example request
curl -X POST https://api.signclad.com/api/v1/signer/reauthentication/verify \
-H "X-Api-Key: $SIGNCLAD_API_KEY" POST /signer/id_verification/start
Start identity verification Extension
Returns the provider's hosted URL to send the signer to. No request body: what is being verified is already fixed by the document.
- Base URL
https://api.signclad.com/api/v1- Authentication
- Signer session token
Responses
| Status | Description |
|---|---|
201 | The check, and where to send the signer. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | meta.error is id_verification_not_requested when this document and recipient do not call for it, or scope_not_allowed. |
409 | The document no longer accepts signer activity, or the revision moved under the signer.… |
503 | The capability is available on the plan but the environment has no provider behind it — an unknown driver name, or missing credentials. meta.capability says which. |
Example request
curl -X POST https://api.signclad.com/api/v1/signer/id_verification/start \
-H "X-Api-Key: $SIGNCLAD_API_KEY" POST /signer/id_verification/complete
Read back an identity verification Extension
Reads the outcome from the provider. It never accepts an outcome from the signer — that
would make the check worthless — and it is idempotent: an already-verified check is returned
without another provider call.
The submit gate is separate: POST /signer/submit answers
403 id_verification_incomplete while a required check has not passed.
- Base URL
https://api.signclad.com/api/v1- Authentication
- Signer session token
Responses
| Status | Description |
|---|---|
200 | The check as it now stands. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | meta.error is id_verification_required when no check was ever started, or scope_not_allowed. |
409 | The document no longer accepts signer activity, or the revision moved under the signer.… |
503 | The capability is available on the plan but the environment has no provider behind it — an unknown driver name, or missing credentials. meta.capability says which. |
Example request
curl -X POST https://api.signclad.com/api/v1/signer/id_verification/complete \
-H "X-Api-Key: $SIGNCLAD_API_KEY"