- In the browser: your form, then the signing page, then a redirect back to your app. The user sees one continuous signup.
- Server to server: the
document.completedwebhook event, then the PDF download, then account activation. This track is the source of truth, because it doesn’t depend on the user’s browser.
Before you begin
- Store your API key in the
SAJN_API_KEYenvironment variable. To create a key, go to workspace settings in the sajn app, then Utvecklare (Developer) > API-nycklar (API keys). - Create a template with the agreement’s content and FORM fields whose keys match your form, such as
full-nameandorg-number. For more information, see Templates and forms. - Subscribe a webhook endpoint to
document.completed. For more information, see Webhooks. - Have a page in your app that finishes the onboarding, such as
https://app.example.com/onboarding/done.
Build the flow
1
Create the document from the template
When the user submits your form, create a document from the template with the user as the only party. Replace
"deliveryMethod": "NONE" stops sajn from emailing an invitation, because you show the signing page yourself:TEMPLATE_ID with your template’s ID. The response is the document. Store its id and parties[0].id.externalId links the document to the signup in your system, so the webhook handler can find the user. For the redirect placeholders, see Redirect after signing.2
Optional: Match the national ID
To make BankID check that the person who signs is the person who signed up, set the party’s national identity number before you send:Replace
NATIONAL_ID with the personal identity number the user entered. The response is the party. You can set nationalId only while the document is a DRAFT.3
Fill in the form values
Write every value in one request with Fill in values on a document. The keys must match the keys on the template’s FORM fields:The response’s
results array has one entry per key, with success and, when a value fails, an error with code, message, and userMessage. remaining lists the keys of required values that are still empty, and values lists every value on the document. To see every key on the document, send a GET request to the same path.4
Send the document and get the signing URL
Send the document. Because the party has Return
"deliveryMethod": "NONE", no email goes out. Then get the party’s signing URL:signingUrl from the second response to your frontend, and redirect the browser to it. To show the signing page inside your app instead, see Embedded signing. The URL lets anyone sign as the party, so don’t log it.5
Show the result after the redirect
After the user signs, sajn redirects the browser to your
redirectUrl, such as https://app.example.com/onboarding/done?doc=cm4k2x9p10001abcd1234efgh. Show a confirmation screen, but don’t activate the account here: the user can close the tab before the redirect, and anyone can open the URL.6
Activate the account from the webhook
When the document is sealed, sajn sends
document.completed to your endpoint. Verify the signature, find the signup by the document’s externalId in data.object, archive the PDF, and activate the account:SAJN_WEBHOOK_SECRET is the webhook’s whsec_ secret, returned when you create the webhook or rotate its secret. For timestamp checks and retries, see Verify webhook signatures and Delivery and retries.Design choices
- Why
NONEinstead ofEMAIL? The user is already in your app. An email detour costs conversions. For a party who isn’t present, such as a co-signer, useEMAILorSMSon that party; the delivery method is per party. - Why a template? The legal team edits the content in the sajn app without a deploy, and the FORM field keys stay the same when the text around them changes.
- Why both a redirect and a webhook? The redirect decides what the user sees next. The webhook decides whether the signup is complete. With only the redirect, a closed tab leaves an orphaned signup. With only the webhook, the user sees no confirmation.
- Which signing method? For identity you rely on later, such as KYC, use an eID such as
SE_BANKID. For accepting terms of service,CLICK_TO_SIGNorDRAWINGhas no eID requirement. For more information, see Set the signing method.
COMPLETED documents and checks each externalId. For an example, see Sync all completed documents nightly.
Handle errors
400 VALIDATION_FAILEDon create: a party ordocumentMetafield is invalid. Readissues.results[].success: falseonfield-values:error.codeisNOT_FOUNDwhen the key doesn’t exist, andVALIDATION_FAILEDwhen the value doesn’t match the field’s type or options. Fix the value; the other values are already written.404 NOT_FOUND: the template or the document doesn’t exist in the workspace that the API key belongs to.resourcenames which one.409 APPROVAL_REQUIREDon send: the API key’s user needs an approval to send. Give the user the permission to send without approval, or request an approval as described in Send a document for signing.
Next steps
Embedded signing
Show the signing page inside your app.
Templates and forms
Build a template with field keys.
Download documents
Archive the sealed PDF and the journal.
Verify identity with sajn ID
Verify who the user is before they sign.

