Quickstart
This guide takes you from zero to your first completed signing request: create an API key, upload a PDF, and send it out for signature. Budget about ten minutes.
All endpoints live under https://api.smartdocs.de/api/v1 and return JSON. Every successful
response is wrapped in the same envelope — { "success": true, "data": …, "timestamp": … } — see
Conventions for the details.
Prefer no code? Automate SmartDocs from n8n with our official
n8n-nodes-smartdocsnode — start signing, react to completion, and download signed PDFs without writing a script.
1. Get an API key
API keys are created in the SmartDocs dashboard — there is no API endpoint for minting keys. Open your organization's settings, go to API keys, and create one:
- The full key (
sdk_live_…) is shown exactly once at creation. Copy it immediately and store it in a secret manager — SmartDocs keeps only a hash. - Each key is scoped to one organization and carries a role:
ADMINorMEMBER. This guide uploads PDFs and creates signing processes, which require an ADMIN key. - You can optionally set an expiry date when creating the key.
Read Authentication for scoping, rotation, and security guidance.
2. Make your first request
Send the key in the X-API-Key header (an Authorization: Bearer header works too):
curl https://api.smartdocs.de/api/v1/templates \
-H "X-API-Key: $SMARTDOCS_API_KEY"
A fresh organization has no templates yet, so you get an empty page back — inside the standard success envelope:
{
"success": true,
"data": {
"items": [],
"total": 0,
"page": 1,
"pageSize": 20
},
"timestamp": "2026-06-11T09:30:12.481Z"
}
If you see this, your key works. A 401 means the key is missing, invalid, expired, or revoked.
3. Upload a PDF
Uploads are a two-step, direct-to-storage flow: the API hands you a presigned URL, you PUT the
bytes straight to storage, then commit. File bytes never flow through the API itself.
Step 1 — initiate. Declare the file name and exact byte size (contentType is optional and
must be application/pdf when present):
curl -X POST https://api.smartdocs.de/api/v1/pdf-assets/uploads \
-H "X-API-Key: $SMARTDOCS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"fileName": "consulting-agreement.pdf",
"sizeBytes": 184302,
"contentType": "application/pdf"
}'
{
"success": true,
"data": {
"uploadId": "0d4f0a4e-6c1d-4b54-9d56-1f2f4f9b8a31",
"uploadUrl": "https://storage.example.com/organizations/…/pdf-assets/…?X-Amz-Signature=…",
"key": "organizations/1f9e2b7c-…/pdf-assets/0d4f0a4e-….pdf",
"contentType": "application/pdf",
"expiresAt": "2026-06-11T09:45:12.481Z"
},
"timestamp": "2026-06-11T09:30:12.481Z"
}
Step 2 — PUT the bytes. Upload to uploadUrl before expiresAt (the URL is valid for 15
minutes). The presigned URL is bound to the declared content type and byte count, so send exactly
what you declared:
curl -X PUT "$UPLOAD_URL" \
-H "Content-Type: application/pdf" \
--data-binary @consulting-agreement.pdf
Step 3 — commit. Finalize the upload. The API verifies the stored object's size, parses the PDF, and creates the asset:
curl -X POST https://api.smartdocs.de/api/v1/pdf-assets/uploads/0d4f0a4e-6c1d-4b54-9d56-1f2f4f9b8a31/commit \
-H "X-API-Key: $SMARTDOCS_API_KEY"
{
"success": true,
"data": {
"id": "9b2f8c34-5e1a-4f0b-8c5d-2a7e9d1c6b43",
"originalFileName": "consulting-agreement.pdf",
"mimeType": "application/pdf",
"sizeBytes": 184302,
"sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"pageCount": 4,
"createdAt": "2026-06-11T09:31:02.110Z",
"processing": {
"status": "QUEUED",
"jobId": "1042",
"startedAt": null,
"finishedAt": null,
"errorMessage": null
}
},
"timestamp": "2026-06-11T09:31:02.143Z"
}
Assets are deduplicated by content: committing a byte-identical PDF returns the existing asset instead of creating a duplicate.
4. Wait for processing
Preview and thumbnail artifacts are generated asynchronously. Poll the processing endpoint until
status is READY — the status moves QUEUED → PROCESSING → READY (or FAILED):
curl https://api.smartdocs.de/api/v1/pdf-assets/9b2f8c34-5e1a-4f0b-8c5d-2a7e9d1c6b43/processing \
-H "X-API-Key: $SMARTDOCS_API_KEY"
{
"success": true,
"data": {
"status": "READY",
"jobId": "1042",
"startedAt": "2026-06-11T09:31:03.502Z",
"finishedAt": "2026-06-11T09:31:06.778Z",
"errorMessage": null
},
"timestamp": "2026-06-11T09:31:08.012Z"
}
Starting a signing process from an asset that is not READY yet fails with a 409. If processing
ends in FAILED, errorMessage explains why and you can re-queue it via
POST /pdf-assets/{id}/processing/retry.
5. Start a signing process
Create a signing process directly from the asset. This example emails one external signer a hosted
signing link, authorized by the link alone (SES_LINK_ONLY):
curl -X POST https://api.smartdocs.de/api/v1/signing-processes \
-H "X-API-Key: $SMARTDOCS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"dispatchMode": "EMAIL",
"sourcePdfAssetId": "9b2f8c34-5e1a-4f0b-8c5d-2a7e9d1c6b43",
"subject": "Consulting agreement — please sign",
"message": "Hi Erika, please review and sign the agreement.",
"expiresAt": "2026-06-25T23:59:59.000Z",
"authPolicy": "SES_LINK_ONLY",
"signers": [
{
"signOrder": 1,
"name": "Erika Mustermann",
"email": "erika@example.com",
"roleLabel": "Client",
"locale": "de"
}
],
"fields": [
{
"assignedSignerSignOrder": 1,
"type": "SIGNATURE",
"label": "Client signature",
"page": 3,
"x": 72,
"y": 640,
"w": 180,
"h": 48,
"required": true
}
]
}'
A few rules worth knowing:
dispatchModeis one ofEMAIL,KIOSK, orCURRENT_USER. WithEMAIL, every external signer must include anemail— SmartDocs delivers the hosted signing link for you; your integration never builds or sends signing URLs itself.authPolicyisAES_OTP(the default when omitted) orSES_LINK_ONLY.AES_OTPrequires each external signer to pass an SMS one-time code, so those signers must includephoneE164— and SMS signing requires a paid plan.signOrdervalues must be unique and sequential starting at 1; signers sign in that order.- Field
typeis one ofTEXT,DATE,CHECKBOX, orSIGNATURE.pageis the zero-based page index;x,y,w,hposition the field on the page in PDF points. - Every field's
assignedSignerSignOrdermust reference one of the declared signers.
The process is created and sent in one step — there is no draft state. The response contains the new process with its signer slots and field definitions (truncated here to the most useful fields; the full payload also embeds the source asset metadata):
{
"success": true,
"data": {
"id": "31f0d4c9-8a2e-47f5-b1c3-6e9d0a5b7f21",
"status": "SENT",
"origin": "DIRECT",
"dispatchMode": "EMAIL",
"authPolicy": "SES_LINK_ONLY",
"subject": "Consulting agreement — please sign",
"expiresAt": "2026-06-25T23:59:59.000Z",
"sentAt": "2026-06-11T09:32:10.512Z",
"signerSlots": [
{
"id": "7d5a1b8e-3c4f-49a2-9e6b-0f8c2d1a5e74",
"signOrder": 1,
"roleLabel": "Client",
"name": "Erika Mustermann",
"email": "erika@example.com",
"status": "READY"
}
]
},
"timestamp": "2026-06-11T09:32:10.540Z"
}
Erika receives an email with her personal signing link. Track progress any time:
curl https://api.smartdocs.de/api/v1/signing-processes/31f0d4c9-8a2e-47f5-b1c3-6e9d0a5b7f21 \
-H "X-API-Key: $SMARTDOCS_API_KEY"
The process status moves SENT → IN_PROGRESS → COMPLETED (or DECLINED, VOIDED,
EXPIRED). Once completed, the process carries the final signed PDF and a completion certificate.
Starting from a published template instead
If your document is already a published template, use POST /templates/{id}/start-signing. The
template version already defines the signer roles and signing fields, so the request supplies
runtime values and concrete signers rather than page coordinates:
curl -X POST https://api.smartdocs.de/api/v1/templates/4d9a1e37-7b7e-45c2-a401-4de6cb8268a0/start-signing \
-H "X-API-Key: $SMARTDOCS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"data": {
"customer": {
"name": "Erika Mustermann",
"memberNo": 4711
},
"contractDate": "2026-06-15"
},
"fieldPrefills": [
{ "fieldKey": "birthDate", "value": "1990-05-01" },
{ "fieldKey": "city", "value": "Berlin" },
{ "fieldKey": "marketingConsent", "value": true }
],
"signers": [
{
"roleKey": "customer",
"name": "Erika Mustermann",
"email": "erika@example.com",
"phoneE164": "+4915112345678",
"locale": "de"
}
],
"expiresAt": "2026-06-25T23:59:59.000Z",
"policy": "EMAIL_AES_OTP",
"subject": "Membership agreement"
}'
Use data for values filled by the sender before the document is sent. In the dashboard start
wizard this is the Prefill step. In an HTML template, data fills Liquid expressions such as
{{ customer.name }} and can control conditional blocks. In a PDF template, data feeds fields
that the PDF editor marks as Sender fields.
Use fieldPrefills for signer-editable field defaults. In the PDF editor, copy the field's
API field key from a Signer field's Additional settings. In the HTML editor, use the field
ID / data-sd-field value. The dashboard start wizard does not currently ask for these
per-send signer defaults, so this is mainly for API integrations. If the same value should be
printed in the document and also verified by the signer in an editable field, send it in both
data and fieldPrefills.
TEXT prefills accept strings or numbers, DATE prefills use yyyy-mm-dd or %TODAY%,
CHECKBOX prefills use booleans, and SIGNATURE fields cannot be prefilled. For HTML templates,
optional fields whose data-sd-field marker is removed by Liquid are skipped; required fields with
missing markers return 400.
6. Download the signed PDF
Once the process is COMPLETED, fetch time-limited download URLs for the signed document and the
completion certificate — for example to store a copy in your CRM:
curl https://api.smartdocs.de/api/v1/signing-processes/31f0d4c9-8a2e-47f5-b1c3-6e9d0a5b7f21/files \
-H "X-API-Key: $SMARTDOCS_API_KEY"
{
"success": true,
"data": {
"signingProcessId": "31f0d4c9-8a2e-47f5-b1c3-6e9d0a5b7f21",
"status": "COMPLETED",
"completedAt": "2026-06-12T14:02:51.913Z",
"signedDocument": {
"pdfAssetId": "4c8e2f6a-1b3d-4e7f-9a0c-5d2b8e1f7a64",
"fileName": "Consulting agreement — please sign - signiert.pdf",
"url": "https://storage.example.com/…?X-Amz-Signature=…",
"expiresAt": "2026-06-13T14:05:00.000Z"
},
"completionCertificate": {
"pdfAssetId": "8a1d5c3b-7e2f-4a9c-b0e6-3f4d1a8c5b72",
"fileName": "Consulting agreement — please sign - Zertifikat.pdf",
"url": "https://storage.example.com/…?X-Amz-Signature=…",
"expiresAt": "2026-06-13T14:05:00.000Z"
}
},
"timestamp": "2026-06-12T14:05:00.121Z"
}
- The URLs are presigned and expire (24 hours by default). Fetch the bytes directly from the URL — no API authentication on that request. Need a fresh link later? Just call the endpoint again; it is idempotent and cheap.
- Calling it before the process is
COMPLETEDreturns a409with codeSIGNING_PROCESS_NOT_COMPLETED. - Download filenames are localized to your organization's default language.
Rather than polling for COMPLETED, register a webhook (organization settings → Webhooks, or
POST /webhooks) and react to the signing.completed event — its payload links straight to this
files endpoint. See Core Concepts for the event list and signature verification.
Next steps
- Authentication — key scoping, rotation, and security best practices.
- Core Concepts — templates, signing processes, signers, and the audit trail.
- Conventions — envelopes, error codes, rate limits, and pagination.
- API Reference — every endpoint, parameter, and schema.