- Your CRM calls
sendContract(deal). The service creates a document from a template, fills in the deal’s values, sets the customer as the signing party, and sends the document. - sajn calls your webhook endpoint with
document.completedwhen the sealed PDF is ready. The service downloads the PDF and updates the deal.
Before you begin
- Node.js 18 or later, and Express:
npm install express. - An API key in the
SAJN_API_KEYenvironment variable. To create one, go to workspace settings in the sajn app, then Utvecklare (Developer) > API-nycklar (API keys). - A template with a party named
Customerand FORM fields with the keyscustomer-name,org-number, andcontract-value. Store its ID inSAJN_TEMPLATE_ID. For more information, see Create documents from templates. - A public HTTPS URL for the webhook endpoint, such as
https://crm.example.com/webhooks/sajn.
Build the service
1
Subscribe to completed documents
Create the webhook once, and store the
secret from the response, which starts with whsec_, in SAJN_WEBHOOK_SECRET. sajn returns the secret only in this response:2
Write a small API client
Save the following file as
sajn.js. It sends the version header on every request, throws on errors with the code and requestId, and takes an optional idempotency key:3
Create and send the contract
Save the following file as The create request returns the whole document, including its
send-contract.js. Each request has an idempotency key derived from the deal, so retrying sendContract for the same deal doesn’t create a second contract:parties, so the service finds the customer’s party without another request. Store the returned document ID on the deal.4
Handle the webhook
Save the following file as All three events carry the document in
server.js. It verifies the Standard Webhooks signature over the raw body, answers right away, and then updates the deal:data.object, in the shape that GET /api/v1/documents/:id returns. The handler deduplicates on the event id, which stays the same across retries. The url from GET /api/v1/documents/:id/files/SIGNED expires at expiresAt, so download the file right away. For more information about the signature headers, see Verify webhook signatures.Run it
Start the server withnode server.js, and call sendContract from your CRM’s deal-stage hook with a deal object such as the following:
contracts/deal-12345.pdf appears and the server logs the deal update.
Handle errors
- An error thrown by
sajnincludes thecodeandrequestId. Branch oncode, and logrequestIdso sajn support can find the request. For what each code means, see Errors. 409 APPROVAL_REQUIREDon send: the API key’s user needs approval to send. Request it withPOST /api/v1/approval-requests. When the request is approved, sajn sends the document for signing.Values not written: a key doesn’t exist on the template (NOT_FOUND), or a value doesn’t match the field’s type (VALIDATION_FAILED).- If your endpoint is down, sajn retries the delivery. For more information, see Delivery and retries.

