Dazr Sign API: Dokumentation für Entwickler

Schnellstart

  1. Aktivieren Sie die Dazr Sign API. Öffnen Sie im Sign-Portal Entwickler und wählen Sie für Ihre App Dazr Sign API aktivieren. Jede App Ihrer Organisation steht dort und in der Konsole von Dazr Identity, mit derselben Client-ID und demselben Secret; jede API wird einzeln aktiviert. Dort können Sie auch eine neue App registrieren.
  2. Fordern Sie den Scope sign an. Leiten Sie die Menschen durch den üblichen Ablauf Mit Dazr Identity anmelden mit scope=openid sign (mit offline_access für ein Refresh-Token). Der Zustimmungsbildschirm erklärt, dass Ihre App in ihrem Namen Dokumente zur Unterschrift vorbereiten und versenden und deren Status sehen darf. Dafür genügt die Dazr Sign API; für Daten der Menschen (profile, email und die anderen) muss auch die Dazr Identity API aktiviert sein.
  3. Rufen Sie die API mit dem Zugriffstoken auf. Die Basisadresse ist https://sign.dazr.eu/api/sign/v1. Senden Sie Authorization: Bearer <access token> und JSON.
  4. Erstellen und versenden Sie ein Dokument. Laden Sie ein PDF mit Text-Tags und einer Empfängerliste hoch und versenden Sie es, oder öffnen Sie das Vorbereitungs-Pop-up, damit die Person die Felder selbst platziert.
// 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"

Text-Tags

Schreiben Sie die Felder als Text in das PDF. Jedes Tag wird durch ein gleich großes oder größeres Feld ersetzt, und der Tag-Text wird überdeckt, sodass Unterzeichnende ihn nie sehen.

TagFeld
{{signature:1}}Unterschrift der ersten empfangenden Person
{{initials:2}}Initialen der zweiten empfangenden Person
{{name:1}} {{date:1}}Name und Datum der Unterschrift, von Dazr Sign ausgefüllt
{{text:2:Company}}Ein Textfeld mit der Beschriftung Company
{{checkbox:2:Terms:optional}}Ein optionales Kontrollkästchen
{{company:1}}Firmenname (ausgefüllt, wenn die Person im Namen einer Organisation unterschreibt)

Die Zahl ist die Position der empfangenden Person in recipients, ab 1. Ein Tag für eine nicht aufgeführte empfangende Person fügt eine leere hinzu, die im Vorbereitungs-Pop-up ergänzt wird. Senden Sie "text_tags": false, um Tags zu ignorieren. Sie können auch fields mit Positionen in Punkten (1/72 Zoll) ab der linken oberen Ecke der Seite senden: { "recipient": 1, "type": "signature", "page": 1, "x": 72, "y": 600, "width": 180, "height": 48 }. Ein value in einem Text-, Firmen- oder Kontrollkästchenfeld legt es fest: Die unterzeichnende Person sieht es und kann es nicht ändern.

Erstellen Sie einen Entwurf mit "prepare": { "origin": "https://app.example.eu" }, und Sie erhalten eine prepare_url. Öffnen Sie sie in einem Pop-up: Die Person platziert Empfangende und Felder in einem kompakten Editor und klickt dann auf Senden oder Als Vorlage speichern. Für eine unterzeichnende Person, die an der Reihe ist, liefert POST /documents/{id}/recipients/{recipient_id}/signing_url ein Unterschrifts-Pop-up. Beide Links gelten 10 bis 15 Minuten und funktionieren einmal. Bei Bedarf meldet sich die Person im Pop-up bei Dazr Identity an, mit der Adresse, an die das Dokument gesendet wurde.

Danach sendet das Pop-up { type: 'dazr-sign', event, document_id, template_id, recipient_id, state } per postMessage an die Seite, die es geöffnet hat, nur wenn diese Seite auf einem der Pop-up-Origins Ihrer App liegt (standardmäßig die Origins Ihrer Redirect-URIs), und schließt sich. event ist sent, saved, cancelled, signed oder declined. Mit redirect_uri (einer Ihrer registrierten Redirect-URIs) und state kehrt ein Pop-up ohne öffnende Seite dorthin zurück, mit denselben Werten als Query-Parameter.

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

Wenn Ihre Seite Cross-Origin-Opener-Policy: same-origin sendet, verwenden Sie stattdessen same-origin-allow-popups, sonst kann das Pop-up nichts zurückmelden.

Qualifizierte Signaturen

Jede unterzeichnende Person hat ein level: "advanced" (Standard: Die E-Mail-Adresse wird durch die Anmeldung mit Dazr Identity bestätigt) oder "qualified". Wer qualifiziert unterschreibt, lädt das PDF in Dazr Sign herunter, unterschreibt es mit der eigenen qualifizierten elektronischen Signatur (ein elektronischer Ausweis, eine Signatur-App wie itsme, ein qualifiziertes Zertifikat in Adobe Acrobat Reader) und lädt die unterschriebene Datei hoch. Dazr Sign prüft sie anhand der EU-Vertrauenslisten und nimmt sie nur an, wenn sie eine qualifizierte Signatur genau auf der ausgegebenen Datei ist. Dazr stellt selbst keine qualifizierten Signaturen aus.

Legen Sie das Niveau pro empfangende Person fest: { "name": "Mario Rossi", "email": "mario@example.eu", "level": "qualified" }. Wer qualifiziert unterschreibt, hat keine Initialenfelder. name_rule am Dokument legt fest, was passiert, wenn der Name im Zertifikat vom Namen der empfangenden Person abweicht: "warn" (Standard: angenommen, mit name_matches false) oder "block" (abgelehnt). Vorlagen behalten das Niveau jeder Rolle, und from_template kann eine Rolle auf "qualified" anheben.

Jede Signatur bleibt gültig: Spätere Signaturen und das abschließende Dazr-Siegel werden als inkrementelle Aktualisierungen hinzugefügt, und das Prüfprotokoll eines solchen Dokuments ist ein separates versiegeltes PDF unter GET /documents/{id}/audit.pdf. Empfangende Personen in Dokumenten und Webhooks haben level und, sobald qualifiziert unterschrieben wurde, 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 oder CAdES) und name_matches. Jedes andere level ergibt 400 invalid_level.

Webhooks

Legen Sie im Sign-Portal unter Entwickler eine Webhook-URL für Ihre App fest. Das Signatur-Secret sehen Sie einmal. Dazr Sign sendet sign.document.sent, viewed, signed, completed, declined, voided und expired für die Dokumente, die Ihre App erstellt hat, mit dem Status des Dokuments und der Empfangenden, nie mit dem Inhalt. Fehlgeschlagene Zustellungen werden nach 5 Minuten, 30 Minuten, 2, 6, 12 und 24 Stunden wiederholt; das Zustellprotokoll zeigt jeden Versuch und kann eine Zustellung erneut senden.

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

Referenz

Alle Pfade beginnen mit https://sign.dazr.eu/api/sign/v1. Zeiten sind ISO 8601 in UTC.

AnfrageWas sie bewirkt
POST /documentsErstellt einen Entwurf aus einem PDF: file in Base64, ein Multipart-Upload (file plus data als JSON) oder eine upload_id. Optional: title, message, recipients, fields, signing_order, deadline_days, reminder_days, send, prepare.
POST /documents/from_templateErstellt einen Entwurf aus einer Vorlage: template_id, recipients als { role, name, email }, values nach Feld-ID oder Beschriftung.
GET /documentsListet die Dokumente Ihrer App für diese Person auf, neueste zuerst: limit (bis 100), cursor, status.
GET /documents/{id}Das Dokument mit Status, Empfangenden und Feldern.
POST /documents/{id}/sendVersendet einen Entwurf.
POST /documents/{id}/remindErinnert die Unterzeichnenden, die an der Reihe sind (höchstens einmal pro Stunde).
POST /documents/{id}/voidStorniert ein Dokument, das zur Unterschrift versendet ist, mit optionalem reason.
DELETE /documents/{id}Löscht einen Entwurf oder ein abgeschlossenes Dokument.
POST /documents/{id}/prepare_urlEin neues Vorbereitungs-Pop-up für einen Entwurf: origin, redirect_uri, state.
POST /documents/{id}/recipients/{recipient_id}/signing_urlEin Unterschrifts-Pop-up für eine unterzeichnende Person, die an der Reihe ist: origin, redirect_uri, state.
GET /documents/{id}/original.pdfDas PDF, wie es versendet wurde.
GET /documents/{id}/signed.pdfDie versiegelte Kopie, sobald alle unterschrieben haben.
GET /documents/{id}/audit.jsonDer Prüfpfad: Ereignisse, Hashes und Unterzeichnende.
GET /documents/{id}/audit.pdfDas separate, versiegelte Prüfprotokoll eines Dokuments mit qualifizierten Signaturen, sobald alle unterschrieben haben.
POST /uploadsStartet einen Upload in Teilen für PDFs über 4 MB: size. Danach PUT /uploads/{upload_id}/parts/{n} mit den Rohbytes jedes Teils.
GET /templatesDie Vorlagen der Person, mit Rollen und Feldern.
GET /templates/{id}Eine Vorlage.
POST /templatesSpeichert eines der Dokumente Ihrer App als Vorlage: document_id, name.
DELETE /templates/{id}Löscht eine Vorlage.

Senden Sie beim Erstellen eines Dokuments einen Header Idempotency-Key: Derselbe Schlüssel und derselbe Body innerhalb von 24 Stunden liefern dasselbe Dokument (Header Idempotent-Replayed: true) statt eines zweiten.

Fehler und Grenzen

Fehler haben einen HTTP-Status und einen Body wie { "error": { "code": "not_found", "message": "..." } }, manchmal mit Details wie 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 (abgelaufen oder widerrufen, oder die Person hat Ihre App entfernt)
403insufficient_scope, sign_api_disabled
404not_found (auch für Dokumente, die Ihre App nicht erstellt hat), 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, mit einem Header Retry-After

Eine App übertragen

Eine App kann zu einer anderen Organisation auf Dazr wechseln, unter App übertragen in den Einstellungen der App. Mit aktivierter Dazr Sign API geht das nur an eine verifizierte Organisation, und eine Person mit der Rolle Inhaber oder Admin dort muss innerhalb von 14 Tagen annehmen. Die Entwicklerdokumentation von Dazr Identity beschreibt jeden Schritt.