Documentação da API Rubriq
API REST pra integrar o Rubriq em sistemas externos. Crie assinaturas,
templates, contatos e webhooks. Toda a superfície da plataforma fica
sob /v1/, autenticada por API key.
https://api.rubriq.com.br
Mesma URL pra todos os endpoints. HTTPS obrigatório.
contato@rubriq.com.br
Dúvidas, bugs, sugestões — respondemos em até 1 dia útil.
Visão geral em 3 minutos
- Gere uma API key no painel da Rubriq (planos Pro e Business).
- Crie templates de assinatura (posições de cada signatário no PDF) — opcional, mas acelera.
- Faça
POST /v1/assinaturascom o PDF em base64 + lista de signatários. - Configure um webhook pra receber
assinatura.concluidaquando todos assinarem. - Baixe o PDF final selado pelo
GET /v1/assinaturas/:id/documento.
Autenticação
A API /v1/ exige uma API key (prefixo
rbq_live_…). Gere/gerencie em Acesso API
dentro do painel (disponível nos planos Pro e Business).
Você pode mandar a key em qualquer um destes headers:
Authorization: Bearer rbq_live_xxxxxxxxxxxxxxxxxxxxxxxx
# ou
x-api-key: rbq_live_xxxxxxxxxxxxxxxxxxxxxxxx
A key é validada a cada requisição. Verificamos que a organização está
ativa, que o plano tem a feature api_access, e
atualizamos o contador de uso pra rate-limit.
- Dashboard (rotas sem
/v1/): Firebase ID token emAuthorization: Bearer …— usado pelo app web do Rubriq. - Signer público (
/assinaturas/token/:token/…): token opaco enviado por e-mail/WhatsApp pro signatário. Sem auth de header.
Boas práticas
- Nunca exponha a key no front-end. Trate como senha.
- Use uma key por integração — facilita revogar uma sem derrubar as outras.
- Roteie chamadas pelo servidor (não direto do browser do usuário).
Formato de resposta
Toda resposta é JSON com a forma { "ok": boolean, ... }.
Sucesso
{
"ok": true,
"data": { ... }
}
Erro
{
"ok": false,
"error": "Mensagem amigável",
"code": "quota_exceeded"
}
Códigos HTTP típicos
| Status | Significa |
|---|---|
200 | Sucesso |
400 | Validação (parâmetro faltando / formato errado) |
401 | API key ausente ou inválida |
402 | Plano não cobre a feature ou cota de IA esgotada |
403 | Organização suspensa |
404 | Recurso não encontrado |
409 | Estado incompatível (ex: cancelar doc já assinado) |
429 | Rate-limit ou cota mensal de assinaturas esgotada |
5xx | Erro interno do servidor |
Rate limit & cotas
- Rate limit: 60 requisições/min por API key. Headers
X-RateLimit-*em toda resposta. - Cota de assinaturas: definida pelo plano (Pro 20/50/100, Business ilimitado). Estouro:
429 quota_exceeded. - Cota de IA: Free = 5 usos/mês; Pro/Business = ilimitado. Endpoints de IA retornam
402 ia_quota_exceeded. - Tamanho do PDF: 20 MB.
- Batch: 100 itens por requisição.
Convenções
Datas
Todas as datas/horas seguem ISO 8601 com timezone: 2026-12-31T23:59:59Z ou 2026-12-31T20:59:59-03:00.
CPF / CNPJ / WhatsApp
Aceitamos com ou sem máscara. Internamente normalizamos pra só dígitos. WhatsApp em formato E.164 com + (+5511999990000).
Posicionamento de assinatura
Coordenadas x e y em % da página (0–100). A âncora é a base-centro: a base do rabisco encosta na linha y%.
IDs
IDs de assinatura, template, pasta, contato são strings opacas. Não tente parsear/inferir significado.
/v1/assinaturas
criar uma
Cria uma assinatura. O PDF entra em base64 (até 20 MB). Os signatários recebem o convite por e-mail e/ou WhatsApp automaticamente.
Body
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
documentoNome | string | sim | Nome exibido pro signatário. Inclui no PDF de comprovante. |
documentoBase64 | string | sim | PDF em base64 com prefixo data:application/pdf;base64,… |
signatarios | array | sim | Lista de signatários. Pelo menos 1. Schema. |
templateId | string | — | Usa posições/papéis salvos no template. Alternativa a posicoesOverride. |
posicoesOverride | array | — | Posições explícitas (ignora template). Schema. |
pastaId | string | — | Move pra essa pasta após criação. |
expiraEm | ISO date | — | Data limite — após isso o link expira. |
tags | string[] | — | Tags pra busca/filtro. |
metodoAutenticacao | string | — | "qualquer" (padrão) ou "icp_brasil" (força certificado digital — Business). |
Schema do signatário
| Campo | Tipo | Notas |
|---|---|---|
nome | string | Obrigatório. |
cpf | string | Opcional. Com ou sem máscara. |
email | string | Pelo menos email OU whatsapp obrigatório. |
whatsapp | string | E.164: +5511999990001. |
role | string | Bate com signatarioRole do template. Ex: CONTRATANTE, TESTEMUNHA. |
Schema de posição
| Campo | Tipo | Notas |
|---|---|---|
pagina | number | 1-indexed. |
x | number | 0–100 (% da largura). |
y | number | 0–100 (% da altura, top-down). |
tipo | string | assinatura, rubrica, nome, cpf, data. |
signatarioIdx | number | Índice no array signatarios (0-based). |
Exemplo de requisição
curl -X POST https://api.rubriq.com.br/v1/assinaturas \
-H "Authorization: Bearer $RBQ_KEY" \
-H "Content-Type: application/json" \
-d '{
"documentoNome": "Contrato — Cliente X",
"documentoBase64": "data:application/pdf;base64,JVBERi0xLjQK...",
"signatarios": [
{
"nome": "Maria Souza",
"cpf": "12345678909",
"whatsapp": "+5511999990001",
"email": "maria@x.com",
"role": "CONTRATANTE"
}
],
"templateId": "contrato-cliente",
"tags": ["vendas", "q1"]
}'
Resposta de sucesso
{
"ok": true,
"data": {
"id": "abc123",
"documentoNome": "Contrato — Cliente X",
"status": "PENDENTE",
"totalSignatarios": 1,
"templateId": "contrato-cliente",
"criadoEm": "2026-05-23T18:00:00Z",
"signatarios": [
{ "nome": "Maria Souza", "role": "CONTRATANTE", "email": "maria@x.com" }
]
}
}
Erros comuns
| Status | Code | Quando |
|---|---|---|
| 400 | posicao_ausente | Sem templateId, sem posicoesOverride e nome do arquivo não bate com template salvo. |
| 402 | feature_requires_upgrade | metodoAutenticacao=icp_brasil em plano não-Business. |
| 429 | quota_exceeded | Cota mensal de assinaturas esgotada. |
/v1/assinaturas
listar
Query params
| Param | Valor |
|---|---|
status | PENDENTE | PARCIAL | ASSINADO | CANCELADO |
vista | ativos (padrão) | arquivados | lixeira |
q | Busca por nome do documento |
tag | Filtra por tag exata |
cpf | CPF de algum signatário (com ou sem máscara) |
desde / ate | ISO date (filtra criadoEm) |
limit | Padrão 50, máximo 200 |
curl -H "Authorization: Bearer $RBQ_KEY" \
"https://api.rubriq.com.br/v1/assinaturas?status=PENDENTE&limit=20"
/v1/assinaturas/:id
detalhe
Retorna metadados completos da assinatura, incluindo lista de signatários (sem o token opaco do signer).
Query params
| Param | Valor |
|---|---|
incluirEventos | 1 — adiciona eventos[] na resposta (trilha forense com IP/UA por evento) |
Resposta
{
"ok": true,
"data": {
"id": "abc123",
"documentoNome": "Contrato — Cliente X",
"status": "ASSINADO",
"metodoAutenticacao": "qualquer",
"icpBrasilSelado": false,
"totalSignatarios": 1,
"assinados": 1,
"criadoEm": "2026-05-23T18:00:00Z",
"assinadoEm": "2026-05-23T19:42:11Z",
"hashFinal": "ff29dfd84ca10b29c3d8c35ea94eb3ba…",
"tags": ["vendas", "q1"],
"pastaId": "pasta-a",
"signatarios": [
{
"nome": "Maria Souza",
"cpf": "12345678909",
"role": "CONTRATANTE",
"email": "maria@x.com",
"assinadoEm": "2026-05-23T19:42:11Z",
"ip": "200.x.x.x",
"userAgent": "Mozilla/5.0…",
"assinaturaTipo": "icp_brasil",
"icpBrasil": {
"cn": "MARIA SOUZA",
"ac": "AC SOLUTI Multipla v5",
"tipo": "PF",
"numeroSerie": "0x9c6b…",
"validadeFim": "2027-04-17T23:59:59Z"
}
}
]
}
}
/v1/assinaturas/:id/eventos
trilha forense
Endpoint dedicado pra trilha de auditoria completa — todos os eventos no ciclo de vida da assinatura, com IP, user agent e detalhes específicos por tipo. Ideal pra integradores que exibem a timeline forense pro cliente final.
Tipos de evento
| Tipo | Detalhes notáveis |
|---|---|
criada | usuario, totalSignatarios, templateId |
aberto | signatarioIdx, ip, userAgent |
otp_solicitado / otp_email_solicitado / otp_whatsapp_solicitado / otp_sms_solicitado | signatarioIdx, ip |
otp_invalido | signatarioIdx, ip — tentativa falha |
assinado / assinado_admin / assinado_icp | signatarioIdx, ip, userAgent, detalhes do cert quando ICP |
finalizado | detalhes.hashFinal, detalhes.icpBrasil |
email_reenviado | signatarioIdx |
cancelada | usuario |
arquivada / restaurada / movido_lixeira | usuario, ip |
Resposta
{
"ok": true,
"data": {
"total": 6,
"eventos": [
{ "tipo": "criada", "timestamp": "2026-05-23T18:00:00Z",
"usuario": { "uid": "abc", "email": "voce@empresa.com" },
"detalhes": { "totalSignatarios": 1, "templateId": "contrato" } },
{ "tipo": "aberto", "timestamp": "2026-05-23T19:30:11Z",
"signatarioIdx": 0, "ip": "200.x.x.x", "userAgent": "Mozilla/5.0…" },
{ "tipo": "otp_email_solicitado", "timestamp": "2026-05-23T19:31:05Z",
"signatarioIdx": 0, "ip": "200.x.x.x" },
{ "tipo": "assinado_icp", "timestamp": "2026-05-23T19:42:11Z",
"signatarioIdx": 0, "ip": "200.x.x.x", "userAgent": "Mozilla/5.0…",
"detalhes": { "ac": "AC SOLUTI…", "numeroSerie": "0x9c6b…",
"hashCertHex": "abc123…" } },
{ "tipo": "finalizado", "timestamp": "2026-05-23T19:42:13Z",
"detalhes": { "hashFinal": "ff29dfd…", "icpBrasil": true } }
]
}
}
GET /v1/assinaturas/:id?incluirEventos=1
em uma única chamada se preferir buscar tudo junto.
/v1/assinaturas/:id/documento
baixar PDF
Por padrão devolve o PDF como stream binário
(Content-Type: application/pdf) — pode ser usado direto em
<iframe src>, <a download> ou range requests.
Query params
| Param | Valor |
|---|---|
original | 1 — devolve o PDF antes da estampa (em vez do assinado) |
formato | base64 — devolve JSON { pdfBase64 } (formato legado pra compat) |
Headers de resposta (binário)
HTTP/2 200
Content-Type: application/pdf
Content-Disposition: inline; filename="Contrato - ASSINADO.pdf"
Cache-Control: private, max-age=300
Content-Length: 158234
<binário do PDF>
Sem assinatura concluída → 409. Use ?original=1 pra baixar antes de assinar.
/v1/assinaturas/:id/documento/url
signed URL
Devolve URL assinada temporária do PDF no Cloud Storage. O client pode usar pra download direto (sem proxy via Rubriq), range requests nativas e UX mais leve.
Query params
| Param | Valor |
|---|---|
original | 1 — URL do PDF original (em vez do assinado) |
ttl | Tempo de validade da URL em segundos. Default 300, mínimo 60, máximo 3600. |
Resposta
{
"ok": true,
"data": {
"pdfUrl": "https://storage.googleapis.com/rubriq-saas.firebasestorage.app/organizations/.../assinado.pdf?X-Goog-Algorithm=...&X-Goog-Signature=...",
"expiresAt": "2026-05-23T18:45:00Z"
}
}
/v1/assinaturas/batch
N documentos
Cria várias assinaturas de uma vez. Máximo 100 itens por requisição.
{
"items": [
{
"documentoNome": "Contrato A",
"documentoBase64": "data:application/pdf;base64,...",
"templateId": "contrato",
"signatarios": [ { "nome": "Maria", ... } ]
}
],
"signatariosPadrao": [ { "nome": "Maria", ... } ]
}
signatariosPadrao é usado quando o item não traz signatarios.
Resposta
{
"ok": true,
"data": {
"total": 50,
"criados": 48,
"resultados": [
{ "ok": true, "id": "...", "documentoNome": "..." },
{ "ok": false, "error": "...", "documentoNome": "..." }
]
}
}
/v1/assinaturas/split-enviar
holerites / folha
Recebe 1 PDF com N páginas + lista de N signatários alinhada por ordem de página. Gera N assinaturas, uma com cada página.
{
"documentoBase64": "data:application/pdf;base64,...",
"nomePadrao": "Holerite Out/2026",
"signatarios": [
{ "nome": "André", "cpf": "...", "whatsapp": "...", "email": "...", "role": "FUNCIONARIO" }
],
"templateId": "holerite-padrao"
}
Ciclo de vida
| Método | Endpoint | Efeito |
|---|---|---|
| DELETE | /v1/assinaturas/:id | Cancela. Manda e-mail de cancelamento pros pendentes. |
| PATCH | /v1/assinaturas/:id/pasta | { "pastaId": "id-ou-null" } |
| PATCH | /v1/assinaturas/:id/tags | { "tags": ["..."] } |
| PATCH | /v1/assinaturas/:id/arquivar | { "arquivar": true|false } |
| POST | /v1/assinaturas/:id/excluir | Move pra lixeira (soft-delete). |
| POST | /v1/assinaturas/:id/restaurar | Restaura da lixeira. |
| POST | /v1/assinaturas/:id/expurgar | Expurgo definitivo (LGPD). Apaga PDFs e doc. Mantém só auditoria. Irreversível. |
Por signatário
/v1/assinaturas/:id/signatarios/:idx/reenviar-email
Reenvia o e-mail de convite ao signatário pendente.
/v1/assinaturas/:id/signatarios/:idx/assinar
assinar como admin
Assinatura server-side. Pra integrações que coletam o rabisco no próprio sistema externo.
Atenção: envie ip e userAgent do navegador do signatário no body — sem eles, o carimbo de auditoria registra só o IP do seu servidor (que chamou a API), não o IP probatório do cliente final.
{
"rabiscoBase64": "data:image/png;base64,iVBORw0KGgo...",
"ip": "200.207.10.42",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ..."
}
/v1/assinaturas/detectar-template
Tenta achar template pelo nome do arquivo. Não usa IA — sem custo de cota.
{ "documentoNome": "Contrato Cliente X v3.pdf" }
/v1/assinaturas/analisar-upload
consome IA
IA lê o PDF e devolve: nome sugerido, problemas de ortografia, qual template casa.
{ "documentoBase64": "data:application/pdf;base64,..." }
/v1/assinaturas/sugerir-nome-doc
consome IA
IA propõe nome a partir do conteúdo do PDF.
/v1/assinaturas/holerites-automatch
consome IA
IA lê o CPF de cada página do PDF e devolve pareamento com contatos cadastrados. Atalho perfeito antes de chamar split-enviar.
/v1/assinaturas/:id/analisar
consome IA
Análise jurídica do documento: resumo, pontos-chave, datas, riscos.
Listar / detalhar
- GET
/v1/templates— lista resumida. - GET
/v1/templates/uso—{ usado, limite, plano }. - GET
/v1/templates/:id— detalhe com posições.
Criar / atualizar
- POST
/v1/templates - PUT
/v1/templates/:id - DELETE
/v1/templates/:id
Body
{
"templateId": "holerite",
"nomeTemplate": "Holerite Mensal",
"totalPaginas": 1,
"palavrasChave": ["holerite", "salário"],
"posicoes": [
{
"pagina": 1,
"x": 50, "y": 90,
"tipo": "assinatura",
"signatarioRole": "FUNCIONARIO"
}
]
}
/v1/templates/sugerir
consome IA
IA lê um PDF modelo e propõe { nome, identificador, palavrasChave[], papeis[] }. Bom pra acelerar criação manual.
Pastas
| Método | Endpoint | Body |
|---|---|---|
| GET | /v1/pastas | — |
| POST | /v1/pastas | { nome, cor? } |
| PATCH | /v1/pastas/:id | { nome?, cor? } |
| DELETE | /v1/pastas/:id | — |
Contatos
| Método | Endpoint | Notas |
|---|---|---|
| GET | /v1/contatos?q=… | Busca opcional. |
| POST | /v1/contatos | { nome, email?, telefone?, cpf?, role? } |
| PATCH | /v1/contatos/:id | — |
| DELETE | /v1/contatos/:id | — |
| POST | /v1/contatos/importar | { contatos: [ … ] } — bulk insert. |
/v1/conta/uso
Retorna o uso atual da sua organização: plano, cota de assinaturas, créditos, cota de IA.
{
"ok": true,
"data": {
"plano": "business",
"assinaturas": { "usado": 142, "limite": null },
"creditos": 0,
"ia": { "ilimitado": true, "limite": null, "usado": 87, "restante": null },
"periodoStart": "2026-05-01T00:00:00Z",
"periodoFimEstimado": "2026-06-01T00:00:00Z"
}
}
Configuração
Webhooks notificam seu sistema quando algo acontece (assinatura criada, concluída, cancelada). É o caminho recomendado pra integração assíncrona — evita polling.
| Método | Endpoint | Notas |
|---|---|---|
| GET | /v1/webhooks/eventos | Catálogo de eventos disponíveis. |
| GET | /v1/webhooks | Lista endpoints configurados na org. |
| POST | /v1/webhooks | Cria um endpoint. Retorna secret uma vez só — guarde. |
| PATCH | /v1/webhooks/:id | { url?, eventos?, ativo? } |
| DELETE | /v1/webhooks/:id | — |
| GET | /v1/webhooks/entregas?limit=50 | Log de entregas (status, retries). |
Eventos disponíveis
| Evento | Quando |
|---|---|
assinatura.criada | Nova assinatura criada. |
assinatura.concluida | Todos os signatários assinaram. |
assinatura.cancelada | Assinatura cancelada (admin ou expiração). |
Payload
Rubriq faz POST application/json pro seu endpoint:
POST /seu-endpoint HTTP/1.1
Content-Type: application/json
X-Rubriq-Event: assinatura.concluida
X-Rubriq-Delivery: 8e6a2bb0-9e1b-4cf9-a4f7-23d0aabd55c1
X-Rubriq-Signature: sha256=ff29dfd84ca10b29c3d8c35ea94eb3ba…
{
"evento": "assinatura.concluida",
"em": "2026-05-23T19:42:11Z",
"dados": {
"id": "abc123",
"documentoNome": "Contrato — Cliente X",
"hashFinal": "ff29dfd84ca10b29c3d8c35ea94eb3ba…",
"totalSignatarios": 1
}
}
Validar a assinatura HMAC
X-Rubriq-Signature é HMAC-SHA256 do corpo bruto
(antes de qualquer JSON.parse) usando o secret
retornado quando você criou o webhook.
const crypto = require('crypto');
function validarWebhook(rawBody, headerSignature, secret) {
const esperado = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
// crypto.timingSafeEqual previne timing attacks
return crypto.timingSafeEqual(
Buffer.from(headerSignature),
Buffer.from(esperado),
);
}
// Express
app.post('/webhook-rubriq', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['x-rubriq-signature'];
if (!validarWebhook(req.body, sig, process.env.RUBRIQ_WEBHOOK_SECRET)) {
return res.status(401).end();
}
const evento = JSON.parse(req.body.toString());
// ... processar evento
res.status(200).end();
});
Retry & entregas
- 3 tentativas in-process com back-off 0s / 2s / 5s.
- Pare confirmando com HTTP 2xx.
- Em qualquer outro status (ou timeout 10s), tentamos de novo.
- Após 3 falhas, o evento vai pro log de entregas com status
failed— consultável em/v1/webhooks/entregas. - Idempotência: garanta no seu lado processar duas vezes o mesmo
X-Rubriq-Deliverysem efeito colateral.
/assinaturas/verificar/:id
Qualquer um pode confirmar que um documento foi assinado no Rubriq batendo nessa URL com o ID — sem API key. Retorna metadados públicos + hash (não expõe dados pessoais completos).
Pra validação criptográfica oficial pela ITI (selo "Assinatura Eletrônica Qualificada"), envie o PDF assinado em validar.iti.gov.br.
Códigos de erro úteis
code | Significa |
|---|---|
api_key_missing | Header de auth ausente. |
api_key_invalid | Key inválida ou revogada. |
org_suspended | Conta suspensa. |
feature_requires_upgrade | Plano não cobre. Campo feature diz qual. |
ia_quota_exceeded | Cota mensal de IA esgotada. |
quota_exceeded | Cota mensal de assinaturas esgotada. |
template_limit | Limite de templates do plano atingido. |
signup_closed | Novos cadastros desabilitados (raramente apareceria via API). |
Exemplo end-to-end
Fluxo completo em Node.js: cria assinatura, recebe webhook, baixa PDF assinado.
// 1) CRIAR ASSINATURA
import fs from 'node:fs';
const pdf = fs.readFileSync('./contrato.pdf').toString('base64');
const criada = await fetch('https://api.rubriq.com.br/v1/assinaturas', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.RBQ_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
documentoNome: 'Contrato — Cliente X',
documentoBase64: `data:application/pdf;base64,${pdf}`,
templateId: 'contrato-cliente',
signatarios: [
{
nome: 'Maria Souza',
cpf: '12345678909',
whatsapp: '+5511999990001',
email: 'maria@x.com',
role: 'CONTRATANTE',
},
],
tags: ['vendas'],
}),
}).then((r) => r.json());
console.log('Criada:', criada.data.id);
// 2) AGUARDAR WEBHOOK 'assinatura.concluida' (configurado previamente)
// → seu endpoint recebe POST com { dados: { id, ... } }
// 3) BAIXAR PDF FINAL (no handler do webhook)
const detalhe = await fetch(
`https://api.rubriq.com.br/v1/assinaturas/${id}/documento`,
{ headers: { Authorization: `Bearer ${process.env.RBQ_KEY}` } },
).then((r) => r.json());
const buffer = Buffer.from(
detalhe.data.pdfBase64.replace(/^data:application\/pdf;base64,/, ''),
'base64',
);
fs.writeFileSync('./contrato-assinado.pdf', buffer);
Changelog
| Data | Mudança |
|---|---|
| 2026-05-23 |
GET /v1/assinaturas/:id agora aceita ?incluirEventos=1
e inclui campos extras nos signatários (ip, userAgent, assinaturaTipo, icpBrasil).
Novo endpoint dedicado GET /v1/assinaturas/:id/eventos com trilha forense.
|
| 2026-05-23 |
GET /v1/assinaturas/:id/documento agora retorna PDF
binário por padrão (Content-Type: application/pdf).
Use ?formato=base64 pra manter o formato legado. Novo
GET /v1/assinaturas/:id/documento/url devolve signed URL
temporária pra download direto do Storage.
|
| 2026-05-21 | Suporte a certificado ICP-Brasil A1 (assinatura qualificada) via Web Crypto no signer. Validável no gov.br. |
| 2026-05-21 | metodoAutenticacao no POST /v1/assinaturas: o criador pode exigir ICP-Brasil. |
| 2026-05-20 | CPF do signatário virou opcional. Email OU WhatsApp obrigatório. |
| 2026-05-15 | Webhooks GA: assinatura.criada/concluida/cancelada com HMAC-SHA256. |
| 2026-05-01 | Endpoints de holerites com auto-match por CPF via IA. |