2026-10
No sunset date.Documents and parties
- Removes the deprecated signer aliases. On
POST /api/v1/documents, sendpartiesinstead ofsigners. OnPOST /api/v1/documents/:id/reminders, sendpartyIdsinstead ofsignerIds. TheACCEPTORrole is rejected; sendSIGNERinstead. Responses fromPOST /api/v1/documentsandGET /api/v1/documents/:id, and document webhook payloads, no longer includesigners; readpartiesinstead. The/api/v1/documents/:id/signersendpoints are removed; use the/api/v1/documents/:id/partiesendpoints instead. - Returns the full document from
POST /api/v1/documents, in the same shape asGET /api/v1/documents/:id. Read the document ID fromidinstead ofdocumentId, and each party ID fromparties[].idinstead ofparties[].signerId.GET /api/v1/documents/:idleaves outfieldsunless you passexpand=fields. TheexternalIdfilter onGET /api/v1/documentsmatches the whole value, case-sensitively; for a partial match, usequery.GET /api/v1/documents/:id/downloadis removed; useGET /api/v1/documents/:id/files/:type.POST /api/v1/documents/:id/parties/:partyId/remindis removed; usePOST /api/v1/documents/:id/reminderswithpartyIds, which reports each party’s outcome inresultsinstead of failing the request. GET /api/v1/documents/:id/parties/:partyIdno longer returns the party’stoken;signingUrlalready carries it. An uploaded attachment in a FORM subfield’sfieldMeta.valueis{ filename, mimeType, size }, without the storage key and checksum.POST /api/v1/filesreturns the file object, the same asGET /api/v1/files/:id, withuploadUrlandkey; useidinstead offileId.- Uses ISO 3166-1 alpha-2 country codes everywhere, as organizations and companies already did. A party’s
country, on documents, templates, and forms, is alpha-2 (SEinstead ofSWE) in requests and responses, andGET /api/v1/helpers/countriesreturns alpha-2 codes. - Returns the same template everywhere, in the shape of
GET /api/v1/templates/:id: the list, create, update, duplicate, delete, and tag endpoints returntemplateMeta,parties,tags, anddeletedAt.GET /api/v1/templates/:idleaves out the content blocks, withfields: null, unless you passexpand=fields.DELETE /api/v1/templates/:idmoves the template to the trash and returns it withdeletedAtset, andPOST /api/v1/templates/:id/tagsandDELETE /api/v1/templates/:id/tags/:tagIdreturn the template, instead of{ success }.DELETE /api/v1/templates/:id/parties/:partyIdreturns{ id, deleted: true }. InPATCH /api/v1/templates/:id/parties/:partyId,nullclears a property. Updating or deleting a locked template, or changing its parties, fails with409 INVALID_STATEinstead of403 PERMISSION_DENIED. - Makes internal approval its own resource. To request approval of a draft, call
POST /api/v1/approval-requestswithdocumentIdandapproverIds, or withoutapproverIdsto submit the approvers already on the document, instead ofPOST /api/v1/documents/:id/sendwithapproverId.GET /api/v1/approval-requestslists requests, filtered bydocumentId,approverId, andstatus, andGET /api/v1/approval-requests/:idreturns one. To act on a request, callPOST /api/v1/approval-requests/:id/approve,/reject, or/cancel; each returns the request. A request lists each approver as{ user, stage, orGroup, status, comment, resolvedAt }, whereuseris{ id, email, name }. RemovesGET /api/v1/documents/:id/approval,DELETE /api/v1/documents/:id/approval,POST /api/v1/documents/:id/approval/approve, andPOST /api/v1/documents/:id/approval/reject. RemovesGET /api/v1/approvers; callGET /api/v1/members?permission=APPROVE_DOCUMENT, which also lists you. - Returns the full document, in the shape of
GET /api/v1/documents/:idwithoutfields, fromPATCH /api/v1/documents/:id,POST /api/v1/documents/:id/send,POST /api/v1/documents/:id/withdraw,POST /api/v1/documents/:id/extend-expiration, andDELETE /api/v1/documents/:id. A document hasdeletedAt,templateId,folderId, andresponsibleUserId, and a full document also hasapprovalRequestId. A deleted document is returned withdeletedAtset.POST /api/v1/documents/:id/sendno longer submits the document for approval: when the document needs one, it returns409 APPROVAL_REQUIREDinstead of403, never202, and a request withapproverIdis rejected; request the approval withPOST /api/v1/approval-requestsinstead.DELETE /api/v1/documents/:id/parties/:partyId,DELETE /api/v1/files/:id, andDELETE /api/v1/documents/:id/links/:linkIdreturn{ id, deleted: true }.GET /api/v1/templates/:id/documentsis removed; useGET /api/v1/documents?templateId=.GET /api/v1/documents/:id/download/:fileTypeis removed; useGET /api/v1/documents/:id/files/:type, orGET /api/v1/documents/:id/filesfor every file that is ready. - Nests a party’s company in
company, withid,name,orgNumber, androle, in place ofcompanyId,companyName,companyOrgNumber, andcompanyRole, on document parties and template parties alike.companyis null for a private individual. Requests toPOST /api/v1/documents,PATCH /api/v1/documents/:id/parties/:partyId,POST /api/v1/templates/:id/parties,PATCH /api/v1/templates/:id/parties/:partyId, andPUT /api/v1/forms/:id/template/partiestakecompanytoo, and a request that still sends one of the flat keys fails with400 VALIDATION_FAILED. In aPATCHrequest,nullclearsphone,externalId,nationalId, or a key ofcompany, andcompany: nullclears the whole company. A document party gainscreatedAt, when it was added to the document; a template party keepscreatedAtandupdatedAt. POST /api/v1/documents/:id/linksreturns the link in the shape of an item fromGET /api/v1/documents/:id/links, and every link hasfromDocumentIdandtoDocumentId.POST /api/v1/files/:id/confirmreturns the file, in the shape ofGET /api/v1/files/:id, instead of{ id, status, size, checksumVerified }.GET /api/v1/folders/:id,POST /api/v1/folders, andPATCH /api/v1/folders/:idreturnchildFolderCountanditemCount.PATCH /api/v1/documents/:id/parties/:partyIdon a sent document changes thename,email, andphoneof a party who hasn’t signed, instead of failing; any other property fails with409 INVALID_STATE.POST /api/v1/documents/:id/partiesandPATCH /api/v1/documents/:id/parties/:partyIdreturn the party in the shape ofGET /api/v1/documents/:id/parties/:partyId, with itssigningUrl, and log that you read the signing URL, as theGETrequest does.- Each document in
GET /api/v1/documentshasparties, with every party’sid,name,email,role,signingStatus, andsignedAt, andtags, so you can tell who has signed without reading each document.
Fields
- Returns the field itself from the field endpoints.
POST /api/v1/documents/:id/fieldsandPOST /api/v1/templates/:id/fieldsreturn the created fields indata, each in the shape ofGET /api/v1/documents/:id/fields/:fieldId; read the document or template ID from each field instead of the top-leveldocumentIdortemplateId. APATCHrequest to a field returns the updated field in that shape. ADELETErequest to a field returns{ id, deleted: true }; to keep the deleted content, read the field before you delete it. - Gives fields one write path.
PATCH /api/v1/documents/:id/fields/:fieldIdandPATCH /api/v1/templates/:id/fields/:fieldIdtake a field ID only; thekey:path prefix is removed. To fill in a FORM subfield or another value, usePATCH /api/v1/documents/:id/field-values. To find the field that holds a key, passkeytoGET /api/v1/documents/:id/fieldsorGET /api/v1/templates/:id/fields.PATCH /api/v1/documents/:id/fields, which updated FORM subfields by key, is removed for the same reason. Thekeyproperty of a field in the create and update requests, which sajn ignored, is removed. - Uses
partyIdandcustomFieldIdinsidefieldMeta, like everywhere else. A box inplacedFieldsand thefieldMetaof a FORM subfield takepartyIdinstead ofsignerId, a PRODUCT_TABLE takesselectionPartyIdinstead ofselectionSignerId, andvisibilityRuletakescustomFieldIdinstead ofcustomInputId. This applies to every request and response that carriesfieldMeta, includingupserton the placed-fields endpoints,initialFieldsonPOST /api/v1/templates, and blocks.GET /api/v1/documents/:id/field-valuesreturnspartyIdinstead ofsignerId. A request that still sends an old name insidefieldMetaorupsertfails with400 VALIDATION_FAILED. - Spells every enum inside
fieldMetain uppercase, like the rest of the API. A placed box haskindINPUTorSTATIC, and itsinputType(such asSIGNATURE),fillSource(such asSIGNER), andstyle.alignare uppercase. So are thetypeof a FORM subfield and of itsfieldMeta(such asDATEPICKER), an attachment’sallowedTypes, thetypeof an AcroForm field informFieldsand of a TABLE column, a DURATION field’sdurationTypeand periodunit, andsectionStyle.backgroundandsectionStyle.padding. OnGETandPATCH /api/v1/documents/:id/field-values,kindisFORM,PDF_ACROFORM, orPDF_PLACED,filledByisSENDERorSIGNER, andtypeis uppercase. A request that sends a lowercase value insidefieldMetafails with400 VALIDATION_FAILED. - Names VAT
vatinstead of the Swedishmomsin product tables. In a PRODUCT_TABLE field’sfieldMeta, a product’smomsisvat,pricing.pricesIncludeMoms,defaultMomsRate, andshowMomsBreakdownarepricesIncludeVat,defaultVatRate, andshowVatBreakdown, the same settings on a column are renamed the same way, the VAT column is keyedvat, andsummaryLabels.momsissummaryLabels.vat. InproductTablesonGET /api/v1/documents/:idand on webhooks, a row’smomsandlineMomsarevatandlineVat, andmomsAmountin the totals isvatAmount. Prices and amounts are decimal amounts in the table’s currency, as before. A request that still sends amomsname fails with400 VALIDATION_FAILED. POST /api/v1/documents/:id/fieldsandPOST /api/v1/templates/:id/fieldstake{ fields: [...] }, also for one field, instead of a field or an array of fields, and an issue path starts withfields.. The placed-fields endpoints return the whole field, in the shape ofGET /api/v1/documents/:id/fields/:fieldId.GET /api/v1/documents/:id/field-valuesandPATCH /api/v1/documents/:id/field-valuesreturn the values indatainstead ofvalues. OnPATCH /api/v1/documents/:id/field-values, a result’serroris{ code, message, userMessage }instead of a Swedish string, withcodeNOT_FOUND,INVALID_STATE, orVALIDATION_FAILED, and the top-levelsuccessis removed; check each result’ssuccess.
Naming
- Renames the Swedish BankID codes to their eID scheme names, like every other scheme:
SE_BANKIDreplacesBANKIDinrequiredSignature, andSE_BANKID_BEFORE_SIGNINGreplacesBANKID_BEFORE_SIGNINGintwoStepVerificationandaccessVerification. Requests that send the old codes are rejected, andGET /api/v1/helpers/signature-methodsandGET /api/v1/helpers/two-step-verificationsreturn the new ones. - Renames the remaining signer fields to party fields.
GET /api/v1/documents/:id/signaturesreturnspartyIdandpartyNameinstead ofsignerIdandsignerName. The reminder endpoints returnpartyId,partyEmail, andpartyNameinstead ofsignerId,signerEmail, andsignerName.GET /api/v1/documents/:id/delegationsreturnsoriginalPartyId,delegatePartyId,originalParty, anddelegatePartyinstead oforiginalSignerId,delegateSignerId,originalSigner, anddelegateSigner. The form endpoints returnrespondentPartyIdinstead ofrespondentSignerId, andPUT /api/v1/forms/:id/respondenttakespartyIdinstead ofsignerId. - Renames the national identity number from
ssntonationalIdon parties, template parties, and contacts, and in thePOST /api/v1/sajn-idrequest.documentMeta.ssnDisplayModeandtemplateMeta.ssnDisplayModebecomenationalIdDisplayMode. InGET /api/v1/documents/:id/signatures,identity.match.methodreturnsNATIONAL_IDinstead ofSSN. TheSECURITY_SIGNATURE_IDENTITY_ACCESSEDwebhook payload sendsnationalIdDisplayModeinstead ofssnDisplayMode. Requests that still sendssnorssnDisplayModeare rejected. - Renames custom field IDs to
customFieldId. OnPOST /api/v1/documentsandPATCH /api/v1/documents/:id, sendcustomFields[].customFieldIdinstead ofcustomFields[].customInputId.GET /api/v1/document-categoriesreturnscustomFieldIdsinstead ofcustomInputIds. - Uses uppercase enum values everywhere. Workspace members have
statusACTIVEorINACTIVE, and thestatusfilter onGET /api/v1/memberstakesACTIVEorINACTIVE; leave it out for every member. Login sessions onGET /api/v1/login/sessions/:idhavestatusPENDING,COMPLETED,FAILED, orEXPIRED. Removes the event typesDOCUMENT_OPENED,DOCUMENT_RECREATED,WORKFLOW_STARTED,WORKFLOW_COMPLETED, andWORKFLOW_FAILED, which sajn never emits, from the events and webhook deliveries endpoints. To track a party opening a document, usedocument.party.opened; to track changes to a sent document, usedocument.updated. - Spells the remaining closed enums in uppercase. Form
questionshavekindNAME,EMAIL,PHONE,FIELD,TEXT,HEADING, orPARAGRAPHandwidthFULLorHALF; formslotshave an uppercasetype, andpublishIssueshaveseverityBLOCKERorWARNING. A document link’soriginisMANUAL,DUPLICATE, orRENEWAL. IndocumentStyle.theme,bodyFontandheadingFont(such asOPEN_SANS),density, andtextSizeare uppercase. A sajn ID verification that was cancelled hasstatusCANCELLED, the spelling documents use, in responses and in thestatusfilter. InPOST /api/v1/documents,integrationLink.integrationisHUBSPOTandintegrationLink.typeisDEAL. - Renames a form’s
titletoname, in responses and inPATCH /api/v1/forms/:id.POST /api/v1/formsreturns200instead of201.POST /api/v1/forms/:id/unpublishandPOST /api/v1/forms/:id/rotate-tokenreturn the form instead of{ success }and{ url }, andDELETE /api/v1/forms/:idreturns{ id, deleted: true }. The form’s template moves from/api/v1/forms/:id/documentto/api/v1/forms/:id/template, with/template/fieldsand/template/parties, andPATCH /api/v1/forms/:id/templatereturns the template instead of{ success }. ItstemplateMeta.signingOrderissigningMode, as on templates. - Moves sajn ID verifications from
/api/v1/sajn-idto/api/v1/identity-checks, the name theidentity_check.*webhook events and theidentityChecksquota inGET /api/v1/limitsuse. An identity check haslanguage, an ISO 639-1 code such assv, instead of the free-formlocale; sendlanguageinstead oflocalewhen you create one.createdByis{ id, email, name }. A check in a list has the same fields as one you get by ID, withaudits,data, andverificationUrlset tonull. The response to the create request no longer returnstoken, whichverificationUrlalready carries. Requests that setemailorphoneto an empty string fail with400 VALIDATION_FAILED; leave the field out instead. - Moves a document’s chat from
/api/v1/documents/:id/chatto/api/v1/documents/:id/messages. The list returns its messages indata, like every other list. A message and a comment have one shape: the text isbody, in responses and inPOST /api/v1/documents/:id/messages, instead of a message’scontent, and the author isauthor: { type, id, name, email }, instead of a comment’s separateauthorType. A comment’sauthoris always present:id,name, andemailare null for the AI assistant or an author who no longer exists. - Renames the PARALLEL or SEQUENTIAL setting in
templateMetafromsigningOrdertosigningMode, in responses and inPATCH /api/v1/templates/:id, so thatsigningOrdernames only a party’s position. A request that still sendstemplateMeta.signingOrderfails with400 VALIDATION_FAILED. - Folds the contact and company searches into the lists.
GET /api/v1/contacts/searchis removed: passemail,phone, orexternalIdtoGET /api/v1/contacts, where every filter you pass must match, instead of any one.GET /api/v1/companies/searchis removed: passorgNumberornametoGET /api/v1/companies, again matching every filter.GET /api/v1/companies/lookup?orgNr=moves toGET /api/v1/company-registry/:orgNumber, which returnsbasic.orgNumberinstead ofbasic.orgNr. A contact returns its address (addressLine1,addressLine2,postalCode,city,state, andcountry), which you can also set when you create or update one, and itscompanyis the full company. A company returnscreatedAtandupdatedAt.GET /api/v1/companies/:idno longer returnscontacts; list them withGET /api/v1/contacts?companyId=. - Gives a member one shape everywhere:
POST /api/v1/members,GET /api/v1/members,GET /api/v1/members/:userId, andPATCH /api/v1/members/:userIdreturn{ id, email, name, role, status, lastActiveAt, joinedAt }, whereidis the user ID that wasuserId.POST /api/v1/membersonly adds a member of the organization to the workspace and returns404for any other email address; it no longer takessendInviteor returnsinvited,roleId,roleName,workspaceId,organizationId, oraddedAt. To invite someone new, callPOST /api/v1/member-inviteswithemailandroleId, which returns the invitation.DELETE /api/v1/members/:userIdandDELETE /api/v1/member-invites/:idreturn{ id, deleted: true }, andPOST /api/v1/member-invites/:id/resendreturns the invitation, instead of{ success: true }. An invitation’sinvitedByis{ id, email, name }, and so is every other user reference.GET /api/v1/mereturns the user ID asidinstead ofuserId./api/v1/workspace-rolesis renamed/api/v1/roles, and/api/v1/workspace-permissionsis renamed/api/v1/permissions;DELETE /api/v1/roles/:idreturns{ id, deleted: true }. To list the members who can approve documents, callGET /api/v1/members?permission=APPROVE_DOCUMENTinstead ofGET /api/v1/approvers. - Renames the PARALLEL or SEQUENTIAL setting in
documentMetafromsigningOrdertosigningMode, in responses and inPOST /api/v1/documentsandPATCH /api/v1/documents/:id, so thatsigningOrdernames only a party’s position. A request that still sendsdocumentMeta.signingOrderfails with400 VALIDATION_FAILED. - Gives every user reference one shape,
{ id, email, name }. Templates, folders, and blocks returncreatedByinstead ofcreatedById, and a form returnssenderinstead ofsenderUserId. A file’suploadedByhasnameinstead offirstNameandlastName. InGET /api/v1/documents/:id/reminders,triggeredByadds the user’sid, and it’snullfor a reminder sajn sent automatically, instead of an object with a nullnameandemail. - Renames
preferredLanguageindocumentMetaandtemplateMetatolanguage, and a block’slocaletolanguage, in responses and requests.reminderIntervalDaysindocumentMetaandtemplateMetais an integer instead of a string:0turns reminders off, andnulluses the default of 3 days. A request that still sendspreferredLanguagefails with400 VALIDATION_FAILED.
Query strings and pagination
- Reads query parameters as plain strings: send
externalId=12345orarchived=falseas is, not JSON-encoded. Booleans taketrueorfalse, dates take an ISO 8601 date or date-time (UTC without an offset), and multi-value filters such asstatus,tagId, andtypetake a comma-separated list or a repeated parameter. An unknown query parameter returns400instead of being ignored. RenamessearchtoqueryonGET /api/v1/templates,sinceanduntiltocreatedAfterandcreatedBeforeonGET /api/v1/events, anddateFromanddateTotocreatedAfterandcreatedBeforeonGET /api/v1/identity-checks, which replacesGET /api/v1/sajn-id, andlocaletolanguageonGET /api/v1/blocks.createdBeforeincludes its boundary, whereasuntilexcluded it, and the identity checks list no longer defaults to the last seven days.GET /api/v1/companies/:idreturns the company without thecompanywrapper. - Gives every list one contract. Page with
limit, from 1 to 100 with a default of 25, andcursor, thenextCursorof the previous response;pageandperPageare removed, and sending them returns400. A list returns{ data, hasMore, nextCursor }, andtotalonly when you passinclude=total;totalPagesis removed. Lists that returned everything in one response are paginated too:GET /api/v1/folders,/document-categories,/workspaces,/companies,/documents/:id/activity, and/documents/:id/comments. Lists bounded by their parent, such as a document’s parties, fields, and signatures, and the/helperslists return every item in one response, as{ data, hasMore: false, nextCursor: null }. Lists sort newest first by default, includingGET /api/v1/documents, which sorted byupdatedAt, andGET /api/v1/formsand/forms/:id/submissions, which sorted byupdatedAtascending; passorderByandorderDirectionto change it. Documents page by keyset on everyorderBy, with emptycompletedAtandexpiresAtvalues last. Filters that reference another resource end inIdand take several values (createdByiscreatedByIdonGET /api/v1/templates, andtagId,companyId,roleId, and the delivery and submissionstatustake a list).ALLis no longer a filter value: leave the filter out instead. Blockscopevalues are uppercase.folderId=rootreplaces the emptyfolderIdfor top-level documents and templates. Mutable resources takecreatedAfter,createdBefore,updatedAfter, andupdatedBefore, all inclusive. - Renames the
scopefilter ofGET /api/v1/blockstovisibility, with the values a block’svisibilitytakes. A block sajn curates hasvisibility: SHAREDinstead ofWORKSPACE, sovisibility=WORKSPACEreturns exactly the blocks that listWORKSPACE.
Errors
- Gives every error response the same shape:
code,message,userMessage,requestId, and, where they apply,resource,issues,requiredScopes, andgrantedScopes.codeis always present and comes from a closed, documented list; branch on it, not on the status or the message.messageis always English text for developers, anduserMessage, always present, is the text that’s safe to show your users, usually Swedish.requestIdreplaceserrorIdand matches theSajn-Request-Idresponse header. Each validation issue gains acode, itsmessageis English, and aVALIDATION_FAILEDerror always lists at least one issue. ANOT_FOUNDerror names the missing resource’s type inresource, and a path that matches no endpoint returnsROUTE_NOT_FOUND. Codes are split or renamed:INVALID_REQUEST,INVALID_BODY, andVALIDATION_ERRORbecomeVALIDATION_FAILED;FORBIDDENbecomesPERMISSION_DENIED,INSUFFICIENT_SCOPE,PLAN_REQUIRED, orACCOUNT_INACTIVE;TOO_MANY_REQUESTSbecomesRATE_LIMITEDorDAILY_QUOTA_EXCEEDED; a reusedIdempotency-KeyreturnsIDEMPOTENCY_KEY_REUSEDorIDEMPOTENCY_KEY_IN_USE; and a failing external service or integration returnsUPSTREAM_UNAVAILABLE.401 UNAUTHORIZEDmeans only that the token is missing, invalid, expired, or revoked. A valid token that isn’t allowed to do something returns403 PERMISSION_DENIEDinstead of401. A state conflict returns409 INVALID_STATEinstead of400, including editing a document that isn’t a draft, editing the fields of a locked template (previously401), and downloading a file that isn’t produced yet (previously404). Other statuses change: sending a document past the monthly limit returns403 LIMIT_EXCEEDEDinstead of400, a deactivated user returns403 ACCOUNT_INACTIVEinstead of401, a duplicate unique value returns409 ALREADY_EXISTSand an invalid value caught deeper in the API returns400 VALIDATION_FAILEDinstead of500, and a failing external service returns a retryable503 UPSTREAM_UNAVAILABLEinstead of500. - A form’s
publishIssueshave an Englishmessage, and the Swedish text thatmessagehad is inuserMessage.
Webhooks
- Removes the
X-Sajn-Secretheader, which carried the endpoint secret in plain text, from webhook deliveries. Verify deliveries with the Standard Webhookswebhook-signatureheader instead. - Uses the REST API’s names in webhook payloads. On document events, the document has
nameinstead oftitle, andSECURITY_DOCUMENT_DOWNLOADEDandSECURITY_SIGNATURE_IDENTITY_ACCESSEDhavedocumentNameinstead ofdocumentTitle. A party without an email address hasemail: nullinstead of"". InproductTables, on webhooks and onGET /api/v1/documents/:id,selectionPartyIdreplacesselectionSignerId. Documents addexpiresAtandcompletedAt, and parties addroleandsignedAt.DOCUMENT_ARCHIVE_UPLOADEDno longer includess3Key, an internal storage key. - Gives
DOCUMENT_PARTY_AUTH_FAILEDandDOCUMENT_PARTY_DELEGATEDthe{ document, party }payload of every other party event, in place of the flatdocumentId,documentName, andsignerId.DOCUMENT_PARTY_AUTH_FAILEDkeepsmethod,hintCode, andfailedAtnext to them, andmethoduses the eID scheme name, such asSE_BANKIDinstead ofBANKID.DOCUMENT_PARTY_DELEGATEDmoves the delegation intodelegation, withid,delegate,reason, anddelegatedAt; read the delegating party frompartyinstead oforiginalSigner. - Changes the webhook delivery body to the event itself,
{ id, type, createdAt, apiVersion, workspaceId, environment, actor, data }, whichGET /api/v1/eventsandGET /api/v1/events/:idalso return.typeis a dotted lowercase event name such asdocument.party.signedinstead ofDOCUMENT_PARTY_SIGNED, and theeventfilter ofGET /api/v1/eventsbecomestype.data.objectis the resource the event is about; a party event addsdata.party, and the document, previously inpayload.document, moves todata.object.environmentisPRODUCTIONorSANDBOX, andactoris the user, API key or system behind the event, or null.idis the event ID andcreatedAtthe time of the event, so both stay the same across retries and replays;webhookEndpointis removed. Some events are renamed or merged:DOCUMENT_SIGNEDisdocument.fully_signed;DOCUMENT_ARCHIVE_UPLOADEDis no longer sent, becausedocument.createdreports the same document withdata.source; the two reminder events becomedocument.party.remindedwithdata.triggerset toAUTOMATICorMANUAL;ID_*events areidentity_check.*, withID_CANCELEDasidentity_check.cancelled; andSECURITY_*events aresecurity.*, with the actor inactorand withoutoccurredAt.DOCUMENT_MODIFIEDisdocument.updated, and the workspace membership events drop theworkspace_prefix:SECURITY_WORKSPACE_MEMBER_REMOVED,SECURITY_WORKSPACE_MEMBER_ROLE_CHANGED, andSECURITY_WORKSPACE_ROLE_UPDATEDaresecurity.member_removed,security.member_role_changed, andsecurity.role_updated.previousAttributesreplaceschangedFieldsontemplate.updatedandpreviousExpiresAtondocument.expiration_extended. Enum values indataare uppercase:viaonmember.addedandscopeonsecurity.documents_exported. Deliveries are signed according to Standard Webhooks, with thewebhook-id,webhook-timestampandwebhook-signatureheaders in place ofX-Sajn-Signature,X-Sajn-DeliveryandX-Sajn-Environment, and a new 2026-10 webhook gets awhsec_secret. - Renames a webhook’s
webhookUrltourlandeventTriggerstoevents, which takes the dotted event types such asdocument.completed. A webhook addsstatus(ENABLED,DISABLEDorPAUSED),pausedAtandpauseReason, and a paused webhook resumes withPOST /api/v1/webhooks/:id/reactivate.PATCH /api/v1/webhooks/:idno longer takessecret: rotate the secret withPOST /api/v1/webhooks/:id/rotate-secret, which signs deliveries with both secrets for 24 hours. Asecretyou pass on create must be a Standard Webhooks secret,whsec_followed by base64.DELETE /api/v1/webhooks/:idreturns{ id, deleted: true }instead of{ success: true }. - Lists a webhook’s deliveries instead of its attempts in
GET /api/v1/webhooks/:id/deliveries. A delivery is one event sent to one endpoint, so itsidis the delivery and every attempt to send it is inattempts, withdurationMsand the request and response headers. A delivery addseventIdandtype, and itsstatusisSUCCESS,FAILEDorPENDING. Theeventfilter becomestype,eventIdfilters on one event, andstatusfilters on the delivery’s status instead of an attempt’s.GET /api/v1/webhooks/:id/deliveries/:deliveryIdandPOST /api/v1/webhooks/:id/deliveries/:deliveryId/retrytake the delivery ID, and the retry returns the new delivery instead of{ ok, queuedReplayOf }.POST /api/v1/events/:id/replayis removed: to send an event again, retry its delivery to that endpoint. A retry, in every API version, sends the delivery under a new delivery ID. - Returns a webhook’s
secretonly fromPOST /api/v1/webhooksandPOST /api/v1/webhooks/:id/rotate-secret. No other webhook response returns it. Store the secret when you create the webhook; to replace a lost one, rotate it. - Makes
data.objecton webhook events the object the REST API returns for the resource, withoutexpand, so a field added to the REST object also appears in the event. A document event carries the document asGET /api/v1/documents/:idreturns it, withdocumentMeta,tags,customFields,templateId,folderId,responsibleUserIdandapprovalRequestId, and withoutorganizationId;data.partyis the party asGET /api/v1/documents/:id/partieslists it, with alpha-2countryand a nestedcompany. A contact event carries the contact asGET /api/v1/contacts/:idreturns it, withpostalCodeinstead ofzipCode, and withoutcompanyNameandworkspaceId. A template event carries the template asGET /api/v1/templates/:idreturns it.member.addedcarries the member asGET /api/v1/members/:userIdreturns it, with the user ID inid, andviamoves todata.via. An identity check event carries the check asGET /api/v1/identity-checkslists it, withstatusCANCELLEDinstead ofCANCELED, andidentity_check.failedaddsdata.failureReason. Payloads leave out national identity numbers.template.updatedsetspreviousAttributesto the earlier values of the fields that changed, anddocument.createdsetsdata.sourcefor a document created from the email inbox. Security events name users as{ id, email, name }: the user who acted isuser, and the member a membership event is about ismember, instead ofworkspaceMemberIdandemail. A call by an OAuth application has the actor{ type: "OAUTH_APP", id }, with the application’s ID.
Limits
- Removes the deprecated
bankIdSignaturesandaiTokensaliases fromGET /api/v1/limits. Readsignatures.SE_BANKIDinstead ofbankIdSignatures, andaiBudgetOre,aiSpentOre, andaiSpentOreSignerinstead ofaiTokensandaiTokensSigner. - Removes the cost fields from
GET /api/v1/limits:quota.additionalBankidCost,quota.smsCost, andadditionalCosts. They always returned0. To track use beyond the plan, compareusagewithquota; the prepaid credit that pays for it is inbalance. - Gives the amounts of money in
GET /api/v1/limitsas{ amount, currency }, withamountin the currency’s minor unit, such as öre forSEK. Product table prices and totals stay decimal amounts in the table’s currency, anddocumentMeta.valueandtemplateMeta.valuestay free text. InGET /api/v1/limits,balanceis in the organization’s currency, and the AI budget fields lose theirOresuffix:quota.aiBudget,remaining.aiBudget,usage.aiSpent, andusage.aiSpentSigner, always inSEK. An unlimited AI budget staysnull.GET /api/v1/organizationreturnspostalCodeinstead ofzipCode.
Other changes
- Returns every response property, with
nullwhen it has no value, instead of leaving it out. This applies to, among others,fieldsonGET /api/v1/documents/:idwithoutexpand=fields,optionson field values and form slots,erroron a successful field-value or batch result,verificationUrlandauditson identity checks, folder counts, and the template settings onGET /api/v1/forms/:id/template. - A custom field’s
optionsis an array of strings, such as["Small","Large"], instead of a JSON-encoded string, in requests and responses. POST /api/v1/login/sessionsreturns the session, with the same fields asGET /api/v1/login/sessions/:id, plusloginUrlandexpiresAt, which are null on every other read. Inclaims, a claim your client isn’t approved for isnullinstead of missing.methodnames the eID as the rest of the API does,SE_BANKIDinstead ofBANKID_SE.DELETE /api/v1/contacts/:idandDELETE /api/v1/custom-fields/:idreturn{ id, deleted: true }instead of the deleted object; to keep its content, read it before you delete it.POST /api/v1/documents/:id/tagsandDELETE /api/v1/documents/:id/tags/:tagIdreturn the document, in the shape ofGET /api/v1/documents/:id, instead of{ success: true }. InPATCH /api/v1/contacts/:id,nullclearsemail,phone,nationalId,externalId, andcompanyRole.
2026-09
Deprecated: from 2027-10-01, requests on this version return400 API_VERSION_SUNSET.
The first dated version: the v1 API as it was on its release date.
