GET /api/v1/events catches anything the webhook missed.
Before you begin
- Store your API key in the
SAJN_API_KEYenvironment variable. - Have an HTTPS endpoint that sajn can reach. If you can’t expose one, see Without a webhook endpoint.
Don’t poll each document
A loop that callsGET /api/v1/documents/DOCUMENT_ID every few seconds until the status changes spends your rate limit on requests that return nothing new. The limit is shared by every API key and integration in your organization, so a busy poll can slow down the rest of your integration. One integration went from about 7,000 requests a day to fewer than 100 when it replaced polling with the steps below.
Get notified when a document is signed
1
Subscribe to the end states
Create a webhook for the events that end a document’s signing:Store the
secret from the response. To check each party’s progress as well, add document.party.signed. For every option, see Manage webhook endpoints.2
Download the signed PDF on document.completed
sajn fires
document.completed after it has sealed the signed PDF, so SIGNED is ready when the event arrives. document.fully_signed fires earlier, before the seal. Don’t download the signed file on it.The event’s data.object is the document. Verify the delivery’s signature, answer 2xx right away, and then download the files. For a complete handler, see Archive documents when they’re completed.3
Catch up with GET /api/v1/events
A webhook delivery can fail while your endpoint is down. Once an hour, read the events since your last run and pass each one to the same handler:Each event has the same shape as a webhook delivery, and its
id stays the same, so a handler that skips IDs it has seen processes each event once. The list reaches back 30 days. For the full loop with a watermark and paging, see Reconcile on a schedule.Without a webhook endpoint
If sajn can’t reach your server, readGET /api/v1/events on a schedule instead of polling each document. One request returns every document that finished since the last run, however many documents you have out for signing:
- Store the time of your last run as a watermark.
- Request events with
createdAfterset to the watermark minus a few minutes, and thetypefilter from the previous section. - Follow
nextCursoruntil it’snull, and handle each event. - Store the time when this run started as the new watermark.
Wait for the original PDF
A draft has noORIGINAL file. sajn generates it in the background when you send the document, and it’s ready when document.sent fires. For a QES document, and for some documents where a party picks products, sajn generates it after the parties have filled in their fields. Until then, GET /api/v1/documents/DOCUMENT_ID/files/ORIGINAL returns 409 INVALID_STATE, and GET /api/v1/documents/DOCUMENT_ID/files leaves it out.
Next steps
Webhook events
See every event and when it fires.
Replay and reconcile events
Read past events and retry deliveries.
Download documents
Download the sealed PDF, the original, and the journal.
Rate limits
See your limit and how to handle 429.

