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}/completed/download
- 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
- POST /abuse/report
26 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}/completed/downloadDownload the completed PDF from a signed email link - 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 - POST
/abuse/reportReport a document
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
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
status | array of string | Optional | One or more document statuses. Repeat the parameter to pass several. |
label | string | Optional | Only records carrying this label. |
recipient_email | string (email) | Optional | Only documents with a recipient at this address. |
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. |
test_mode | boolean | Optional | Restrict to test-mode or live documents. Omitted returns both. |
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.… |
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
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
files | array of object | Required | |
recipients | array of object | Required | |
allow_decline | boolean | Optional | |
allow_reassign | boolean | Optional | |
api_application_id | string (uuid) | Optional | Branding and embed origins to use for this document. |
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. |
checkbox_groups | array of object | Optional | |
conditional_rules | array of object | Optional | |
copied_contacts | array of object | Optional | |
custom_requester_email | string (email) | Optional | Reply-to address for the invitation. |
custom_requester_name | string | Optional | Name the invitation comes from. |
decline_redirect_url | string (uri) | Optional | Where a signer lands after declining. |
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 emails 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 | object | Optional | Whether the signer must prove who they are with a government ID before signing, and through which provider. Set on a document for everybody, or on a single recipient. provider is absent, not null, when it was never named — the account default applies. |
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 | Optional | Body of the signing invitation. A safe subset of HTML is allowed. |
metadata | object | Optional | Up to 50 key/value pairs stored with the record and returned unchanged. Keys are under 40 characters, values under 500, and values must be strings — encode anything else yourself. |
name | string | Optional | Internal name. Defaults to the first file's name. |
redirect_url | string (uri) | Optional | Where a signer lands after finishing. |
reminders | boolean | Optional | Automatic reminders on days 3, 6, and 10. |
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 | Created. |
400 | The request body could not be parsed as JSON. |
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, an unenrolled second factor, 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/9c8f2b1a4d6e?token=eyJhbGciOi...",
"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
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, an unenrolled second factor, 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/sign/embedded/8f14e45f?token=eyJhbGciOi...",
"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/f7cec8bea2?token=eyJhbGciOi...",
"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.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token
Path parameters
| Name | Type | Description |
|---|---|---|
id | string (uuid) | The document's id. |
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
allow_decline | boolean | Optional | |
allow_reassign | boolean | Optional | |
api_application_id | string (uuid) | Optional | Branding and embed origins to use for this document. |
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. |
checkbox_groups | array of object | Optional | |
conditional_rules | array of object | Optional | |
copied_contacts | array of object | Optional | |
custom_requester_email | string (email) | Optional | Reply-to address for the invitation. |
custom_requester_name | string | Optional | Name the invitation comes from. |
decline_redirect_url | string (uri) | Optional | Where a signer lands after declining. |
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 emails 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 | object | Optional | Whether the signer must prove who they are with a government ID before signing, and through which provider. Set on a document for everybody, or on a single recipient. provider is absent, not null, when it was never named — the account default applies. |
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 | Optional | Body of the signing invitation. A safe subset of HTML is allowed. |
metadata | object | Optional | Up to 50 key/value pairs stored with the record and returned unchanged. Keys are under 40 characters, values under 500, and values must be strings — encode anything else yourself. |
name | string | Optional | Internal name. Defaults to the first file's name. |
recipients | array of object | Optional | |
redirect_url | string (uri) | Optional | Where a signer lands after finishing. |
reminders | boolean | Optional | Automatic reminders on days 3, 6, and 10. |
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.… |
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
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, an unenrolled second factor, 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 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
Path parameters
| Name | Type | Description |
|---|---|---|
id | string (uuid) | The document's id. |
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
allow_decline | boolean | Optional | |
allow_reassign | boolean | Optional | |
api_application_id | string (uuid) | Optional | Branding and embed origins to use for this document. |
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. |
copied_contacts | array of object | Optional | |
custom_requester_email | string (email) | Optional | Reply-to address for the invitation. |
custom_requester_name | string | Optional | Name the invitation comes from. |
decline_redirect_url | string (uri) | Optional | Where a signer lands after declining. |
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 emails 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 | object | Optional | Whether the signer must prove who they are with a government ID before signing, and through which provider. Set on a document for everybody, or on a single recipient. provider is absent, not null, when it was never named — the account default applies. |
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 | Optional | Body of the signing invitation. A safe subset of HTML is allowed. |
metadata | object | Optional | Up to 50 key/value pairs stored with the record and returned unchanged. Keys are under 40 characters, values under 500, and values must be strings — encode anything else yourself. |
name | string | Optional | Internal name. Defaults to the first file's name. |
redirect_url | string (uri) | Optional | Where a signer lands after finishing. |
reminders | boolean | Optional | Automatic reminders on days 3, 6, and 10. |
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.… |
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.
- Base URL
https://api.signclad.com/api/v1- Authentication
- API key or OAuth 2.1 access token
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. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
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. |
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, Pending, or Bounced, and only for recipients who have not started
signing. 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
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.… |
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
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.… |
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. |
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
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. |
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, an unenrolled second factor, 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?expires=1789050000&signature=...",
"audit_trail_url": "https://files.signclad.com/audit/8f14e45f-ea8f-4b2c-9f0e-1b2c3d4e5f60.json?expires=1789050000&signature=...",
"expires_at": "2026-09-09T18:00:00Z"
} GET /documents/{id}/completed/download
Download the completed PDF from a signed email link Extension
The completed copy, for whoever it was emailed to. Unauthenticated — the signature in
the query string is the whole credential, which is what makes it usable by a signer, who
has no Signclad account and no session.
The HMAC covers the document id, the audience and the expires value together, so a
forwarded link cannot be re-aimed at another document, another recipient, or a later
expiry. It is minted by the completed-copy email and nowhere else; there is no endpoint
that issues one on request.
Only the canonical completed artifact is served. file_format, audit_only,
audit_page and the long-term-validation substitution are all choices for
GET /documents/{id}/completed_pdf, which takes a credential and can afford them.
Every failure is the same 404, byte-identical to the one for a document that does not
exist: a bad signature, a tampered audience, an expired link, an unsealed document and
an unknown id are indistinguishable from outside.
- Base URL
https://api.signclad.com/api/v1- Authentication
- None — this operation is public
Path parameters
| Name | Type | Description |
|---|---|---|
id | string (uuid) | The document's id. |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
audience | string | Required | Who the copy was addressed to — a recipient id, an email address, or copy. Covered by the signature. |
expires | integer (int64) | Required | Unix timestamp after which the link stops working. Covered by the signature. |
signature | string | Required | HMAC-SHA256 over the path, audience and expires. |
Responses
| Status | Description |
|---|---|
200 | The sealed PDF bytes. |
404 | Bad or expired signature, tampered audience, unknown document, or a document that is not sealed. All of them share this body. |
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/download \
-H "X-Api-Key: $SIGNCLAD_API_KEY" 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
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.… |
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.… |
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 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
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. |
Responses
| Status | Description |
|---|---|
200 | A page of events, oldest first. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
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
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.… |
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
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.… |
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
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.… |
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
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.… |
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
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 | How long the single-use exchange window stays open. |
Responses
| Status | Description |
|---|---|
201 | A new signing URL. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
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/9c8f2b1a4d6e?token=eyJhbGciOi...",
"signing_url": "https://app.signclad.com/sign/9c8f2b1a4d6e",
"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. Present it as
Authorization: Bearer <token> against /signer/*, exactly as a token from
POST /signer/exchange.
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
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, an unenrolled second factor, 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}/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
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 | |
start | string | Optional | Which view the builder opens on. |
Responses
| Status | Description |
|---|---|
201 | A new builder URL. |
401 | Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.… |
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
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 |
|---|---|---|---|
strategy | string | Required | 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.… |
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. |
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.… |
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
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
search | string | Optional | |
page | integer | Optional |
Responses
| Status | Description |
|---|---|
200 | A page of reusable files |
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
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.… |
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. |
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
Path parameters
| Name | Type | Description |
|---|---|---|
id | string |
Responses
| Status | Description |
|---|---|
204 | File queued for deletion |
404 | File not found or not accessible |
409 | File is still in use; remove all uses before deletion |
Example request
curl -X DELETE https://api.signclad.com/api/v1/files/{id}/stored \
-H "X-Api-Key: $SIGNCLAD_API_KEY" POST /abuse/report
Report a document Extension
Public, unauthenticated: the reporter is a stranger on a signing page who thinks the
document is phishing. Always answers 202 with the same message whether or not the document
id resolved — a report endpoint that confirmed which ids exist would be a lookup service.
Rate limited per document as well as per IP, and the throttle fires before the captcha, so a
flood never burns captcha tokens.
- Base URL
https://api.signclad.com/api/v1- Authentication
- None — this operation is public
Request body
application/json
| Property | Type | Required | Description |
|---|---|---|---|
document_id | string | Required | |
reason | string | Required | |
captcha_token | string or null | Optional | |
detail | string or null | Optional | |
reporter_email | string or null | Optional |
Responses
| Status | Description |
|---|---|
202 | Received. The same answer for an id that does not exist. |
422 | errors.captcha_token reads The captcha could not be verified. Please try again. |
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/abuse/report \
-H "X-Api-Key: $SIGNCLAD_API_KEY"