Dazr Sign API: documentazione per sviluppatori

Guida rapida

  1. Attiva la Dazr Sign API. Nel portale Sign apri Sviluppatori e scegli Attiva Dazr Sign API per la tua app. Ogni app della tua organizzazione è elencata lì e nella console di Dazr Identity, con lo stesso client ID e lo stesso secret; ogni API si attiva a parte. Lì puoi anche registrare una nuova app.
  2. Richiedi lo scope sign. Fai passare le persone dal consueto flusso Accedi con Dazr Identity con scope=openid sign (aggiungi offline_access per un refresh token). La schermata di consenso spiega che la tua app può preparare e inviare documenti da firmare a loro nome e vederne lo stato. Basta la Dazr Sign API; per chiedere anche i dati delle persone (profile, email e gli altri) serve anche la Dazr Identity API.
  3. Chiama l’API con il token di accesso. L’indirizzo di base è https://sign.dazr.eu/api/sign/v1. Invia Authorization: Bearer <access token> e JSON.
  4. Crea e invia un documento. Carica un PDF con tag di testo e un elenco di destinatari e invialo, oppure apri il popup di preparazione per far posizionare i campi alla persona.
// 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"

Tag di testo

Scrivi i campi nel PDF come testo. Ogni tag viene sostituito da un campo della stessa dimensione o più grande, e il testo del tag viene coperto, così chi firma non lo vede mai.

TagCampo
{{signature:1}}Firma del primo destinatario
{{initials:2}}Iniziali del secondo destinatario
{{name:1}} {{date:1}}Nome e data della firma, compilati da Dazr Sign
{{text:2:Company}}Un campo di testo con l’etichetta Company
{{checkbox:2:Terms:optional}}Una casella di controllo facoltativa
{{company:1}}Ragione sociale (compilata quando la persona firma per conto di un’organizzazione)

Il numero è la posizione del destinatario in recipients, a partire da 1. Un tag per un destinatario non indicato aggiunge un destinatario vuoto, da completare nel popup di preparazione. Invia "text_tags": false per ignorare i tag. Puoi anche inviare fields con posizioni in punti (1/72 di pollice) dall’angolo in alto a sinistra della pagina: { "recipient": 1, "type": "signature", "page": 1, "x": 72, "y": 600, "width": 180, "height": 48 }. Un value su un campo di testo, ragione sociale o casella lo fissa: chi firma lo vede ma non può modificarlo.

Crea una bozza con "prepare": { "origin": "https://app.example.eu" } e ricevi un prepare_url. Aprilo in un popup: la persona posiziona destinatari e campi in un editor compatto, poi fa clic su Invia o Salva come modello. Per chi firma ed è di turno, POST /documents/{id}/recipients/{recipient_id}/signing_url restituisce un popup di firma. Entrambi i link valgono da 10 a 15 minuti e funzionano una sola volta. Se serve, la persona accede a Dazr Identity nel popup, con l’indirizzo a cui è stato inviato il documento.

Al termine, il popup invia { type: 'dazr-sign', event, document_id, template_id, recipient_id, state } con postMessage alla pagina che lo ha aperto, solo se quella pagina si trova su una delle origini popup della tua app (di default, le origini dei tuoi redirect URI), e si chiude. event è sent, saved, cancelled, signed o declined. Con redirect_uri (uno dei tuoi redirect URI registrati) e state, un popup che ha perso la pagina di origine torna lì con gli stessi valori come parametri della query.

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

Se la tua pagina invia Cross-Origin-Opener-Policy: same-origin, usa invece same-origin-allow-popups, altrimenti il popup non può comunicare il risultato.

Firme qualificate

Ogni firmatario ha un level: "advanced" (predefinito: l’indirizzo email è confermato accedendo con Dazr Identity) oppure "qualified". Chi firma con firma qualificata scarica il PDF in Dazr Sign, lo firma con la propria firma elettronica qualificata (una carta d’identità elettronica, un’app di firma come itsme, un certificato qualificato in Adobe Acrobat Reader) e carica il file firmato. Dazr Sign lo verifica con le liste di fiducia UE e lo accetta solo se è una firma qualificata esattamente sul file consegnato. Dazr non rilascia firme qualificate.

Imposta il livello per ogni destinatario: { "name": "Mario Rossi", "email": "mario@example.eu", "level": "qualified" }. Chi firma con firma qualificata non ha campi per le sigle. name_rule sul documento stabilisce cosa succede se il nome sul certificato è diverso da quello del destinatario: "warn" (predefinito: accettata, con name_matches false) o "block" (rifiutata). I modelli conservano il livello di ogni ruolo, e from_template può alzare un ruolo a "qualified".

Ogni firma resta valida: le firme successive e il sigillo finale di Dazr vengono aggiunti come aggiornamenti incrementali, e l’audit trail di questi documenti è un PDF sigillato separato in GET /documents/{id}/audit.pdf. I destinatari nei documenti e nei webhook hanno level e, dopo la firma qualificata, 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 o CAdES) e name_matches. Qualsiasi altro level restituisce 400 invalid_level.

Webhook

Imposta un URL webhook per la tua app nel portale Sign, in Sviluppatori. Vedi il secret di firma una sola volta. Dazr Sign invia sign.document.sent, viewed, signed, completed, declined, voided ed expired per i documenti creati dalla tua app, con lo stato del documento e dei destinatari, mai il contenuto. Le consegne non riuscite vengono ritentate dopo 5 minuti, 30 minuti, 2, 6, 12 e 24 ore; il registro delle consegne mostra ogni tentativo e permette di reinviarne una.

// 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: [...] } } }

Riferimento

Tutti i percorsi iniziano con https://sign.dazr.eu/api/sign/v1. Gli orari sono in ISO 8601, UTC.

RichiestaCosa fa
POST /documentsCrea una bozza da un PDF: file in base64, un caricamento multipart (file più data come JSON) o un upload_id. Facoltativi: title, message, recipients, fields, signing_order, deadline_days, reminder_days, send, prepare.
POST /documents/from_templateCrea una bozza da un modello: template_id, recipients come { role, name, email }, values per ID o etichetta del campo.
GET /documentsElenca i documenti della tua app per questa persona, dai più recenti: limit (fino a 100), cursor, status.
GET /documents/{id}Il documento con stato, destinatari e campi.
POST /documents/{id}/sendInvia una bozza.
POST /documents/{id}/remindRicorda la firma a chi è di turno (al massimo una volta all’ora).
POST /documents/{id}/voidAnnulla un documento in attesa di firma, con un reason facoltativo.
DELETE /documents/{id}Elimina una bozza o un documento chiuso.
POST /documents/{id}/prepare_urlUn nuovo popup di preparazione per una bozza: origin, redirect_uri, state.
POST /documents/{id}/recipients/{recipient_id}/signing_urlUn popup di firma per chi firma ed è di turno: origin, redirect_uri, state.
GET /documents/{id}/original.pdfIl PDF così come è stato inviato.
GET /documents/{id}/signed.pdfLa copia sigillata, quando tutti hanno firmato.
GET /documents/{id}/audit.jsonL’audit trail: eventi, hash e firmatari.
GET /documents/{id}/audit.pdfL’audit trail separato e sigillato di un documento con firme qualificate, quando tutti hanno firmato.
POST /uploadsAvvia un caricamento a parti per PDF oltre 4 MB: size. Poi PUT /uploads/{upload_id}/parts/{n} con i byte di ogni parte.
GET /templatesI modelli della persona, con ruoli e campi.
GET /templates/{id}Un modello.
POST /templatesSalva come modello uno dei documenti della tua app: document_id, name.
DELETE /templates/{id}Elimina un modello.

Invia un’intestazione Idempotency-Key quando crei un documento: la stessa chiave e lo stesso corpo entro 24 ore restituiscono lo stesso documento (intestazione Idempotent-Replayed: true) invece di crearne un secondo.

Errori e limiti

Gli errori hanno uno stato HTTP e un corpo come { "error": { "code": "not_found", "message": "..." } }, a volte con dettagli come index.

StatoCodici
400invalid_field, invalid_recipients, invalid_email, not_pdf, pdf_unreadable, pdf_encrypted, invalid_origin, invalid_redirect_uri, unknown_role, unknown_field
401unauthenticated, invalid_token (scaduto o revocato, oppure la persona ha rimosso la tua app)
403insufficient_scope, sign_api_disabled
404not_found (anche per i documenti che la tua app non ha creato), 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, con un’intestazione Retry-After

Trasferire un’app

Un’app può passare a un’altra organizzazione registrata su Dazr, con Trasferisci app nelle impostazioni dell’app. Con la Dazr Sign API attiva può passare solo a un’organizzazione verificata, e chi la possiede o la amministra deve accettare entro 14 giorni. La documentazione per sviluppatori di Dazr Identity descrive ogni passaggio.