Skip to main content

Sign API Best Practices

Best practices for building reliable, efficient signing workflows with the Skribble Sign API.

API Version Selection

Use Sign API v2 for all production integrations — it is the current stable version.

Sign API v3 is available as a preview and is a great opportunity to test upcoming features early and share feedback with the Skribble team before general availability:

  • Draft workflow — build signature requests before inviting signers
  • Multi-document support — up to 50 documents per request
  • Signer groups and flexible signer management
Preview — Subject to Change

Sign API v3 is not yet stable. Breaking changes may occur before GA. Use it in non-production environments and share your feedback with us.

Signature Request Workflow

In v2, a signature request is created and goes directly to OPEN — signers are notified immediately. Include the document inline in the creation call, either as a URL reference or Base64-encoded content, or reference a previously uploaded document by ID.

OPEN → SIGNED/DECLINED/WITHDRAWN

Option 1 — Document via URL

POST /signature-requests
{
"title": "Contract Agreement",
"message": "Please sign this contract.",
"document": {
"url": "https://your-app.com/documents/contract.pdf",
"filename": "contract.pdf"
},
"signatures": [
{ "signer_email_address": "alice@example.com" }
]
}

Option 2 — Document as Base64

POST /signature-requests
{
"title": "Contract Agreement",
"message": "Please sign this contract.",
"document": {
"content": "<base64-encoded-pdf>",
"filename": "contract.pdf"
},
"signatures": [
{ "signer_email_address": "alice@example.com" }
]
}

Option 3 — Pre-uploaded document by ID

Upload the document first, then reference it by ID:

POST /documents
{
"content": "<base64-encoded-pdf>",
"filename": "contract.pdf"
}

Then reference the returned id in the signature request:

POST /signature-requests
{
"title": "Contract Agreement",
"document_id": "doc-aaa-111",
"signatures": [
{ "signer_email_address": "alice@example.com" }
]
}
v3 Draft Workflow

Sign API v3 (preview) introduces a document-first, explicit-initiation model with multi-document support and signer groups. See Migrating from v2 → Draft Workflow for the full flow.

Document Handling

Upload Best Practices

  1. Validate before upload - Ensure documents are valid PDFs
  2. Use meaningful filenames - They appear in the signing interface
  3. Optimize file size - Large files slow down the signing experience
  4. Base64 encode properly - Documents must be Base64-encoded
// Upload a document
const response = await api.post('/documents', {
title: 'Contract.pdf',
content_type: 'application/pdf',
content: base64EncodedPdf
});

Supported Attachment Types

  • PDF documents
  • Microsoft Office formats (Word, Excel, PowerPoint)
  • Images (JPEG, PNG)
  • Plain text files

Signer Management

Adding Signers

You can add signers in two ways:

1. By Email (Skribble account required):

{
"signer_email_address": "signer@example.com"
}

2. With Identity Data (no account required):

{
"signer_identity_data": {
"email_address": "signer@example.com",
"first_name": "John",
"last_name": "Doe",
"mobile_number": "+41791234567",
"language": "en"
}
}

Signer Modification Rules

  • In v2, signers are part of the creation call — once the request is OPEN, you cannot add or remove signers
  • Once any signer has signed, you cannot modify the request
  • Use DELETE /signature-requests/{id} to withdraw an open request and recreate it if changes are needed

Customizing the Signing URL

When a signature request is created, each signer receives a signing_url. This URL forwards the signer to a preview page of the PDF document where they can start the signature process as usual.

You can append query parameters to the signing_url to control the signer's experience after completing or declining the signature process.

ParameterTypeDescription
exitURLstring (URL-encoded)Optional URL to redirect after the signature process finished or declined. Example: https%3A%2F%2Fgoogle.com
errorURLstring (URL-encoded)Optional URL to redirect in case of an error. Example: https%3A%2F%2Fbing.com
hidedownloadbooleanOptional flag to hide and disable the download document option. Example: true
redirectTimeoutintegerOptional timeout in seconds before the redirect is executed. Example: 20
langstringOptional language code to display the signing page in a specific language. Supported values: en (default), de, fr. Example: lang=fr
overlaybooleanOptional flag to show or hide the Skribble overlay on the signing page.
const signingUrlWithParams = `${signer.signing_url}?exitURL=${encodeURIComponent('https://your-app.com/done')}&lang=de&hidedownload=true`;
note

Missing signer fields like first name and last name can be adjusted by the signer directly through the Skribble signing interface — they are not required to be set upfront via the API.

Signature Qualities

Choose the appropriate signature quality based on your requirements:

QualityDescriptionUse Case
SESSimple Electronic SignatureLow-risk documents, internal approvals
AESAdvanced Electronic SignatureStandard contracts, agreements
QESQualified Electronic SignatureHigh-value contracts, regulatory requirements
DEMOTest signatureDevelopment and testing

Legislation Compliance

LegislationRegionStandard
ZERTESSwitzerlandSwiss Federal Act on Electronic Signatures
EIDASEuropean UnionEU Regulation on electronic identification

Callbacks and Webhooks

Setting Up Callbacks

Configure callbacks to receive real-time updates:

{
"callback_success_url": "https://your-app.com/webhooks/skribble/success",
"callback_error_url": "https://your-app.com/webhooks/skribble/error",
"callback_update_url": "https://your-app.com/webhooks/skribble/update"
}

Callback Types

TypeTriggered When
SUCCESSAll signers have signed
UPDATEA signer has signed (partial completion)
ERRORAn error occurred
START_SIGNA signer started signing
INITIATERequest was initiated
IDENT_ERRORIdentification error

Callback Best Practices

  1. Acknowledge quickly - Return 200 within 5 seconds
  2. Process asynchronously - Queue the work, respond immediately
  3. Handle idempotency - The same callback may be delivered multiple times
  4. Verify authenticity - Validate callback requests come from Skribble

Reminders

Sending Manual Reminders

POST /signature-requests/{id}/remind

Reminder Limitations

  • Rate limit: One reminder per signer per hour
  • Only works for signers who haven't completed signing
  • Consider using automatic reminders for better UX

Sealing Documents

For documents that need an organizational seal rather than personal signatures:

const sealedDoc = await api.post('/seal', {
content: base64EncodedPdf,
account_name: 'your-seal-account'
});

SendTo Feature

For simple one-off document signings without the full signature request flow. No API key or authentication is required — this endpoint is publicly accessible.

info

Because no credentials are needed, SendTo is ideal for letting end-users or third parties trigger a signing directly from your application without exposing any API keys.

// Create a send-to request
const sendTo = await api.post('/sendto', {
content: base64EncodedPdf,
signer_email_address: 'signer@example.com',
title: 'Document to Sign'
});

// Track status
const status = await api.get(`/sendto/${sendTo.id}/track`);

// Download when complete
const signedDoc = await api.get(`/sendto/${sendTo.id}/download`);

SendTo Limitations

  • Documents expire after 90 days
  • Unclaimed requests expire after 1 day
  • Simpler than full signature requests but less flexible

Performance Tips

  1. Batch document uploads - Upload documents in parallel before creating requests
  2. Cache authentication tokens - Reuse tokens until they expire
  3. Use pagination - When listing requests, use page_number and page_size
  4. Poll efficiently - Use callbacks instead of polling when possible

Common Pitfalls

Avoid These Mistakes

  1. Missing required fields - Ensure all signers and document details are complete in the creation call, since v2 requests go directly to OPEN
  2. Ignoring status - Always check status_overall before performing actions
  3. Not handling callbacks - Rely on callbacks rather than polling for status updates
  4. Hardcoding URLs - Use environment-specific base URLs

Status Checking

Always verify the current status before operations:

const request = await api.get(`/signature-requests/${id}`);

if (request.status_overall === 'OPEN') {
// Waiting for signatures — can send reminders
} else if (request.status_overall === 'SIGNED') {
// All signers signed — download the signed document
} else if (request.status_overall === 'DECLINED') {
// A signer declined — handle accordingly
} else if (request.status_overall === 'WITHDRAWN') {
// Request was withdrawn
}