API do Dazr Sign: documentação para programadores

Início rápido

  1. Ative a API do Dazr Sign. No portal do Sign, abra Programadores e escolha Ativar a API do Dazr Sign para a sua aplicação. Todas as aplicações da sua organização aparecem aí e na consola do Dazr Identity, com o mesmo ID e segredo de cliente; cada API é ativada separadamente. Também pode registar aí uma nova aplicação.
  2. Peça o âmbito sign. Envie as pessoas pelo fluxo habitual Iniciar sessão com Dazr Identity com scope=openid sign (acrescente offline_access para um refresh token). O ecrã de consentimento indica que a sua aplicação pode preparar e enviar documentos para assinatura em nome da pessoa e ver o seu estado. Isto funciona só com a API do Dazr Sign; pedir também dados das pessoas (profile, email e os outros) exige que a API do Dazr Identity também esteja ativa.
  3. Chame a API com o token de acesso. O endereço base é https://sign.dazr.eu/api/sign/v1. Envie Authorization: Bearer <access token> e JSON.
  4. Crie e envie um documento. Carregue um PDF com etiquetas de texto e uma lista de destinatários e depois envie-o, ou abra a janela de preparação para que a pessoa coloque os campos.
// 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"

Etiquetas de texto

Escreva os campos no PDF como texto. Cada etiqueta é substituída por um campo do mesmo tamanho ou maior, e o texto da etiqueta é coberto, para que os signatários nunca o vejam.

EtiquetaCampo
{{signature:1}}Assinatura do primeiro destinatário
{{initials:2}}Rubrica do segundo destinatário
{{name:1}} {{date:1}}Nome e data da assinatura, preenchidos pelo Dazr Sign
{{text:2:Company}}Um campo de texto com a legenda Empresa
{{checkbox:2:Terms:optional}}Uma caixa de verificação opcional
{{company:1}}Nome da empresa (preenchido quando a pessoa assina em nome de uma organização)

O número é a posição do destinatário em recipients, a começar em 1. Uma etiqueta para um destinatário que não indicou acrescenta um destinatário vazio, a preencher na janela de preparação. Envie "text_tags": false para ignorar as etiquetas. Também pode enviar fields com posições em pontos (1/72 de polegada) a partir do canto superior esquerdo da página: { "recipient": 1, "type": "signature", "page": 1, "x": 72, "y": 600, "width": 180, "height": 48 }. Um value num campo de texto, empresa ou caixa de verificação fixa-o: o signatário vê-o e não o pode alterar.

Crie um rascunho com "prepare": { "origin": "https://app.example.eu" } e recebe um prepare_url. Abra-o numa janela pop-up: a pessoa coloca destinatários e campos num editor compacto e depois clica em Enviar ou Guardar como modelo. Para um signatário cuja vez chegou, POST /documents/{id}/recipients/{recipient_id}/signing_url dá uma janela de assinatura. Ambas as ligações são válidas durante 10 a 15 minutos e funcionam uma vez. A pessoa inicia sessão com o Dazr Identity dentro da janela, se necessário, com o endereço para onde o documento foi enviado.

Quando termina, a janela envia { type: 'dazr-sign', event, document_id, template_id, recipient_id, state } com postMessage para a página que a abriu, só se essa página estiver numa das origens de pop-up da sua aplicação (por defeito, as origens dos seus URIs de redirecionamento), e fecha-se. event é sent, saved, cancelled, signed ou declined. Com redirect_uri (um dos seus URIs de redirecionamento registados) e state, uma janela que perdeu a página de origem volta para lá com os mesmos valores como parâmetros de consulta.

<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 a sua página enviar Cross-Origin-Opener-Policy: same-origin, use same-origin-allow-popups, caso contrário a janela não consegue comunicar o resultado.

Assinaturas qualificadas

Cada signatário tem um level: "advanced" (a predefinição: o endereço de e-mail é confirmado ao iniciar sessão com o Dazr Identity) ou "qualified". Um signatário qualificado transfere o PDF no Dazr Sign, assina-o com a sua própria assinatura eletrónica qualificada (um cartão de cidadão, uma aplicação de assinatura como o itsme, um certificado qualificado no Adobe Acrobat Reader) e carrega o ficheiro assinado. O Dazr Sign verifica-o com as listas de confiança da UE e só o aceita se for uma assinatura qualificada exatamente sobre o ficheiro que entregou. O Dazr não emite assinaturas qualificadas.

Defina o nível por destinatário: { "name": "Mario Rossi", "email": "mario@example.eu", "level": "qualified" }. Um signatário qualificado não tem campos de rubrica. name_rule no documento indica o que acontece quando o nome no certificado difere do nome do destinatário: "warn" (a predefinição: aceite, com name_matches false) ou "block" (recusado). Os modelos mantêm o nível de cada função, e from_template pode elevar uma função a "qualified".

Todas as assinaturas continuam válidas: as assinaturas posteriores e o selo final do Dazr são acrescentados como atualizações incrementais, e o registo de auditoria de um documento destes é um PDF selado separado em GET /documents/{id}/audit.pdf. Os destinatários nos documentos e webhooks têm level e, depois de um signatário qualificado ter assinado, 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 ou CAdES) e name_matches. Qualquer outro level dá 400 invalid_level.

Webhooks

Defina um URL de webhook para a sua aplicação no portal do Sign, em Programadores. Recebe o respetivo segredo de assinatura uma vez. O Dazr Sign envia sign.document.sent, viewed, signed, completed, declined, voided e expired para os documentos que a sua aplicação criou, com o estado do documento e o estado dos destinatários, nunca o conteúdo. As entregas falhadas são repetidas após 5 minutos, 30 minutos, 2, 6, 12 e 24 horas; o registo de entregas mostra cada tentativa e pode reenviar uma.

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

Referência

Todos os caminhos começam por https://sign.dazr.eu/api/sign/v1. As horas estão em ISO 8601, em UTC.

PedidoO que faz
POST /documentsCria um rascunho a partir de um PDF: file em base64, um carregamento multipart (file e data como JSON) ou um upload_id. Opcional: title, message, recipients, fields, signing_order, deadline_days, reminder_days, send, prepare.
POST /documents/from_templateCria um rascunho a partir de um modelo: template_id, recipients como { role, name, email }, values por ID ou legenda do campo.
GET /documentsLista os documentos da sua aplicação para esta pessoa, os mais recentes primeiro: limit (até 100), cursor, status.
GET /documents/{id}O documento com o estado, os destinatários e os campos.
POST /documents/{id}/sendEnvia um rascunho.
POST /documents/{id}/remindLembra os signatários cuja vez chegou (no máximo uma vez por hora).
POST /documents/{id}/voidCancela um documento em assinatura, com um reason opcional.
DELETE /documents/{id}Elimina um rascunho ou um documento encerrado.
POST /documents/{id}/prepare_urlUma nova janela de preparação para um rascunho: origin, redirect_uri, state.
POST /documents/{id}/recipients/{recipient_id}/signing_urlUma janela de assinatura para um signatário cuja vez chegou: origin, redirect_uri, state.
GET /documents/{id}/original.pdfO PDF tal como foi enviado.
GET /documents/{id}/signed.pdfA cópia selada, depois de todos terem assinado.
GET /documents/{id}/audit.jsonO registo de auditoria: eventos, hashes e signatários.
GET /documents/{id}/audit.pdfO registo de auditoria separado e selado de um documento com signatários qualificados, depois de todos terem assinado.
POST /uploadsInicia um carregamento por partes para PDF com mais de 4 MB: size. Depois PUT /uploads/{upload_id}/parts/{n} com os bytes de cada parte.
GET /templatesOs modelos da pessoa, com as respetivas funções e campos.
GET /templates/{id}Um modelo.
POST /templatesGuarda um dos documentos da sua aplicação como modelo: document_id, name.
DELETE /templates/{id}Elimina um modelo.

Envie um cabeçalho Idempotency-Key quando cria um documento: a mesma chave e o mesmo corpo em 24 horas devolvem o mesmo documento (cabeçalho Idempotent-Replayed: true) em vez de um segundo.

Erros e limites

Os erros têm um estado HTTP e um corpo como { "error": { "code": "not_found", "message": "..." } }, por vezes com pormenores como index.

EstatutoCódigos
400invalid_field, invalid_recipients, invalid_email, not_pdf, pdf_unreadable, pdf_encrypted, invalid_origin, invalid_redirect_uri, unknown_role, unknown_field
401unauthenticated, invalid_token (expirado ou revogado, ou a pessoa removeu a sua aplicação)
403insufficient_scope, sign_api_disabled
404not_found (também para documentos que a sua aplicação não criou), 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, com um cabeçalho Retry-After

Transferir uma aplicação

Uma aplicação pode passar para outra organização registada na Dazr, em Transferir aplicação, nas definições da aplicação. Com a API do Dazr Sign ativada, só pode passar para uma organização verificada, e um proprietário ou administrador dessa organização tem de a aceitar no prazo de 14 dias. A documentação para programadores do Dazr Identity descreve cada passo.