> ## 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.

# Webhook events

> Every webhook event that sajn sends, when it fires, and the data it carries

Subscribe an endpoint to an event by adding its type to the webhook's `events`. Event types are dotted lowercase names: the resource, an optional sub-resource, and what happened, such as `document.party.signed`. This page lists every type, grouped by resource. Each event links to its reference page, which has the full schema, and each group links to its data on [Webhook payloads](/webhooks/payloads).

Every event appears in [`GET /api/v1/events`](/api-reference/list-events) for 30 days, whether or not an endpoint subscribed to it. sajn records each occurrence once: if the same thing is reported again with identical data, such as a party opening a document a second time before anything changed, sajn neither records nor delivers it again.

## Choose events

Most integrations need only a few events:

| To | Subscribe to |
| - | - |
| Store the signed PDF | `document.completed` |
| Mirror document status in a CRM | `document.sent`, `document.completed`, `document.rejected`, `document.expired`, `document.withdrawn` |
| Track each party's progress | `document.party.opened`, `document.party.signed`, `document.party.rejected` |
| Catch invitations that didn't arrive | `document.party.delivery_failed` |
| Chase documents before they expire | `document.expiring_soon` |
| Follow internal approvals | The `approval_request.*` events |
| Act on a submitted form | `form.submitted` |
| Warn before work stops on a quota | `usage.limit_reached` |
| Feed a SIEM | The `security.*` events |

`document.completed` means that the sealed PDF is ready: sajn fires it after it has sealed the signed document. `document.fully_signed` fires earlier, when every party has signed but before the seal, so don't download the signed file on it.

## Document events

These events fire when a document changes state. `data.object` is the document, in the shape that [`GET /api/v1/documents/{id}`](/api-reference/get-a-document-by-id) returns. For the extra fields, see [Document events](/webhooks/payloads#document-events).

| Event | Fires when |
| - | - |
| [`document.created`](/api-reference/webhook-events/documentcreated) | A document is created, including as a duplicate of another document or from an attachment emailed to the workspace inbox. `data.source` says which. |
| [`document.sent`](/api-reference/webhook-events/documentsent) | The document is sent to its parties. Sending it again after a withdrawal fires the event again. |
| [`document.fully_signed`](/api-reference/webhook-events/documentfully_signed) | Every party has signed. sajn hasn't sealed the PDF yet. |
| [`document.completed`](/api-reference/webhook-events/documentcompleted) | sajn has sealed the signed PDF, and the document is complete. |
| [`document.rejected`](/api-reference/webhook-events/documentrejected) | A party rejects the document, which ends signing for every party. `document.party.rejected` reports the same rejection with the party. |
| [`document.expired`](/api-reference/webhook-events/documentexpired) | A pending document passes its expiration date before every party has signed. |
| [`document.expiring_soon`](/api-reference/webhook-events/documentexpiring_soon) | A pending document expires in about a day, and at least one party hasn't signed. |
| [`document.expiration_extended`](/api-reference/webhook-events/documentexpiration_extended) | A pending or expired document gets a new expiration date. An expired document returns to `PENDING`. `data.previousAttributes.expiresAt` holds the earlier date. |
| [`document.withdrawn`](/api-reference/webhook-events/documentwithdrawn) | The sender withdraws a sent document. The document returns to `DRAFT`. |
| [`document.updated`](/api-reference/webhook-events/documentupdated) | The content of a sent document is updated in place, before anyone has signed. |
| [`document.deleted`](/api-reference/webhook-events/documentdeleted) | The document moves to the trash, by a member or by the workspace's retention policy. |
| [`document.restored`](/api-reference/webhook-events/documentrestored) | The document is restored from the trash. |
| [`document.archived`](/api-reference/webhook-events/documentarchived) | The document is archived. |
| [`document.unarchived`](/api-reference/webhook-events/documentunarchived) | The document is taken out of the archive. |
| [`document.comment.created`](/api-reference/webhook-events/documentcommentcreated) | A workspace member or a party comments on the document, in a new thread or as a reply. `data.object` is the comment, and `data.thread` is its thread. |

## Party events

These events fire when something happens to one party on a document. `data.object` is the document, and `data.party` is the party that the event is about, as [`GET /api/v1/documents/{id}/parties`](/api-reference/list-all-parties-for-a-document) lists it. For the extra fields, see [Party events](/webhooks/payloads#party-events).

| Event | Fires when |
| - | - |
| [`document.party.sent`](/api-reference/webhook-events/documentpartysent) | sajn sends the party their invitation by email or SMS. |
| [`document.party.delivery_failed`](/api-reference/webhook-events/documentpartydelivery_failed) | The party's invitation email bounces or their SMS fails. After a bounce, sajn also stops the party's scheduled reminders. |
| [`document.party.opened`](/api-reference/webhook-events/documentpartyopened) | The party opens the document from the signing link. It can fire again on a later visit. |
| [`document.party.read`](/api-reference/webhook-events/documentpartyread) | The party has read the whole document in the signing view. It fires once per party. |
| [`document.party.verified`](/api-reference/webhook-events/documentpartyverified) | The party passes the verification that protects the document, such as an SMS code, a PIN, or an eID. `data.purpose` is `ACCESS` or `SIGN`. |
| [`document.party.auth_failed`](/api-reference/webhook-events/documentpartyauth_failed) | The party fails a verification step, such as a wrong SMS code or PIN, or a failed eID authentication. |
| [`document.party.signed`](/api-reference/webhook-events/documentpartysigned) | The party signs. |
| [`document.party.rejected`](/api-reference/webhook-events/documentpartyrejected) | The party rejects the document. |
| [`document.party.delegated`](/api-reference/webhook-events/documentpartydelegated) | The party delegates signing to someone else. `data.delegation` describes the delegate. |
| [`document.party.updated`](/api-reference/webhook-events/documentpartyupdated) | Someone corrects the name, email address, or phone number of a party who hasn't signed a sent document. `data.previousAttributes` holds the old values. |
| [`document.party.added`](/api-reference/webhook-events/documentpartyadded) | A party is added to a document that's already sent. |
| [`document.party.removed`](/api-reference/webhook-events/documentpartyremoved) | A party is removed from a document that's already sent. `data.party` is the party as it was, and `data.object.parties` no longer lists it. |
| [`document.party.reminded`](/api-reference/webhook-events/documentpartyreminded) | The party gets a reminder to sign. `data.trigger` is `AUTOMATIC` for a scheduled reminder, or `MANUAL` for one that someone sent. |

## Approval request events

These events follow a document's [internal approval](/api-reference/request-approval-of-a-document). `data.object` is the approval request, as [`GET /api/v1/approval-requests/{id}`](/api-reference/get-an-approval-request) returns it.

| Event | Fires when |
| - | - |
| [`approval_request.created`](/api-reference/webhook-events/approval_requestcreated) | A document is submitted for approval, from the dashboard or the API. A rejected request that's submitted again fires it again, with the same `id`. |
| [`approval_request.approved`](/api-reference/webhook-events/approval_requestapproved) | The last required approver approves. If `autoSend` is `true`, sajn then sends the document, which fires `document.sent`. |
| [`approval_request.rejected`](/api-reference/webhook-events/approval_requestrejected) | An approver rejects the request. The document returns to `DRAFT`. |
| [`approval_request.cancelled`](/api-reference/webhook-events/approval_requestcancelled) | The requester cancels a pending request. sajn deletes the request, and the document returns to `DRAFT`. |

## Identity check events

These events fire as an [identity check](/concepts/sajn-id) moves through its steps. `data.object` is the check, as [`GET /api/v1/identity-checks`](/api-reference/list-identity-checks) lists it. The data never contains the verified national identity number.

| Event | Fires when |
| - | - |
| [`identity_check.created`](/api-reference/webhook-events/identity_checkcreated) | An identity check is created. |
| [`identity_check.sent`](/api-reference/webhook-events/identity_checksent) | sajn sends the verification link by email or SMS, including when it's sent again. |
| [`identity_check.opened`](/api-reference/webhook-events/identity_checkopened) | The person opens the verification link. |
| [`identity_check.verified`](/api-reference/webhook-events/identity_checkverified) | The person completes the verification. |
| [`identity_check.failed`](/api-reference/webhook-events/identity_checkfailed) | The verification fails. `data.failureReason` says why. |
| [`identity_check.cancelled`](/api-reference/webhook-events/identity_checkcancelled) | The identity check is cancelled. |

## Contact and company events

These events fire when a contact or a company in the workspace changes. `data.object` is the contact, as [`GET /api/v1/contacts/{id}`](/api-reference/get-a-contact-by-id) returns it, or the company, as [`GET /api/v1/companies/{id}`](/api-reference/get-a-company-by-id) returns it.

| Event | Fires when |
| - | - |
| [`contact.created`](/api-reference/webhook-events/contactcreated) | A contact is created. |
| [`contact.updated`](/api-reference/webhook-events/contactupdated) | A contact's details change. |
| [`contact.deleted`](/api-reference/webhook-events/contactdeleted) | A contact is deleted. `data.object` is the contact as it was. |
| [`company.created`](/api-reference/webhook-events/companycreated) | A company is created, including when sajn creates one for a new contact's company name. |
| [`company.updated`](/api-reference/webhook-events/companyupdated) | A company's name, organization number, or country changes. |
| [`company.deleted`](/api-reference/webhook-events/companydeleted) | A company is deleted. |

## Template and form events

Template events fire when a template changes; forms don't fire them. `data.object` is the template, as [`GET /api/v1/templates/{id}`](/api-reference/get-a-template-by-id) returns it.

| Event | Fires when |
| - | - |
| [`template.created`](/api-reference/webhook-events/templatecreated) | A template is created, including as a duplicate of another template. |
| [`template.updated`](/api-reference/webhook-events/templateupdated) | A template changes. sajn sends at most one event per template per minute, and `data.previousAttributes` holds the earlier values of what changed. Treat it as a signal to read the template again, not as a complete change log. |
| [`template.deleted`](/api-reference/webhook-events/templatedeleted) | A template moves to the trash. |
| [`template.restored`](/api-reference/webhook-events/templaterestored) | A template is restored from the trash. |
| [`form.submitted`](/api-reference/webhook-events/formsubmitted) | A respondent submits a public form. It fires once per submission. `data.object` is the submission, as [`GET /api/v1/forms/{id}/submissions/{submissionId}`](/api-reference/get-a-form-submission) returns it. |

## Workspace and usage events

| Event | Fires when |
| - | - |
| [`workspace.created`](/api-reference/webhook-events/workspacecreated) | A workspace is created. The event belongs to the new workspace, so an endpoint in another workspace doesn't receive it. |
| [`member.invited`](/api-reference/webhook-events/memberinvited) | sajn sends someone an invitation to join the workspace. It fires once per invitation. `data.object` is the invitation, as [`GET /api/v1/member-invites`](/api-reference/list-pending-workspace-invitations) lists it. |
| [`member.invite_accepted`](/api-reference/webhook-events/memberinvite_accepted) | The invitee accepts the invitation. `member.added` fires too, with the new member. |
| [`member.added`](/api-reference/webhook-events/memberadded) | A user joins the workspace. `data.object` is the member, as [`GET /api/v1/members/{userId}`](/api-reference/get-a-workspace-member) returns it, and `data.via` says how they joined. |
| [`usage.limit_reached`](/api-reference/webhook-events/usagelimit_reached) | The organization reaches its monthly document quota or an eID signature quota. It fires at most once per quota and billing period. Signatures beyond the quota are billed from the balance; documents beyond it are refused until the period ends or the plan changes. |

## Security events

These events report security-relevant actions in a workspace, for a SIEM or an audit feed. `data.object` holds the details, and `actor` says whether a user, an API key, or an OAuth app acted. For the fields, see [Security events](/webhooks/payloads#security-events).

| Event | Fires when |
| - | - |
| [`security.document_downloaded`](/api-reference/webhook-events/securitydocument_downloaded) | Someone downloads a document's original file, signed file, or audit journal. |
| [`security.documents_exported`](/api-reference/webhook-events/securitydocuments_exported) | Someone exports documents in bulk, from a selection or a folder. |
| [`security.signature_identity_accessed`](/api-reference/webhook-events/securitysignature_identity_accessed) | Someone reads the signatures and identity data of a document. |
| [`security.member_removed`](/api-reference/webhook-events/securitymember_removed) | A member is removed from the workspace. |
| [`security.member_role_changed`](/api-reference/webhook-events/securitymember_role_changed) | A workspace member gets a different role. |
| [`security.role_updated`](/api-reference/webhook-events/securityrole_updated) | A workspace role's definition is saved, through the dashboard or the API. |
| [`security.workspace_retention_updated`](/api-reference/webhook-events/securityworkspace_retention_updated) | The workspace's retention periods change. |

Organization-level actions, such as sign-ins, two-factor changes, and API key changes, have no security event, because webhooks belong to a workspace.

## sajn Login events

[`login.completed`](/api-reference/webhook-events/logincompleted) and [`login.failed`](/api-reference/webhook-events/loginfailed) report the outcome of a [sajn Login](/login/overview) authentication. They use the same delivery, signing, and retries as every other event. For when they fire and their data, see [Login webhooks](/login/webhooks).

## Test event

[`webhook.test`](/api-reference/webhook-events/webhooktest) is sent only when you call [`POST /api/v1/webhooks/{id}/test`](/api-reference/send-a-test-event-to-a-webhook), and only to that webhook. You can't subscribe to it, and `GET /api/v1/events` doesn't list it. `data.object` is the webhook's `id` and `url`. For how to use it, see [Test webhooks locally](/webhooks/testing).

## Events in API version 2026-09

An endpoint on `2026-09` receives the same events under their uppercase names, such as `DOCUMENT_PARTY_SIGNED`. A few differ: `document.fully_signed` is `DOCUMENT_SIGNED`, an inbox upload also fires `DOCUMENT_ARCHIVE_UPLOADED`, reminders are `DOCUMENT_REMINDER_AUTOMATIC` and `DOCUMENT_REMINDER_MANUAL`, identity check events are `ID_*` with `ID_CANCELED`, and security events are `SECURITY_*`. For the full mapping, see [Upgrading to 2026-10](/upgrading/2026-10).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.