Documents API
Create, send, inspect, and download documents.
Updated
On this page
- GET /documents
- POST /documents
- GET /documents/{id}
- PATCH /documents/{id}
- DELETE /documents/{id}
- POST /documents/{id}/send
- POST /documents/{id}/remind
- PATCH /documents/{id}/recipients
- PATCH /documents/{id}/authentication
- GET /documents/{id}/completed_pdf
- GET /documents/{id}/nom151_certificate
- GET /documents/{id}/events
- GET /documents/{id}/attachments
- POST /documents/{id}/cancel
- POST /documents/{id}/complete
- POST /documents/{id}/recipients/{recipient_id}/reassign
- POST /documents/{id}/recipients/{recipient_id}/signing_url
- POST /documents/{id}/recipients/{recipient_id}/in_person_session
- POST /documents/{id}/embedded_edit_url
- PUT /documents/{id}/files/{position}
- GET /files
- POST /files
- GET /verify/{hash}
- DELETE /files/{id}/stored
- GET /labels
- POST /labels
- PATCH /labels/{id}
- DELETE /labels/{id}
- PUT /documents/{id}/labels
29 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
/documentsList documents - POST
/documentsCreate a document - GET
/documents/{id}Get a document - PATCH
/documents/{id}Update a draft document - DELETE
/documents/{id}Delete a document - POST
/documents/{id}/sendUpdate and send a draft - POST
/documents/{id}/remindSend a reminder - PATCH
/documents/{id}/recipientsUpdate recipients - PATCH
/documents/{id}/authenticationUpdate recipient authentication - GET
/documents/{id}/completed_pdfDownload the completed PDF - GET
/documents/{id}/nom151_certificateDownload the NOM-151 constancia - GET
/documents/{id}/eventsList document events - GET
/documents/{id}/attachmentsList uploaded attachments - POST
/documents/{id}/cancelCancel a document - POST
/documents/{id}/completeMark a document manually completed - POST
/documents/{id}/recipients/{recipient_id}/reassignReassign a recipient - POST
/documents/{id}/recipients/{recipient_id}/signing_urlRegenerate a signing URL - POST
/documents/{id}/recipients/{recipient_id}/in_person_sessionStart an in-person signing session - POST
/documents/{id}/embedded_edit_urlRegenerate an embedded builder URL - PUT
/documents/{id}/files/{position}Replace a file on a draft - GET
/filesList reusable stored files - POST
/filesUpload a file - GET
/verify/{hash}Verify a sealed file by hash - DELETE
/files/{id}/storedDelete an unused stored file - GET
/labelsList labels - POST
/labelsCreate a label - PATCH
/labels/{id}Rename or recolor a label - DELETE
/labels/{id}Delete a label - PUT
/documents/{id}/labelsSet a document's labels
GET /documents
List documents Extension
Cursor-paginated list of the workspace's documents, newest first. Replaces polling
documents one id at a time.
This list sends total_count: a second count over the same filters, so tab badges
do not need a page walk.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
status | array of string | Optional | One or more document statuses. Repeat the parameter to pass several (?status=Draft&status=Sent); the bracket spelling ?status[]=Draft&status[]=Sent is accepted too, for clients whose query encoder produces it. |
label | string | Optional | Only records carrying this label. |
recipient_email | string (email) | Optional | Only documents with a recipient at this address. |
waiting_on | string | Optional | Whose signature the document is stuck on. me is a signer at the authenticated user's own address whose turn has come and has not passed — sent or viewed; others is everything else.… |
updated_since | string (date-time) | Optional | Only records changed at or after this time. The reliable way to poll: sort is by updated_at ascending when this is present. |
metadata | object | Optional | Exact match on stored metadata, expressed as metadata[key]=value. Several keys are combined with AND. |
q | string | Optional | Free-text search over name, subject, recipient names, and recipient emails. |
archived | boolean | Optional | Include archived records. Defaults to excluding them. |
archived_only | boolean | Optional | Return only archived records. Narrower than archived, which widens the list to include them alongside everything else. |
test_mode | boolean | Optional | Restrict to test-mode or live documents. Omitted returns both. |
sort | string | Optional | Which column orders the page. Omitted keeps the default of newest first, which is also the order a cursor walks. |
direction | string | Optional | Read only when sort is given. |
cursor | string | Optional | Opaque cursor from a previous response's next_cursor. |
limit | integer | Optional | Items per page. |
Responses
| Status | Description |
|---|---|
200 | A page of documents. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
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 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X GET https://api.signclad.com/api/v1/documents \
-H "X-Api-Key: $SIGNCLAD_API_KEY" POST /documents
Create a document
Creates a document from one or more files and sends it for signature. draft: true
keeps it editable and returns a document-level embedded_edit_url instead of sending.
Returns 201 immediately with the transient status Created, whatever draft
was; subsequent GETs report Draft, or Sending followed by Sent once the email
provider accepts the initial invitation.
files[].pages_number is 0 in this response and carries the real count on the next
GET; the extension field files[].status is processing until ingest finishes.
Signing and embedded URLs are valid straight away.
Unknown properties are dropped silently: they are neither rejected nor echoed back.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
files | array of object | Required | |
recipients | array of object | Required | |
allow_decline | boolean or null | Optional | null on a template that never made a statement either way, in which case each document created from it takes the workspace default at that moment. Always a boolean on a document. |
allow_reassign | boolean or null | Optional | null on a template that never made a statement, as allow_decline. Always a boolean on a document, and pinned to false by cfr_part11. |
api_application_id | string or null | Optional | Branding and embed origins to use for this document. null when none is set. |
apply_signing_order | boolean | Optional | Send to recipients in order; each is notified only once every earlier signer has signed. |
attachment_requests | array of object | Optional | |
cfr_part11 | boolean | Optional | 21 CFR Part 11 mode. It can also be switched on by the workspace or the account, so a request that never mentions it may still come back with it set.… |
cfr_part11_signing_mode | string or null | Optional | streamlined re-authenticates once for the session; per_signature re-authenticates for each signature or initials field. Asking for a mode without the plan feature is 422 not_available_on_plan. Documents only.… |
checkbox_groups | array of object | Optional | |
conditional_rules | array of object | Optional | |
copied_contacts | array of object | Optional | |
custom_requester_email | string or null | Optional | Reply-to address for the invitation. null when the workspace default applies. |
custom_requester_name | string or null | Optional | Name the invitation comes from. null when the workspace default applies. |
decline_redirect_url | string or null | Optional | Where a signer lands after declining. null when none is set. |
draft | boolean | Optional | Keep the document editable instead of sending it. A draft returns a document-level embedded_edit_url. |
embedded_signing | boolean | Optional | Return per-recipient embedded_signing_urls for use in an iframe. |
embedded_signing_notifications | boolean | Optional | Send Signclad's own signing prompts even though the document is embedded.… |
expires_in | integer or null | Optional | Days until the document expires. Defaults to the template's value, then the account's, which is 30. |
fields | array of array of object | Optional | One array of fields per file, in files order. |
id_verification | one of: IdVerificationRequest, null | Optional | null when nothing was asked for. Documents only, like the Part 11 settings: a template stores it and never echoes it. |
labels | array of one of: string, object | Optional | |
language | string | Optional | Language for the signing experience and its emails. Arabic renders right to left. |
message | string or null | Optional | Body of the signing invitation. A safe subset of HTML is allowed. null when none was set and none was inherited. |
metadata | one of: Metadata, null | Optional | null rather than {} when nothing was stored. |
name | string | Optional | Internal name. Defaults to the first file's name. |
redirect_url | string or null | Optional | Where a signer lands after finishing. null when none is set. |
reminders | boolean or null | Optional | Automatic reminders on days 3, 6, and 10. null on a template that never made a statement either way; always a boolean on a document. |
requester_email_address | string or null | Optional | Who the document is from, resolved from the credential that created it. null when it could not be resolved — an API key whose owner has since been removed, say. Emitted on documents and templates. |
self_sign | boolean | Optional | The requester signs immediately rather than being emailed a link. |
skip_invalid_fields | boolean | Optional | Drop template_fields entries that cannot be applied and report them in warnings[] instead of failing the whole request. |
subject | string | Optional | Subject line of the signing invitation. |
test_mode | boolean | Optional | A test document is excluded from billing and is not legally binding. Sandbox API keys force this on. Test mode does not suppress delivery: a test document emails its recipients like any other, and an undeliverable address bounces.… |
text_tags | boolean | Optional | Parse Signclad [type|modifier] tags or legacy positional {{...}} tags in the uploaded files into fields. Both formats work for documents and templates and may be mixed in one file.… |
wait_for_fields | boolean | Optional | Answer once the uploaded files have been prepared and the field import has run, so the response already carries fields_pending: false and the fields from text tags, imported form widgets and the generated signature page.… |
with_signature_page | boolean | Optional | Append a generated signature page listing every signer, each with a signature field, a locked date-signed field, and a name autofill. Those fields are addressable as SignaturePage_Signature_<recipient_id> and the page counts toward pages_number. |
Responses
| Status | Description |
|---|---|
201 | Created. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
409 | The request is well formed; the resource is not in a state that allows it.… |
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 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X POST https://api.signclad.com/api/v1/documents \
-H "X-Api-Key: $SIGNCLAD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Loan agreement",
"subject": "Please sign your loan agreement",
"message": "<p>Two signatures, about a minute.</p>",
"test_mode": false,
"draft": false,
"reminders": true,
"expires_in": 30,
"language": "en",
"metadata": {
"loan_id": "48213"
},
"files": [
{
"name": "loan-agreement.pdf",
"file_url": "https://files.example.com/loan-agreement.pdf?X-Amz-Expires=7200&X-Amz-Signature=..."
}
],
"recipients": [
{
"id": "signer-1",
"name": "Jane Doe",
"email": "[email protected]"
}
],
"fields": [
[
{
"api_id": "borrower_signature",
"type": "signature",
"recipient_id": "signer-1",
"page": 1,
"x": 375,
"y": 206,
"width": 180,
"height": 44,
"required": true
},
{
"api_id": "borrower_date",
"type": "date",
"recipient_id": "signer-1",
"page": 1,
"x": 375,
"y": 262,
"width": 120,
"height": 24,
"lock_sign_date": true,
"date_format": "MM/DD/YYYY"
}
]
]
}' Example response (201)
{
"id": "8f14e45f-ea8f-4b2c-9f0e-1b2c3d4e5f60",
"status": "Created",
"archived": false,
"name": "Loan agreement",
"subject": "Please sign your loan agreement",
"message": "<p>Two signatures, about a minute.</p>",
"test_mode": false,
"draft": false,
"embedded_signing": true,
"apply_signing_order": false,
"allow_decline": true,
"allow_reassign": true,
"language": "en",
"expires_in": 30,
"reminders": true,
"created_at": "2026-09-09T17:44:10Z",
"updated_at": "2026-09-09T17:44:10Z",
"requester_email_address": "[email protected]",
"decline_message": null,
"error_message": null,
"embedded_edit_url": null,
"embedded_preview_url": null,
"cfr_part11": false,
"cfr_part11_signing_mode": null,
"template_id": null,
"template_ids": [],
"metadata": {
"loan_id": "48213"
},
"files": [
{
"name": "loan-agreement.pdf",
"pages_number": 0,
"status": "processing"
}
],
"recipients": [
{
"id": "signer-1",
"name": "Jane Doe",
"email": "[email protected]",
"status": "created",
"signing_order": 1,
"embedded_signing_url": "https://app.signclad.com/sign/embedded/4f8c1b7a2e9d05364c8b1e7a2d9f06354b8c1e7a2d9f06354b8c1e7a2d9f0635",
"bounced": false,
"bounced_details": null
}
],
"fields": [
[
{
"api_id": "borrower_signature",
"type": "signature",
"recipient_id": "signer-1",
"page": 1,
"x": 375,
"y": 206,
"width": "180.0",
"height": "44.0",
"required": true,
"value": null
}
]
],
"warnings": [
{
"code": "lock_sign_date_value_ignored",
"message": "A value was supplied for borrower_date, which fills itself on signing. It was ignored.",
"pointer": "/fields/0/1/value"
}
]
} GET /documents/{id}
Get a document
The full document object, including recipients, fields, and files. This is where the
settled status lives: a document that answered Created at create reads Draft or
Sent here.
fields comes back grouped by field type, not in the order it was sent. Address fields
by api_id, never by index.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Path parameters
| Name | Type | Description |
|---|---|---|
id | string (uuid) | The document's id. |
Responses
| Status | Description |
|---|---|
200 | The document. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
404 | No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative. |
429 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X GET https://api.signclad.com/api/v1/documents/{id} \
-H "X-Api-Key: $SIGNCLAD_API_KEY" Example response (200)
{
"id": "8f14e45f-ea8f-4b2c-9f0e-1b2c3d4e5f60",
"status": "Sent",
"archived": false,
"name": "Loan agreement",
"subject": "Please sign your loan agreement",
"message": "<p>Two signatures, about a minute.</p>",
"test_mode": false,
"draft": false,
"embedded_signing": true,
"apply_signing_order": false,
"allow_decline": true,
"allow_reassign": true,
"language": "en",
"expires_in": 30,
"expires_at": "2026-10-09T17:44:10Z",
"reminders": true,
"created_at": "2026-09-09T17:44:10Z",
"updated_at": "2026-09-09T17:44:12Z",
"completed_at": null,
"requester_email_address": "[email protected]",
"decline_message": null,
"error_message": null,
"embedded_edit_url": null,
"embedded_preview_url": "https://app.signclad.com/p/qNqQ0tqAcTGFGuBDcDSIGWxdrytYhwGGpqXFaxvoNXbLmAkPxCsRvUSVgHLTHCNE",
"cfr_part11": false,
"cfr_part11_signing_mode": null,
"template_id": null,
"template_ids": [],
"metadata": {
"loan_id": "48213"
},
"files": [
{
"name": "loan-agreement.pdf",
"pages_number": 4,
"status": "ready"
}
],
"recipients": [
{
"id": "signer-1",
"name": "Jane Doe",
"email": "[email protected]",
"status": "sent",
"signing_order": 1,
"embedded_signing_url": "https://app.signclad.com/sign/embedded/9d05364c8b1e7a2d9f06354b8c1e7a2d9f06354b8c1e7a2d9f06354b8c1e7a2d",
"bounced": false,
"bounced_details": null,
"viewed_at": null,
"signed_at": null
}
],
"fields": [
[
{
"api_id": "borrower_date",
"type": "date",
"recipient_id": "signer-1",
"page": 1,
"x": 375,
"y": 262,
"width": "120.0",
"height": "24.0",
"lock_sign_date": true,
"date_format": "MM/DD/YYYY",
"value": null
},
{
"api_id": "borrower_signature",
"type": "signature",
"recipient_id": "signer-1",
"page": 1,
"x": 375,
"y": 206,
"width": "180.0",
"height": "44.0",
"required": true,
"value": null
}
]
],
"conditional_logic_decisions": [],
"completed_pdf_url": null,
"audit_trail_url": null,
"sent_revision_hash": "4c9a1f0b7e2d5a836c1b4e9f0a2d7c53e81b6f40a95d2c7e13b8f6a0d4c2e915",
"source": "api"
} PATCH /documents/{id}
Update a draft document Extension
Updates settings, recipients, and fields on a document that is still a draft. Sending a
draft is POST /documents/{id}/send; this operation never sends.
Returns 409 document_not_active when the document has left the draft state — except
for archived. A body that carries nothing but archived is applied to a document in any
state, including a completed or canceled one, and writes no revision. Archiving is
filing, not editing.
A sent document is not frozen, though: a recipient who has not started can still be
corrected through PATCH /documents/{id}/recipients while the document is Sent,
Viewed or Pending.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Path parameters
| Name | Type | Description |
|---|---|---|
id | string (uuid) | The document's id. |
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
allow_decline | boolean or null | Optional | null on a template that never made a statement either way, in which case each document created from it takes the workspace default at that moment. Always a boolean on a document. |
allow_reassign | boolean or null | Optional | null on a template that never made a statement, as allow_decline. Always a boolean on a document, and pinned to false by cfr_part11. |
api_application_id | string or null | Optional | Branding and embed origins to use for this document. null when none is set. |
apply_signing_order | boolean | Optional | Send to recipients in order; each is notified only once every earlier signer has signed. |
archived | boolean | Optional | Files the document away, or brings it back. Sent on its own, it works whatever the document's state; sent alongside anything else, the draft rule applies to the whole request. |
attachment_requests | array of object | Optional | |
cfr_part11 | boolean | Optional | 21 CFR Part 11 mode. It can also be switched on by the workspace or the account, so a request that never mentions it may still come back with it set.… |
cfr_part11_signing_mode | string or null | Optional | streamlined re-authenticates once for the session; per_signature re-authenticates for each signature or initials field. Asking for a mode without the plan feature is 422 not_available_on_plan. Documents only.… |
checkbox_groups | array of object | Optional | |
conditional_rules | array of object | Optional | |
copied_contacts | array of object | Optional | |
custom_requester_email | string or null | Optional | Reply-to address for the invitation. null when the workspace default applies. |
custom_requester_name | string or null | Optional | Name the invitation comes from. null when the workspace default applies. |
decline_redirect_url | string or null | Optional | Where a signer lands after declining. null when none is set. |
draft | boolean | Optional | Keep the document editable instead of sending it. A draft returns a document-level embedded_edit_url. |
embedded_signing | boolean | Optional | Return per-recipient embedded_signing_urls for use in an iframe. |
embedded_signing_notifications | boolean | Optional | Send Signclad's own signing prompts even though the document is embedded.… |
expires_in | integer or null | Optional | Days until the document expires. Defaults to the template's value, then the account's, which is 30. |
fields | array of array of object | Optional | |
files | array of object | Optional | |
id_verification | one of: IdVerificationRequest, null | Optional | null when nothing was asked for. Documents only, like the Part 11 settings: a template stores it and never echoes it. |
labels | array of one of: string, object | Optional | |
language | string | Optional | Language for the signing experience and its emails. Arabic renders right to left. |
message | string or null | Optional | Body of the signing invitation. A safe subset of HTML is allowed. null when none was set and none was inherited. |
metadata | one of: Metadata, null | Optional | null rather than {} when nothing was stored. |
name | string | Optional | Internal name. Defaults to the first file's name. |
recipients | array of object | Optional | |
redirect_url | string or null | Optional | Where a signer lands after finishing. null when none is set. |
reminders | boolean or null | Optional | Automatic reminders on days 3, 6, and 10. null on a template that never made a statement either way; always a boolean on a document. |
requester_email_address | string or null | Optional | Who the document is from, resolved from the credential that created it. null when it could not be resolved — an API key whose owner has since been removed, say. Emitted on documents and templates. |
self_sign | boolean | Optional | The requester signs immediately rather than being emailed a link. |
skip_invalid_fields | boolean | Optional | Drop template_fields entries that cannot be applied and report them in warnings[] instead of failing the whole request. |
subject | string | Optional | Subject line of the signing invitation. |
test_mode | boolean | Optional | A test document is excluded from billing and is not legally binding. Sandbox API keys force this on. Test mode does not suppress delivery: a test document emails its recipients like any other, and an undeliverable address bounces.… |
text_tags | boolean | Optional | Parse Signclad [type|modifier] tags or legacy positional {{...}} tags in the uploaded files into fields. Both formats work for documents and templates and may be mixed in one file.… |
with_signature_page | boolean | Optional | Append a generated signature page listing every signer, each with a signature field, a locked date-signed field, and a name autofill. Those fields are addressable as SignaturePage_Signature_<recipient_id> and the page counts toward pages_number. |
Responses
| Status | Description |
|---|---|
200 | The updated draft. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
404 | No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative. |
409 | The request is well formed; the resource is not in a state that allows it.… |
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 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X PATCH https://api.signclad.com/api/v1/documents/{id} \
-H "X-Api-Key: $SIGNCLAD_API_KEY" DELETE /documents/{id}
Delete a document
Deletes the document and cancels signing that is in progress.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Path parameters
| Name | Type | Description |
|---|---|---|
id | string (uuid) | The document's id. |
Responses
| Status | Description |
|---|---|
204 | Deleted. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
404 | No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative. |
409 | The request is well formed; the resource is not in a state that allows it.… |
429 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X DELETE https://api.signclad.com/api/v1/documents/{id} \
-H "X-Api-Key: $SIGNCLAD_API_KEY" POST /documents/{id}/send
Update and send a draft
Sends a draft document. Accepts most create-time settings, but not files,
recipients, or fields; edit those through the builder or PATCH /documents/{id}
before sending.
The response carries the transient status Draft; subsequent GETs report Sending
until the email provider accepts the initial invitation, then Sent. Sending also
regenerates every recipient's signing_url, so a URL captured from the draft response
is dead once this call returns.
Returns 409 document_not_active when the document is not a draft, and applies none of
the settings in the body when it does: the state is checked before anything is written.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Path parameters
| Name | Type | Description |
|---|---|---|
id | string (uuid) | The document's id. |
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
allow_decline | boolean or null | Optional | null on a template that never made a statement either way, in which case each document created from it takes the workspace default at that moment. Always a boolean on a document. |
allow_reassign | boolean or null | Optional | null on a template that never made a statement, as allow_decline. Always a boolean on a document, and pinned to false by cfr_part11. |
api_application_id | string or null | Optional | Branding and embed origins to use for this document. null when none is set. |
apply_signing_order | boolean | Optional | Send to recipients in order; each is notified only once every earlier signer has signed. |
attachment_requests | array of object | Optional | |
cfr_part11 | boolean | Optional | 21 CFR Part 11 mode. It can also be switched on by the workspace or the account, so a request that never mentions it may still come back with it set.… |
cfr_part11_signing_mode | string or null | Optional | streamlined re-authenticates once for the session; per_signature re-authenticates for each signature or initials field. Asking for a mode without the plan feature is 422 not_available_on_plan. Documents only.… |
copied_contacts | array of object | Optional | |
custom_requester_email | string or null | Optional | Reply-to address for the invitation. null when the workspace default applies. |
custom_requester_name | string or null | Optional | Name the invitation comes from. null when the workspace default applies. |
decline_redirect_url | string or null | Optional | Where a signer lands after declining. null when none is set. |
draft | boolean | Optional | Keep the document editable instead of sending it. A draft returns a document-level embedded_edit_url. |
embedded_signing | boolean | Optional | Return per-recipient embedded_signing_urls for use in an iframe. |
embedded_signing_notifications | boolean | Optional | Send Signclad's own signing prompts even though the document is embedded.… |
expires_in | integer or null | Optional | Days until the document expires. Defaults to the template's value, then the account's, which is 30. |
id_verification | one of: IdVerificationRequest, null | Optional | null when nothing was asked for. Documents only, like the Part 11 settings: a template stores it and never echoes it. |
labels | array of one of: string, object | Optional | |
language | string | Optional | Language for the signing experience and its emails. Arabic renders right to left. |
message | string or null | Optional | Body of the signing invitation. A safe subset of HTML is allowed. null when none was set and none was inherited. |
metadata | one of: Metadata, null | Optional | null rather than {} when nothing was stored. |
name | string | Optional | Internal name. Defaults to the first file's name. |
redirect_url | string or null | Optional | Where a signer lands after finishing. null when none is set. |
reminders | boolean or null | Optional | Automatic reminders on days 3, 6, and 10. null on a template that never made a statement either way; always a boolean on a document. |
requester_email_address | string or null | Optional | Who the document is from, resolved from the credential that created it. null when it could not be resolved — an API key whose owner has since been removed, say. Emitted on documents and templates. |
self_sign | boolean | Optional | The requester signs immediately rather than being emailed a link. |
skip_invalid_fields | boolean | Optional | Drop template_fields entries that cannot be applied and report them in warnings[] instead of failing the whole request. |
subject | string | Optional | Subject line of the signing invitation. |
test_mode | boolean | Optional | A test document is excluded from billing and is not legally binding. Sandbox API keys force this on. Test mode does not suppress delivery: a test document emails its recipients like any other, and an undeliverable address bounces.… |
text_tags | boolean | Optional | Parse Signclad [type|modifier] tags or legacy positional {{...}} tags in the uploaded files into fields. Both formats work for documents and templates and may be mixed in one file.… |
with_signature_page | boolean | Optional | Append a generated signature page listing every signer, each with a signature field, a locked date-signed field, and a name autofill. Those fields are addressable as SignaturePage_Signature_<recipient_id> and the page counts toward pages_number. |
Responses
| Status | Description |
|---|---|
201 | Sent. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
404 | No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative. |
409 | The request is well formed; the resource is not in a state that allows it.… |
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 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X POST https://api.signclad.com/api/v1/documents/{id}/send \
-H "X-Api-Key: $SIGNCLAD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"subject": "Your loan documents are ready",
"message": "<p>Please review and sign.</p>",
"reminders": true
}' POST /documents/{id}/remind
Send a reminder
Reminds recipients who have not finished. Omitting recipients reminds every unsigned
recipient.
A reminder asked for here is sent even on an embedded document, whose
embedded_signing_notifications default silences only the reminders Signclad sends on its
own schedule. The recipient's own answers still apply: a cc, someone who unsubscribed
from reminders, and a recipient with send_email: false are never reminded.
The response's reminded names who was actually reached, which may be nobody. See
RemindResult.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Path parameters
| Name | Type | Description |
|---|---|---|
id | string (uuid) | The document's id. |
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
recipients | array of object | Optional |
Responses
| Status | Description |
|---|---|
201 | Reminder queued for the recipients in reminded, which is empty when it reached nobody. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
404 | No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative. |
409 | The request is well formed; the resource is not in a state that allows it.… |
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 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X POST https://api.signclad.com/api/v1/documents/{id}/remind \
-H "X-Api-Key: $SIGNCLAD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"recipients": [
{
"email": "[email protected]",
"name": "Jane Doe"
}
]
}' PATCH /documents/{id}/recipients
Update recipients
Corrects recipient name and email on a live document. Allowed only while the document is
Sent, Viewed or Pending, and only for recipients who have not started signing — a
recipient who has saved a value or signed is past correcting. Any other state is
409 document_not_active.
This is how a typo in an address is fixed after sending, and the reason `PATCH
/documents/{id}` refusing a non-draft is not the end of the story.
delivery_method and phone_number cannot be changed here. Non-embedded recipients are
e-mailed again; every updated recipient's old links stop working.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Path parameters
| Name | Type | Description |
|---|---|---|
id | string (uuid) | The document's id. |
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
recipients | array of object | Required |
Responses
| Status | Description |
|---|---|
200 | The updated document. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
404 | No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative. |
409 | The request is well formed; the resource is not in a state that allows it.… |
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 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X PATCH https://api.signclad.com/api/v1/documents/{id}/recipients \
-H "X-Api-Key: $SIGNCLAD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"recipients": [
{
"id": "signer-1",
"name": "Jane Doe",
"email": "[email protected]"
}
]
}' PATCH /documents/{id}/authentication
Update recipient authentication
Sets or clears the passcode and passcode delivery for individual recipients.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Path parameters
| Name | Type | Description |
|---|---|---|
id | string (uuid) | The document's id. |
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
recipients | array of object | Required |
Responses
| Status | Description |
|---|---|
200 | The updated document. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
404 | No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative. |
409 | The request is well formed; the resource is not in a state that allows it.… |
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 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X PATCH https://api.signclad.com/api/v1/documents/{id}/authentication \
-H "X-Api-Key: $SIGNCLAD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"recipients": [
{
"id": "signer-1",
"passcode": "482913",
"passcode_delivery": {
"enabled": true,
"methods": [
"email"
],
"expire_after_access": true
}
}
]
}' GET /documents/{id}/completed_pdf
Download the completed PDF
Returns the sealed PDF bytes, or a short-lived link when url_only is true. The bytes
come back as application/pdf with content-disposition: inline, filenamed from the
document name plus each signer's name, lowercased and underscore-joined.
Returns 404 (never 403) until every signer has finished, so a retry loop can key on
the status code alone. That 404 body is byte-identical to the one for a document that
does not exist, so only context distinguishes them.
Long-term validation is served by default. A workspace whose plan includes pades_lt
gets the completed_lt artifact — the PAdES B-LT/B-LTA enrichment — from this route with
no parameter, whenever the document has one. There is no opt-in because a customer who
paid for a file that still verifies in ten years should not have to change their
integration to receive it. The substitution is safe: the enrichment is an incremental
update appended after the canonical file's %%EOF, so the canonical bytes are a prefix
of what comes back, every signature over them still verifies, and the completed
artifact's SHA-256 still describes the first source_size bytes. GET /verify/{hash}
recognises the enriched file's own hash. See api/docs/ltv.md.
audit_page=false is unaffected: only the canonical artifact is enriched.
On a 21 CFR Part 11 document the audit page is part of the record: audit_page=false and
file_format=zip answer 422 with errors.audit_page or errors.file_format keyed
not_available_on_cfr_part11 — the artifact asked for is not one this document may
produce, and a 404 would not say so.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Path parameters
| Name | Type | Description |
|---|---|---|
id | string (uuid) | The document's id. |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
url_only | boolean | Optional | Return a JSON object with a short-lived pre-signed download URL instead of the bytes. The link points at the stored object, not at this endpoint, so it needs no credential of its own and can be passed to something that has none. |
audit_page | boolean | Optional | Include the audit page. false returns the separately generated and sealed no-audit artifact. Cannot be disabled on 21 CFR Part 11 documents. |
audit_only | boolean | Optional | Return the signed audit.json — the event chain, the chain head, the revision manifest hash, and the hashes of the PDF artifacts — instead of a PDF. |
file_format | string | Optional | pdf returns one PDF. zip returns the sealed PDF, per-file variants, requested attachments, and the signed audit.json. |
Responses
| Status | Description |
|---|---|
200 | The completed file, or its URL when url_only=true. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
404 | The document does not exist for this workspace, or it is not complete yet. Both cases share this body. |
422 | The artifact asked for cannot exist for this document — errors.audit_page or errors.file_format keyed not_available_on_cfr_part11 on a Part 11 document. |
429 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X GET https://api.signclad.com/api/v1/documents/{id}/completed_pdf \
-H "X-Api-Key: $SIGNCLAD_API_KEY" Example response (200)
{
"completed_pdf_url": "https://files.signclad.com/signed/8f14e45f-ea8f-4b2c-9f0e-1b2c3d4e5f60.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=600&X-Amz-Signature=...",
"audit_trail_url": "https://files.signclad.com/audit/8f14e45f-ea8f-4b2c-9f0e-1b2c3d4e5f60.json?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=600&X-Amz-Signature=...",
"expires_at": "2026-09-09T18:00:00Z"
} GET /documents/{id}/nom151_certificate
Download the NOM-151 constancia
Mexico NOM-151 constancia de conservación for a completed document, issued by a
certification service provider after sealing.
Three answers, from one 200: the ZIP bytes by default, a link with url_only, or the
parsed constancia with object_only. url_only wins if both are set.
The order of the refusals is the contract, and each means something different to act on. A
document in another workspace is 404 before anything else. Then, in order:
- 422 not_available_on_plan — the plan does not carry NOM-151. Unchanged from before the
feature shipped, so a client written against that answer keeps working.
- 422 not_enabled — the plan carries it and the workspace has not switched it on. This
never becomes true by retrying; somebody has to change a setting.
- 422 certificate_unavailable — switched on, and the constancia is not issued yet. The
only one of the three worth retrying.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Path parameters
| Name | Type | Description |
|---|---|---|
id | string (uuid) | The document's id. |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
url_only | boolean | Optional | Return a JSON object with a short-lived download URL instead of the bytes. |
object_only | boolean | Optional | Return the parsed constancia object instead of the file. |
Responses
| Status | Description |
|---|---|
200 | The constancia. A ZIP by default — it holds the certificate, the certified file, and the chain — a link with url_only, or the parsed object with object_only. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
404 | No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative. |
422 | One of three, under errors.base: not_available_on_plan (with meta.feature), not_enabled, or certificate_unavailable. Only the last is worth retrying. |
429 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X GET https://api.signclad.com/api/v1/documents/{id}/nom151_certificate \
-H "X-Api-Key: $SIGNCLAD_API_KEY" GET /documents/{id}/events
List document events Extension
The document's audit trail: every event with its sequence, actor, IP, user agent, and
hash-chain link. The same rows that produce the audit page and audit.json.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Path parameters
| Name | Type | Description |
|---|---|---|
id | string (uuid) | The document's id. |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
cursor | string | Optional | Opaque cursor from a previous response's next_cursor. |
limit | integer | Optional | Events per page. |
type | array of string | Optional | Filter to one or more event types. Repeat the parameter to pass several (?type=document_sent&type=document_signed); ?type[]= is accepted too. |
Responses
| Status | Description |
|---|---|
200 | A page of events, oldest first. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
404 | No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative. |
429 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X GET https://api.signclad.com/api/v1/documents/{id}/events \
-H "X-Api-Key: $SIGNCLAD_API_KEY" GET /documents/{id}/attachments
List uploaded attachments Extension
Files that recipients uploaded to satisfy attachment_requests.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Path parameters
| Name | Type | Description |
|---|---|---|
id | string (uuid) | The document's id. |
Responses
| Status | Description |
|---|---|
200 | The attachments. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
404 | No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative. |
429 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X GET https://api.signclad.com/api/v1/documents/{id}/attachments \
-H "X-Api-Key: $SIGNCLAD_API_KEY" POST /documents/{id}/cancel
Cancel a document Extension
Stops signing and moves the document to Canceled without deleting it, so the audit
trail survives. DELETE /documents/{id} cancels and deletes.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Path parameters
| Name | Type | Description |
|---|---|---|
id | string (uuid) | The document's id. |
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
notify_recipients | boolean | Optional | Email everybody who had not finished. |
reason | string | Optional |
Responses
| Status | Description |
|---|---|
200 | The canceled document. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
404 | No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative. |
409 | The request is well formed; the resource is not in a state that allows it.… |
429 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X POST https://api.signclad.com/api/v1/documents/{id}/cancel \
-H "X-Api-Key: $SIGNCLAD_API_KEY" POST /documents/{id}/complete
Mark a document manually completed Extension
Ends signing early and seals what has been signed so far. The document's status becomes
Manually completed and the reason is recorded in the audit trail.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Path parameters
| Name | Type | Description |
|---|---|---|
id | string (uuid) | The document's id. |
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
notify_recipients | boolean | Optional | |
reason | string | Optional |
Responses
| Status | Description |
|---|---|
200 | The completed document. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
404 | No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative. |
409 | The request is well formed; the resource is not in a state that allows it.… |
429 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X POST https://api.signclad.com/api/v1/documents/{id}/complete \
-H "X-Api-Key: $SIGNCLAD_API_KEY" POST /documents/{id}/recipients/{recipient_id}/reassign
Reassign a recipient Extension
Hands a recipient's turn to somebody else. The original recipient's links stop working,
a new recipient row is created with reassigned_from, and the reassignment is recorded
in the audit trail. Allowed only while allow_reassign is true and the recipient has
not signed.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Path parameters
| Name | Type | Description |
|---|---|---|
id | string (uuid) | The document's id. |
recipient_id | string | The recipient's caller-supplied id, as sent in recipients[].id. |
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
email | string (email) | Required | |
message | string | Optional | Note included in the new recipient's invitation. |
name | string | Optional | |
reason | string | Optional |
Responses
| Status | Description |
|---|---|
201 | The new recipient. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
404 | No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative. |
409 | The request is well formed; the resource is not in a state that allows it.… |
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 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X POST https://api.signclad.com/api/v1/documents/{id}/recipients/{recipient_id}/reassign \
-H "X-Api-Key: $SIGNCLAD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Sam Rivera",
"email": "[email protected]",
"reason": "Jane is out of office"
}' POST /documents/{id}/recipients/{recipient_id}/signing_url
Regenerate a signing URL Extension
Issues a fresh single-use embedded signing URL for one recipient. This is the only
regeneration route; there is no GET. Hosts call it instead of recreating the document
every time somebody opens their portal.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Path parameters
| Name | Type | Description |
|---|---|---|
id | string (uuid) | The document's id. |
recipient_id | string | The recipient's caller-supplied id, as sent in recipients[].id. |
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
expires_in_minutes | integer | Optional | Echoed, not applied. The value comes back in the response's expires_at, but the link itself always expires after the deployment's configured exchange window — 30 minutes by default. Do not rely on a longer window than that. |
Responses
| Status | Description |
|---|---|
201 | A new signing URL. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
404 | No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative. |
409 | The request is well formed; the resource is not in a state that allows it.… |
429 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X POST https://api.signclad.com/api/v1/documents/{id}/recipients/{recipient_id}/signing_url \
-H "X-Api-Key: $SIGNCLAD_API_KEY" Example response (201)
{
"embedded_signing_url": "https://app.signclad.com/sign/embedded/4f8c1b7a2e9d05364c8b1e7a2d9f06354b8c1e7a2d9f06354b8c1e7a2d9f0635",
"signing_url": "https://app.signclad.com/sign/4f8c1b7a2e9d05364c8b1e7a2d9f06354b8c1e7a2d9f06354b8c1e7a2d9f0635",
"expires_at": "2026-09-09T18:15:00Z"
} POST /documents/{id}/recipients/{recipient_id}/in_person_session
Start an in-person signing session Extension
Signing in person: the host is standing next to the signer with a tablet and hands it over.
No email, no link, nothing to click — which is the point, because the situations this is
for are the ones where the signer has no working email in the room.
A write on the sender's credential. What comes back is a signer bearer token scoped to
exactly one recipient, with the same lifetime every other signer session has, so the tablet
can be handed over without exposing the sender's own session. It opens the same signing
session an emailed link would have opened, and is presented as
Authorization: Bearer <token>.
The guards are the link exchange's, minus the two that are about a link: the document has
to be open, the recipient has to be a signer who has not finished (`409
recipient_not_a_signer / recipient_not_signable`), and the signing order has to have
reached them (403 not_your_turn). The passcode gate is deliberately not applied — a
passcode proves that the person who received the email is the one opening it, and here the
host has identified the signer face to face.
The session is recorded as a signer_session_started event with source: in_person, and a
document whose source is web is promoted to in_person. A document created through the
API, a bulk send or a template link keeps the provenance it was created with, so the column
never disagrees with the usage row written when it was sent.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Path parameters
| Name | Type | Description |
|---|---|---|
id | string (uuid) | The document's id. |
recipient_id | string | The recipient's caller-supplied id, as sent in recipients[].id. |
Responses
| Status | Description |
|---|---|
201 | A signer session for the host's device. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
404 | No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative. |
409 | The request is well formed; the resource is not in a state that allows it.… |
422 | The request was well formed; the account may not make it right now.… |
429 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X POST https://api.signclad.com/api/v1/documents/{id}/recipients/{recipient_id}/in_person_session \
-H "X-Api-Key: $SIGNCLAD_API_KEY" Example response (201)
{
"token": "sgn_sess_9c8f2b1a4d6e5f70819a2b3c4d5e6f70",
"token_type": "Bearer",
"expires_at": "2026-09-09T18:15:00Z",
"scope": "in_person",
"document_id": "8f14e45f-ea8f-4b2c-9f0e-1b2c3d4e5f60",
"recipient_id": "recipient_1",
"session_id": "01J9K3P2S5N7Q8R0T2V4X6Z8A0"
} POST /documents/{id}/embedded_edit_url
Regenerate an embedded builder URL Extension
Issues a fresh single-use embedded_edit_url for the document builder. The embed script
normally receives a renewal URL from the iframe in its setId message; this route is
for hosts that lost it.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Path parameters
| Name | Type | Description |
|---|---|---|
id | string (uuid) | The document's id. |
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
expires_in_minutes | integer | Optional | Echoed, not applied, exactly as on SigningUrlRequest: it sets the reported expires_at while the link honours the configured exchange window. |
start | string | Optional | Which view the builder opens on. Not read here — it is a parameter of the embed script, which you pass when you mount the iframe, not of this call. |
Responses
| Status | Description |
|---|---|
201 | A new builder URL. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
404 | No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative. |
409 | The request is well formed; the resource is not in a state that allows it.… |
429 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X POST https://api.signclad.com/api/v1/documents/{id}/embedded_edit_url \
-H "X-Api-Key: $SIGNCLAD_API_KEY" PUT /documents/{id}/files/{position}
Replace a file on a draft Extension
Swaps one file of a draft document and re-anchors its fields. Run it once with
dry_run: true to see the report, then again with dry_run: false and the
expected_revision the dry run returned.
PUT /document_templates/{id}/files/{position} is the template equivalent and behaves
identically, against template revisions instead of draft revisions.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Path parameters
| Name | Type | Description |
|---|---|---|
id | string (uuid) | The document's id. |
position | integer | 1-based position of the file within the document or template. |
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
dry_run | boolean | Optional | Report what would happen and change nothing. |
expected_revision | integer | Optional | The revision the dry run reported. A commit against a stale revision is 409 revision_mismatch. |
file_base64 | string | Optional | |
file_id | string | Optional | |
file_url | string (uri) | Optional | |
name | string | Optional | |
scale_to_page | boolean | Optional | Scale coordinates when the new page size differs from the old one. |
strategy | string | Optional | How fields find their place on the new file. keep_positions keeps page and coordinates; text_tags re-parses the tags and matches by api_id; anchors finds the words each field was placed next to and moves the field with them.… |
Responses
| Status | Description |
|---|---|
200 | The replacement report. Nothing changed when dry_run was true. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
404 | No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative. |
409 | The request is well formed; the resource is not in a state that allows it.… |
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 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X PUT https://api.signclad.com/api/v1/documents/{id}/files/{position} \
-H "X-Api-Key: $SIGNCLAD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "loan-agreement-v2.pdf",
"file_url": "https://files.example.com/loan-agreement-v2.pdf?X-Amz-Expires=7200&X-Amz-Signature=...",
"strategy": "anchors",
"scale_to_page": true,
"dry_run": true
}' Example response (200)
{
"revision": 7,
"dry_run": true,
"requires_review": true,
"report": {
"kept": [
{
"api_id": "borrower_signature",
"page": 1,
"x": 375,
"y": 206
}
],
"moved": [
{
"api_id": "borrower_date",
"page": 1,
"x": 375,
"y": 289,
"previous_page": 1,
"previous_x": 375,
"previous_y": 262,
"reason": "Anchor text moved down 27 points."
}
],
"scaled": [],
"orphaned": [
{
"api_id": "witness_initials",
"previous_page": 5,
"reason": "Page 5 does not exist in the new file."
}
]
},
"file": {
"name": "loan-agreement-v2.pdf",
"pages_number": 4,
"status": "ready"
}
} GET /files
List reusable stored files
Lists ready original files in the current workspace. Members see files in
accessible documents and templates; owners, admins, and workspace credentials
also see unattached uploads and retained history. Sandbox restrictions apply.
Files are returned once, newest first, in pages of 20. No storage is copied.
can_delete is false while any live reference or saved history needs the file.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
search | string | Optional | |
page | integer | Optional |
Responses
| Status | Description |
|---|---|
200 | A page of reusable files |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
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 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X GET https://api.signclad.com/api/v1/files \
-H "X-Api-Key: $SIGNCLAD_API_KEY" POST /files
Upload a file Extension
Uploads a file once and returns an id usable as files[].file_id anywhere file_url
or file_base64 is accepted. 25 MB per file. The response status is processing
until ingest finishes; a file may be referenced before it is ready.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Request body
multipart/form-data
| Property | Type | Required | Description |
|---|---|---|---|
file | string (binary) | Required | The file bytes. |
name | string | Optional | Display name. Defaults to the uploaded filename. |
purpose | string | Optional |
Responses
| Status | Description |
|---|---|
201 | The stored file. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
409 | The request is well formed; the resource is not in a state that allows it.… |
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 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X POST https://api.signclad.com/api/v1/files \
-H "X-Api-Key: $SIGNCLAD_API_KEY" Example response (201)
{
"id": "file_01J9K3P2S5N7Q8R1T2V3W4X5",
"name": "loan-agreement.pdf",
"mime": "application/pdf",
"size": 184320,
"status": "processing",
"pages_number": 0,
"created_at": "2026-09-09T17:44:10Z"
} GET /verify/{hash}
Verify a sealed file by hash Extension
Public and unauthenticated. Takes the SHA-256 of a PDF somebody has in their hands and
reports which sealed artifacts it matches, when each was sealed, whether its timestamp
still validates and how it was obtained, whether a daily anchor covers it, and the audit
chain head at that moment. The file itself is never uploaded: verify.signclad.com
hashes it in the browser and sends only the hash.
An unknown hash is a 200 with an empty matches array, not a 404: "this file is not
one of ours" is an answer, and a 404 here would also let somebody probe for which
hashes exist.
Matches completed, completed_no_audit and completed_lt, and names which in
matches[].artifact.
- Base URL
https://api.signclad.com/api/v1- Authentication
- None — this operation is public
Path parameters
| Name | Type | Description |
|---|---|---|
hash | string | Lowercase hex SHA-256 of the PDF being checked. |
Responses
| Status | Description |
|---|---|
200 | What the hash matches. Empty when nothing does. |
429 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X GET https://api.signclad.com/api/v1/verify/{hash} \
-H "X-Api-Key: $SIGNCLAD_API_KEY" Example response (200)
{
"matches": [
{
"document_id": "8f14e45f-ea8f-4b2c-9f0e-1b2c3d4e5f60",
"artifact": "completed",
"sealed_at": "2026-09-09T17:44:15Z",
"timestamp_valid": true,
"chain_head": "7d3f9a1c5b8e2046d1f3a5c7e9b0d2f4a6c8e0b2d4f6a8c1e3b5d7f9a0c2e4b6",
"timestamp": {
"status": "detached",
"attached_at": "2026-09-09T19:02:41Z",
"source": "completed"
},
"anchor": {
"anchored_on": "2026-09-09",
"root_sha256": "4b2c9f0e1b2c3d4e5f60a1b2c3d4e5f607d3f9a1c5b8e2046d1f3a5c7e9b0d2f4",
"timestamped": true
}
}
]
} DELETE /files/{id}/stored
Delete an unused stored file
Uses the same visibility rules as the stored-file picker. Returns 409 if any document, template, attachment, reusable asset, or saved history still references the file, including references outside the current workspace. Otherwise tombstones the row and queues retryable deletion of the original and derivatives on the recorded storage disk. A 204 confirms acceptance, not reclaimed bytes. Lost cleanup jobs are recovered by files:cleanup-unused.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Path parameters
| Name | Type | Description |
|---|---|---|
id | string |
Responses
| Status | Description |
|---|---|
204 | Queued for deletion. A 204 confirms acceptance, not reclaimed bytes: the objects themselves go on a retryable job. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
404 | No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative. |
409 | The request is well formed; the resource is not in a state that allows it.… |
429 | Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.… |
Example request
curl -X DELETE https://api.signclad.com/api/v1/files/{id}/stored \
-H "X-Api-Key: $SIGNCLAD_API_KEY" GET /labels
List labels Extension
Every label defined in the workspace, by name. Labels are the workspace's own filing
system: a document or a template carries any number of them, and
PUT /documents/{id}/labels and PUT /document_templates/{id}/labels are what put
them there.
The list carries id, name and color and nothing else; the create and update
responses return the whole stored row.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or Session
Responses
| Status | Description |
|---|---|
200 | Every label in the workspace. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
Example request
curl -X GET https://api.signclad.com/api/v1/labels \
-H "X-Api-Key: $SIGNCLAD_API_KEY" POST /labels
Create a label Extension
Names are trimmed and unique within the workspace, so the same label cannot be created
twice with different surrounding whitespace. A duplicate is 422, not a silent reuse.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or Session
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
name | string | Required | Trimmed before it is stored, and unique within the workspace. |
color | string or null | Optional | Six hex digits with a leading #, or null. |
Responses
| Status | Description |
|---|---|
201 | The stored label. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
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/labels \
-H "X-Api-Key: $SIGNCLAD_API_KEY" PATCH /labels/{id}
Rename or recolor a label Extension
name is required on every call — this is a replace of the label's own fields, not a
partial edit — and the uniqueness check ignores the label being edited, so saving a label
without changing its name is not a conflict.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or Session
Path parameters
| Name | Type | Description |
|---|---|---|
id | string | The label's id. |
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
name | string | Required | Trimmed before it is stored, and unique within the workspace. |
color | string or null | Optional | Six hex digits with a leading #, or null. |
Responses
| Status | Description |
|---|---|
200 | The stored label. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
404 | No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative. |
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 PATCH https://api.signclad.com/api/v1/labels/{id} \
-H "X-Api-Key: $SIGNCLAD_API_KEY" DELETE /labels/{id}
Delete a label Extension
Removes the label and unfiles every document carrying it. The documents themselves are untouched.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or Session
Path parameters
| Name | Type | Description |
|---|---|---|
id | string | The label's id. |
Responses
| Status | Description |
|---|---|
204 | Deleted. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
404 | No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative. |
Example request
curl -X DELETE https://api.signclad.com/api/v1/labels/{id} \
-H "X-Api-Key: $SIGNCLAD_API_KEY" PUT /documents/{id}/labels
Set a document's labels Extension
Replaces the document's whole label set with the ids given, so an empty array clears it.
label_ids must be present even when empty, and every id must already exist in this
workspace — this route files a document, it does not create labels.
Filing a document does not touch its sealed content, its revision, or its status, so it
is allowed at any point in a document's life, including after it has completed.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token or Session
Path parameters
| Name | Type | Description |
|---|---|---|
id | string (uuid) | The document's id. |
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
label_ids | array of string | Required | Ids of labels in this workspace. Duplicates are rejected. |
Responses
| Status | Description |
|---|---|
200 | The document's labels after the change. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
403 | Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, or a signer acting out of turn. meta.error always says which.… |
404 | No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative. |
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/documents/{id}/labels \
-H "X-Api-Key: $SIGNCLAD_API_KEY"