Documentation Index
Fetch the complete documentation index at: https://docs.sajn.se/llms.txt
Use this file to discover all available pages before exploring further.
Onboarding Signing Flow
A common pattern when building a product on top of sajn is to collect a signed document as part of account signup or onboarding — a terms of service, a data processing agreement, a broker authorization, a membership contract. The user fills in a form in your app, signs inline, and is dropped back into your flow without ever seeing an email. This concept explains how the pieces fit together. Each piece links to its own reference.The Pattern
The flow has two tracks running in parallel:- User-facing: your form → signing page → redirect back to your app. The user perceives one continuous signup.
- Server-to-server: webhook → PDF download → archive. This is how you get a durable copy of the signed document, independent of whatever the browser does.
Prerequisites
Before wiring this up:- A template with FORM fields that have stable keys (e.g.
full_name,company_number,address). Keys are how you fill the fields programmatically — unlike field IDs, they survive template edits. - A webhook endpoint subscribed to
DOCUMENT_COMPLETED. See Webhooks. - A redirect URL in your app that finishes the onboarding (e.g.
/onboarding/done).
Step 1 — Collect input from the user
The user fills in your signup form. Nothing sajn-specific here — just capture the values you’re going to push into the template: name, email, org number, whatever your document needs.Step 2 — Create the document from a template
When the user submits the form, create a document from your template and include the signer inline. The critical bit isdeliveryMethod: "NONE" — this tells sajn not to send an email. You’re going to show the signing page yourself.
externalIdlinks the sajn document back to the signup in your own system. When the webhook fires, you’ll use this to find the user.redirectEnabled+redirectUrlsend the user back to your app after signing. The{documentId}and{signerId}placeholders are replaced with real values. See Redirect URL.deliveryMethod: "NONE"suppresses the email. The signing URL still exists — you’ll fetch it in Step 4.
documentId and signerId.
Step 3 — Fill the form fields
For each FORM field with a key, issue a PATCH usingkey:<fieldKey> instead of a field ID:
Fields without keys can’t be filled this way. If a template field isn’t filling, check that the template has a key set on that field.
Step 4 — Send the document and fetch the signing URL
POST /api/v1/documents/{id}/send moves the document from DRAFT to PENDING. Because every signer has deliveryMethod: "NONE", no emails go out. Then fetch the signing URL for the signer:
signingUrl. Return this to your frontend and either redirect the browser to it or open it in an embedded iframe (see Embedding).
Step 5 — User signs and is redirected
The user signs on sajn’s hosted page (or inside your embed). When they finish, sajn redirects to the URL you configured in Step 2, with the placeholders filled in:Step 6 — Webhook fires and you archive the PDF
When the document is sealed, sajn POSTsDOCUMENT_COMPLETED to your webhook. This is where you get the authoritative signal. Download the PDF (with the audit certificate) and store it:
Why this shape?
A few design choices worth calling out:Why deliveryMethod: NONE instead of EMAIL?
Why deliveryMethod: NONE instead of EMAIL?
During onboarding the user is already in your app. Emailing them a link and asking them to check their inbox breaks the flow and drops conversion.
NONE lets you keep them in-session.For signers who aren’t present — a counterparty, a supervisor — use EMAIL or SMS on that specific signer. Delivery method is per-signer, so you can mix them.Why templates instead of generating the document inline?
Why templates instead of generating the document inline?
Templates let non-developers own the document content. They also give you stable field keys — so your code fills
full_name regardless of how the legal text around it shifts over time.If your document is truly dynamic (generated from user input), you can also create documents directly with file uploads or inline content, but you lose the template’s stability.Why both redirect URL and webhook?
Why both redirect URL and webhook?
They answer different questions.
- Redirect URL answers “what does the user see next?” It runs in the browser, so it’s subject to network drops and closed tabs.
- Webhook answers “is this signup actually complete?” It runs server-to-server, with request logs you can inspect in the dashboard. It’s the one that should unlock downstream state (activate account, provision resources, bill the customer).
What about retries if the webhook fails?
What about retries if the webhook fails?
sajn does not automatically retry failed webhook deliveries. Failures are logged for 72 hours in the dashboard and organization members are notified in-app.If your archival logic is critical, consider also running a reconciliation job that periodically lists documents (
GET /api/v1/documents) with status COMPLETED and checks that you’ve archived each one. Using externalId makes this join trivial.BankID vs Drawing signature in onboarding?
BankID vs Drawing signature in onboarding?
If you need to verify who signed — for KYC, regulated contracts, or anything where identity matters later — use
BANKID (requires Swedish SSN). For simple terms-of-service style acceptance, CLICK_TO_SIGN or DRAWING is lighter and has no SSN prerequisite. See Signing Methods.Putting it together
End-to-end pseudocode for a signup handler:AWAITING_SIGNATURE to ACTIVE once the signed PDF is archived.
Next Steps
Templates & Forms
Structure a template with field keys
Redirect URL
Full reference for post-signing redirects
Webhooks
Subscribe to DOCUMENT_COMPLETED
Downloading Signed Documents
Archive the signed PDF with audit trail
Embedding
Show the signing page inside your app
Signing Methods
Choose BankID, Drawing, or Click-to-Sign

