Skip to main content
In this recipe, you write a job that runs every night and copies each document completed since the last run into your archive: the sealed PDF, the signing journal, and a JSON file with the document’s details. It’s the safety net next to webhooks: if your webhook endpoint missed a document.completed delivery, the next night’s run catches the document.

Before you begin

  • Python 3.9 or later, and the requests package: pip install requests.
  • An API key in the SAJN_API_KEY environment variable. To create one, go to workspace settings in the sajn app, then Utvecklare (Developer) > API-nycklar (API keys). The job archives the documents of the key’s workspace.
  • A scheduler, such as cron, that can run the job once a night.

Build the job

1

Write the job

Save the following file as nightly_sync.py. It reads the last run’s timestamp from last-sync.txt, lists documents completed since then with a cursor, archives each one, and saves the new timestamp only after every document succeeded:
The job works as follows:
  • completedAfter includes its boundary, and the job stores the time the run started, so a document completed during the run is archived again the next night. Writing to a fixed folder per document makes that harmless.
  • The job passes each response’s nextCursor as cursor until hasMore is false. The cursor keeps the pages stable while documents change.
  • Each file url expires at the response’s expiresAt, so the job downloads it right away.
  • If any document fails, the job stops before it saves the timestamp, so the next run retries the same window.
  • Each document costs three API requests, plus its share of the list pages. For your plan’s limits, see Rate limits and quotas.
2

Run it once by hand

The first run has no last-sync.txt, so it archives every completed document. The output is similar to the following:
3

Schedule it

Add a cron entry that runs the job at 02:00 every night:
Replace API_KEY with your API key, or load it from your secret store instead.

Handle errors

  • 409 INVALID_STATE on a file: sajn hasn’t produced the file yet. sajn generates the journal shortly after it seals the document. The job stops, and the next run retries the document.
  • 401 UNAUTHORIZED: the key is invalid or was revoked.
  • 400 VALIDATION_FAILED: a malformed completedAfter in last-sync.txt. The value must be an ISO 8601 date-time.
For the error shape and every code, see Errors.