Dazr Sign API: documentatie voor ontwikkelaars

Snel aan de slag

  1. Schakel de Dazr Sign API in. Open in het Sign-portaal Ontwikkelaars en kies Dazr Sign API inschakelen voor je app. Elke app van je organisatie staat daar en in de console van Dazr Identity, met dezelfde client-ID en hetzelfde secret; elke API schakel je apart in. Je kunt daar ook een nieuwe app registreren.
  2. Vraag de scope sign aan. Stuur mensen door de gebruikelijke flow van Inloggen met Dazr Identity met scope=openid sign (voeg offline_access toe voor een refresh token). Het toestemmingsscherm vermeldt dat je app namens hen documenten mag voorbereiden en ter ondertekening versturen, en de status ervan mag zien. Dit werkt met alleen de Dazr Sign API; wie ook gegevens van mensen vraagt (profile, email en de andere), heeft ook de Dazr Identity API nodig.
  3. Roep de API aan met het toegangstoken. Het basisadres is https://sign.dazr.eu/api/sign/v1. Stuur Authorization: Bearer <access token> en JSON.
  4. Maak een document en verstuur het. Upload een pdf met teksttags en een lijst ontvangers en verstuur het, of open de voorbereidingspop-up zodat de persoon zelf de velden plaatst.
// Node 18+: create a document from a PDF with text tags, then send it
import fs from 'node:fs';
const api = 'https://sign.dazr.eu/api/sign/v1';
const headers = { Authorization: 'Bearer ' + accessToken, 'Content-Type': 'application/json' };

let res = await fetch(api + '/documents', {
  method: 'POST',
  headers: { ...headers, 'Idempotency-Key': 'order-1042' },
  body: JSON.stringify({
    title: 'Service agreement',
    file: fs.readFileSync('agreement.pdf').toString('base64'),
    recipients: [
      { name: 'Alex Example', email: 'alex@example.eu' },
      { name: 'Sam Client', email: 'sam@client.example' },
    ],
  }),
});
const { document } = await res.json();

res = await fetch(api + '/documents/' + document.id + '/send', { method: 'POST', headers });
console.log((await res.json()).document.status); // "sent"

Teksttags

Typ de velden als tekst in de pdf. Elke tag wordt vervangen door een veld van dezelfde grootte of groter, en de tagtekst wordt overschilderd, zodat ondertekenaars die nooit zien.

TagVeld
{{signature:1}}Handtekening van de eerste ontvanger
{{initials:2}}Paraaf van de tweede ontvanger
{{name:1}} {{date:1}}Naam en datum van ondertekening, ingevuld door Dazr Sign
{{text:2:Company}}Een tekstveld met het label Company
{{checkbox:2:Terms:optional}}Een optioneel selectievakje
{{company:1}}Bedrijfsnaam (ingevuld wanneer de persoon namens een organisatie tekent)

Het getal is de positie van de ontvanger in recipients, vanaf 1. Een tag voor een ontvanger die je niet hebt opgegeven, voegt een lege ontvanger toe, in te vullen in de voorbereidingspop-up. Stuur "text_tags": false om tags te negeren. Je kunt ook fields sturen met posities in punten (1/72 inch) vanaf de linkerbovenhoek van de pagina: { "recipient": 1, "type": "signature", "page": 1, "x": 72, "y": 600, "width": 180, "height": 48 }. Een value op een tekst-, bedrijfs- of selectievakveld legt het vast: de ondertekenaar ziet het en kan het niet wijzigen.

Maak een concept met "prepare": { "origin": "https://app.example.eu" } en je krijgt een prepare_url. Open die in een pop-up: de persoon plaatst ontvangers en velden in een compacte editor en klikt dan op Versturen of Opslaan als sjabloon. Voor een ondertekenaar die aan de beurt is, geeft POST /documents/{id}/recipients/{recipient_id}/signing_url een ondertekenpop-up. Beide links zijn 10 tot 15 minuten geldig en werken één keer. Zo nodig meldt de persoon zich in de pop-up aan bij Dazr Identity, met het adres waarnaar het document is verstuurd.

Als het klaar is, stuurt de pop-up { type: 'dazr-sign', event, document_id, template_id, recipient_id, state } met postMessage naar de pagina die hem opende, alleen als die pagina op een van de pop-uporigins van je app staat (standaard de origins van je redirect-URI’s), en sluit dan. event is sent, saved, cancelled, signed of declined. Met redirect_uri (een van je geregistreerde redirect-URI’s) en state keert een pop-up die zijn opener kwijt is daarheen terug, met dezelfde waarden als queryparameters.

<script src="https://sign.dazr.eu/sdk.js"></script>
<script>
document.querySelector('#sign').addEventListener('click', async () => {
  // Ask your server for the URL after the click: the popup opens at once.
  const url = fetch('/my-server/prepare-url').then(r => r.json()).then(j => j.prepare_url);
  const result = await DazrSign.open(url);
  if (result.event === 'sent') showSent(result.document_id);
  // 'closed': the window was closed; check the status with the API or a webhook
});
</script>

Als je pagina Cross-Origin-Opener-Policy: same-origin stuurt, gebruik dan same-origin-allow-popups, anders kan de pop-up niets terugmelden.

Gekwalificeerde handtekeningen

Elke ondertekenaar heeft een level: "advanced" (standaard: het e-mailadres wordt bevestigd door in te loggen met Dazr Identity) of "qualified". Een gekwalificeerde ondertekenaar downloadt de pdf in Dazr Sign, ondertekent die met een eigen gekwalificeerde elektronische handtekening (een elektronische identiteitskaart, een ondertekeningsapp zoals itsme, een gekwalificeerd certificaat in Adobe Acrobat Reader) en uploadt het ondertekende bestand. Dazr Sign controleert het tegen de EU-vertrouwenslijsten en accepteert het alleen als het een gekwalificeerde handtekening is op precies het bestand dat Dazr Sign meegaf. Dazr geeft zelf geen gekwalificeerde handtekeningen uit.

Stel het niveau per ontvanger in: { "name": "Mario Rossi", "email": "mario@example.eu", "level": "qualified" }. Een gekwalificeerde ondertekenaar heeft geen paraafvelden. name_rule op het document bepaalt wat er gebeurt als de naam op het certificaat afwijkt van de naam van de ontvanger: "warn" (standaard: geaccepteerd, met name_matches false) of "block" (geweigerd). Sjablonen bewaren het niveau van elke rol, en from_template kan een rol verhogen naar "qualified".

Elke handtekening blijft geldig: latere handtekeningen en het afsluitende Dazr-zegel worden als incrementele updates toegevoegd, en de audittrail van zo’n document is een aparte verzegelde pdf op GET /documents/{id}/audit.pdf. Ontvangers in documenten en webhooks hebben level en, zodra een gekwalificeerde ondertekenaar heeft ondertekend, certificate: subject (common_name, given_name, surname, serial_number, country, organization, organization_identifier), issuer, serial, sha256, trust_service_provider, trusted_list_country, signing_time, trusted_timestamp, format (PAdES of CAdES) en name_matches. Elk ander level geeft 400 invalid_level.

Webhooks

Stel in het Sign-portaal onder Ontwikkelaars een webhook-URL in voor je app. Je krijgt het ondertekeningssecret één keer te zien. Dazr Sign stuurt sign.document.sent, viewed, signed, completed, declined, voided en expired voor de documenten die je app heeft gemaakt, met de status van het document en van de ontvangers, nooit de inhoud. Mislukte leveringen worden opnieuw geprobeerd na 5 minuten, 30 minuten, 2, 6, 12 en 24 uur; het leveringslog toont elke poging en kan er een opnieuw versturen.

// Node: check the Dazr-Signature header (t=<unix time>,v1=<HMAC-SHA256 hex>)
import crypto from 'node:crypto';

export function verify(rawBody, header, secret) {
  const m = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(header || '');
  if (!m || Math.abs(Date.now() / 1000 - Number(m[1])) > 300) return false;
  const want = crypto.createHmac('sha256', secret).update(m[1] + '.' + rawBody).digest();
  return crypto.timingSafeEqual(want, Buffer.from(m[2], 'hex'));
}
// The body: { id, type: 'sign.document.completed', created, data: { document: { id, status, recipients: [...] } } }

Naslag

Alle paden beginnen met https://sign.dazr.eu/api/sign/v1. Tijden zijn ISO 8601 in UTC.

VerzoekWat het doet
POST /documentsMaakt een concept van een pdf: file in base64, een multipart-upload (file plus data als JSON) of een upload_id. Optioneel: title, message, recipients, fields, signing_order, deadline_days, reminder_days, send, prepare.
POST /documents/from_templateMaakt een concept van een sjabloon: template_id, recipients als { role, name, email }, values per veld-ID of label.
GET /documentsToont de documenten van je app voor deze persoon, nieuwste eerst: limit (tot 100), cursor, status.
GET /documents/{id}Het document met zijn status, ontvangers en velden.
POST /documents/{id}/sendVerstuurt een concept.
POST /documents/{id}/remindHerinnert de ondertekenaars die aan de beurt zijn (hooguit één keer per uur).
POST /documents/{id}/voidAnnuleert een document dat ter ondertekening uitstaat, met een optionele reason.
DELETE /documents/{id}Verwijdert een concept of een afgesloten document.
POST /documents/{id}/prepare_urlEen nieuwe voorbereidingspop-up voor een concept: origin, redirect_uri, state.
POST /documents/{id}/recipients/{recipient_id}/signing_urlEen ondertekenpop-up voor een ondertekenaar die aan de beurt is: origin, redirect_uri, state.
GET /documents/{id}/original.pdfDe pdf zoals hij is verstuurd.
GET /documents/{id}/signed.pdfDe verzegelde kopie, zodra iedereen heeft getekend.
GET /documents/{id}/audit.jsonHet auditspoor: gebeurtenissen, hashes en ondertekenaars.
GET /documents/{id}/audit.pdfDe aparte, verzegelde audittrail van een document met gekwalificeerde ondertekenaars, zodra iedereen heeft ondertekend.
POST /uploadsStart een upload in delen voor pdf’s groter dan 4 MB: size. Daarna PUT /uploads/{upload_id}/parts/{n} met de ruwe bytes van elk deel.
GET /templatesDe sjablonen van de persoon, met hun rollen en velden.
GET /templates/{id}Eén sjabloon.
POST /templatesSlaat een van de documenten van je app op als sjabloon: document_id, name.
DELETE /templates/{id}Verwijdert een sjabloon.

Stuur een header Idempotency-Key mee wanneer je een document maakt: dezelfde sleutel en body binnen 24 uur geven hetzelfde document terug (header Idempotent-Replayed: true) in plaats van een tweede.

Fouten en limieten

Fouten hebben een HTTP-status en een body zoals { "error": { "code": "not_found", "message": "..." } }, soms met details zoals index.

StatusCodes
400invalid_field, invalid_recipients, invalid_email, not_pdf, pdf_unreadable, pdf_encrypted, invalid_origin, invalid_redirect_uri, unknown_role, unknown_field
401unauthenticated, invalid_token (verlopen of ingetrokken, of de persoon heeft je app verwijderd)
403insufficient_scope, sign_api_disabled
404not_found (ook voor documenten die je app niet heeft gemaakt), template_not_found
409not_draft, not_sent, not_your_turn, not_signable, signer_without_fields, no_signers, void_first, idempotency_in_progress
413pdf_too_large, too_large, quota
422idempotency_key_reused
429rate_limited, met een header Retry-After

Een app overdragen

Een app kan naar een andere organisatie op Dazr verhuizen, via App overdragen in de instellingen van de app. Met de Dazr Sign API aan kan dat alleen naar een geverifieerde organisatie, en een eigenaar of beheerder daar moet binnen 14 dagen accepteren. De ontwikkelaarsdocumentatie van Dazr Identity beschrijft elke stap.