Titus Docs · TitusOne
Programadores

API de integração

Crie recolhas a partir do seu CRM, envie o link ao cliente e receba os documentos por webhook. Especificação completa em /openapi.json (OpenAPI 3.1).

Autenticação

Crie uma chave em Escritório Virtual → Chaves de API e envie-a em todos os pedidos no cabeçalho Authorization: Bearer td_live_…. A chave só é mostrada uma vez; guarde-a num cofre e nunca a ponha em código do lado do navegador.

1. Ver o catálogo

GET /api/v1/integrations/document-types?locale=pt
GET /api/v1/integrations/document-types?kind=collect

Devolve value (o identificador a usar), source (AT, SS, BdP, IRN, ADENE, AIMA, IMT), kind (collect para recolha por robô, template para modelo em PDF), name e description.

2. Criar uma recolha

curl -X POST https://docs.titusone.pt/api/v1/integrations/recolhas \
  -H "Authorization: Bearer td_live_..." \
  -H "Idempotency-Key: crm-processo-118" \
  -H "Content-Type: application/json" \
  -d '{
    "client": { "name": "Titus Gorila", "email": "titus@exemplo.pt", "phone": "929999991", "externalId": "13838" },
    "documents": ["declaracao-modelo-3-irs", "mapa-responsabilidades-credito", "declaracao-situacao-contributiva"],
    "notes": "Para o pedido de crédito habitação.",
    "reference": "Processo 2026/118",
    "expiresInDays": 7
  }'
HTTP/1.1 201 Created
{
  "recolhaId": "4f7c…",
  "seqId": 1043,
  "clientId": "9b21…",
  "status": "criada",
  "paymentMode": "credits",
  "shareUrl": "https://docs.titusone.pt/r/Xk3…",
  "expiresAt": "2026-11-18T10:00:00.000Z"
}
  • Idempotency-Key é obrigatória. Repetir com a mesma chave e o mesmo corpo devolve a mesma resposta (sem gastar créditos outra vez); com outro corpo dá 409 idempotency_conflict.
  • O cliente é encontrado por externalId ou pelo e-mail. Com updateIfExists: true, a ficha é atualizada.
  • requester.email (opcional) tem de ser um membro ativo da sua conta; senão dá 403 requester_not_approved.
  • Cada documento gasta 1 crédito; sem créditos dá 402 insufficient_credits. Os documentos não obtidos devolvem o crédito.

3. Acompanhar

GET /api/v1/integrations/recolhas/{recolhaId}
GET /api/v1/integrations/recolhas/{recolhaId}/files/{fileId}

Estados da recolha: criada, aberta, em_curso, concluida, parcial, falhou, expirada, cancelada. Por documento: pendente, em_curso, obtido, sem_dados, erro, modelo.

4. Webhooks

Crie o endpoint em Escritório Virtual → Webhooks e guarde o segredo de assinatura (whsec_…). Quando a recolha termina enviamos recolha.completed:

POST https://o-seu-crm.pt/webhooks/titus-docs
X-TitusDocs-Event: recolha.completed
X-TitusDocs-Delivery: 812
X-TitusDocs-Signature: t=1762858800,v1=5d41402abc4b2a76b9719d911017c592...

{
  "event": "recolha.completed",
  "recolhaId": "4f7c…", "seqId": 1043, "clientId": "9b21…",
  "status": "concluida", "completedAt": "2026-11-11T10:07:41.000Z",
  "documents": [
    { "type": "declaracao-modelo-3-irs", "status": "obtido",
      "files": [{ "id": "…", "name": "Modelo 3 IRS 2025.pdf", "bytes": 182311, "sha256": "…",
                  "url": "https://docs.titusone.pt/api/v1/integrations/recolhas/4f7c…/files/…" }] }
  ]
}

Responda com um código 2xx em menos de 10 segundos. Se falhar, repetimos com espera crescente, até 8 tentativas, e pode reenviar à mão no Escritório. Pode haver repetições: deduplique por X-TitusDocs-Delivery ou por event + recolhaId.

Verificar a assinatura (Node.js)

import crypto from "node:crypto";

function assinaturaValida(segredo, cabecalho, corpoEmTexto) {
  const { t, v1 } = Object.fromEntries(cabecalho.split(",").map((p) => p.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;           // mais de 5 min: rejeitar
  const esperado = crypto.createHmac("sha256", segredo).update(`${t}.${corpoEmTexto}`).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(esperado), Buffer.from(v1));
}

Erros

Todos os erros têm o formato { "error": "texto", "code": "codigo" }. Os 500 e 503 podem ser repetidos com a mesma Idempotency-Key.

Documentação da API · Titus Docs