Dazr Sign API: documentazione per sviluppatori
Prepara e invia documenti da firmare dal tuo software, a nome delle persone che lo usano. Chi firma lo fa come sempre con Dazr Sign: con accesso tramite Dazr Identity, al proprio turno, una sola volta.
Guida rapida
- 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.
- Richiedi lo scope
sign. Fai passare le persone dal consueto flusso Accedi con Dazr Identity conscope=openid sign(aggiungioffline_accessper 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,emaile gli altri) serve anche la Dazr Identity API. - Chiama l’API con il token di accesso. L’indirizzo di base è
https://sign.dazr.eu/api/sign/v1. InviaAuthorization: Bearer <access token>e JSON. - 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.
| Tag | Campo |
|---|---|
{{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.
Popup: preparare e firmare
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.
| Richiesta | Cosa fa |
|---|---|
POST /documents | Crea 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_template | Crea una bozza da un modello: template_id, recipients come { role, name, email }, values per ID o etichetta del campo. |
GET /documents | Elenca 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}/send | Invia una bozza. |
POST /documents/{id}/remind | Ricorda la firma a chi è di turno (al massimo una volta all’ora). |
POST /documents/{id}/void | Annulla un documento in attesa di firma, con un reason facoltativo. |
DELETE /documents/{id} | Elimina una bozza o un documento chiuso. |
POST /documents/{id}/prepare_url | Un nuovo popup di preparazione per una bozza: origin, redirect_uri, state. |
POST /documents/{id}/recipients/{recipient_id}/signing_url | Un popup di firma per chi firma ed è di turno: origin, redirect_uri, state. |
GET /documents/{id}/original.pdf | Il PDF così come è stato inviato. |
GET /documents/{id}/signed.pdf | La copia sigillata, quando tutti hanno firmato. |
GET /documents/{id}/audit.json | L’audit trail: eventi, hash e firmatari. |
GET /documents/{id}/audit.pdf | L’audit trail separato e sigillato di un documento con firme qualificate, quando tutti hanno firmato. |
POST /uploads | Avvia un caricamento a parti per PDF oltre 4 MB: size. Poi PUT /uploads/{upload_id}/parts/{n} con i byte di ogni parte. |
GET /templates | I modelli della persona, con ruoli e campi. |
GET /templates/{id} | Un modello. |
POST /templates | Salva 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.
| Stato | Codici |
|---|---|
400 | invalid_field, invalid_recipients, invalid_email, not_pdf, pdf_unreadable, pdf_encrypted, invalid_origin, invalid_redirect_uri, unknown_role, unknown_field |
401 | unauthenticated, invalid_token (scaduto o revocato, oppure la persona ha rimosso la tua app) |
403 | insufficient_scope, sign_api_disabled |
404 | not_found (anche per i documenti che la tua app non ha creato), template_not_found |
409 | not_draft, not_sent, not_your_turn, not_signable, signer_without_fields, no_signers, void_first, idempotency_in_progress |
413 | pdf_too_large, too_large, quota |
422 | idempotency_key_reused |
429 | rate_limited, con un’intestazione Retry-After |
- PDF fino a 25 MB e 200 pagine, senza password. Richieste fino a 4 MB; i PDF più grandi passano da
/uploads. - Fino a 20 destinatari e 400 campi per documento, 100 modelli per persona. Documenti e modelli contano nello spazio Dazr della persona.
- 120 richieste al minuto per persona per app, 30 nuovi documenti ogni 10 minuti e 30 invii all’ora.
- I token di accesso durano 10 minuti. Usa il refresh token (
offline_access) per ottenerne uno nuovo.
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.
- I documenti creati dalla tua app prima del trasferimento restano alle persone a cui appartengono. L’app non li vede più tramite l’API e non vengono inviati webhook per loro.
- L’URL del webhook e le origini dei popup restano. Il secret di firma del webhook viene rinnovato e mostrato una volta sola a chi accetta.
- I token di accesso e di aggiornamento emessi prima del trasferimento smettono di funzionare, e le persone approvano di nuovo l’app al prossimo accesso. I modelli appartengono alle persone e non cambiano.
- I conteggi dei documenti nel portale Sign ripartono dal trasferimento.