Documentação da API
Integra ID
Integre assinaturas digitais e certificações de autenticidade diretamente no seu sistema. Gerencie documentos, envie solicitações de assinatura e receba notificações via webhook.
01 Autenticação
Todas as requisições devem incluir o header X-Api-Key com sua chave de API.
POST /v1/documents X-Api-Key: iid_live_a1b2c3d4e5f6... Content-Type: application/json
| Prefixo | Ambiente |
|---|---|
| iid_live_ | Produção |
| iid_test_ | Homologação |
02 Formato de resposta
{
"document_id": "uuid",
"name": "contrato.pdf",
...
}{
"error": {
"code": "document_not_found",
"message": "Documento não encontrado.",
"request_id": "uuid",
"details": null
}
}Todo response inclui o header X-Request-Id com o UUID da requisição para rastreabilidade.
03 Escopos
Cada API Key possui um conjunto de escopos que limitam as operações permitidas:
| Escopo | Operações permitidas |
|---|---|
| documents:read | Listar e consultar documentos, obter URL de download |
| documents:write | Upload de documentos (simples e em dois passos) |
| certifications:read | Consultar certificações de integridade |
| certifications:write | Enviar arquivos para certificação (Hashing e ICP-Brasil placeholder) |
| sign:read | Consultar status de assinaturas |
| sign:cancel | Cancelar solicitações de assinatura pendentes |
| sign:send | Enviar e reenviar links de assinatura (/signatures/send, /signatures/:id/resend) |
04 Rate Limiting
Limites por API Key, por endpoint, por janela de 1 hora. Ao exceder, a API retorna HTTP 429 com o código rate_limit_exceeded.
05 Idempotência
Para operações POST, envie o header Idempotency-Key para evitar duplicatas em caso de retry.
Idempotency-Key: <uuid-v4-gerado-pelo-cliente>
| Regra | Detalhe |
|---|---|
| Unicidade | A chave deve ser única por operação e gerada pelo seu sistema |
| Cache | Responses são cacheados por 24 horas |
| Conflito | Mesma chave com payload diferente retorna HTTP 409 (idempotency_key_conflict) |
| Replay | Responses repetidos incluem X-Idempotent-Replayed: true |
06 Endpoints
Upload de documento em Base64. Recomendado para arquivos até ~4.5 MB (o payload Base64 equivalente é ~6 MB, limite do corpo da Edge Function). Para arquivos maiores, utilize obrigatoriamente o fluxo de dois passos com /upload-url + /complete-upload, que não possui limite prático de tamanho.
{
"filename": "contrato-joao.pdf",
"file_base64": "<conteúdo do arquivo em Base64>",
"document_type": "contract",
"external_id": "ERP-00123",
"external_source": "totvs",
"metadata": {
"cliente": "João Silva",
"contrato_numero": "2024-001"
}
}| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| filename | string | ✅ | Nome do arquivo (incluindo extensão) |
| file_base64 | string | ✅ | Conteúdo do arquivo codificado em Base64 |
| document_type | string | — | document, contract ou others. Padrão: document |
| external_id | string | — | ID do documento no seu sistema (único por tenant) |
| external_source | string | — | Identificador do sistema de origem (ex: "totvs") |
| metadata | object | — | Campos livres para uso interno |
{
"document_id": "3f7a8b2c-...",
"external_id": "ERP-00123",
"name": "contrato-joao.pdf",
"document_type": "contract",
"status": "uploaded",
"signing_status": "draft",
"created_at": "2024-01-15T10:30:00Z"
}| Código | HTTP | Descrição |
|---|---|---|
| invalid_payload | 422 | Campo obrigatório ausente ou file_base64 inválido |
| duplicate_external_id | 409 | external_id já existe neste tenant |
| storage_error | 500 | Falha ao salvar no storage |
Passo 1 do upload em dois passos. Gera uma URL pré-assinada para upload direto ao storage (arquivos grandes).
{
"filename": "contrato-grande.pdf",
"content_type": "application/pdf",
"document_type": "contract",
"external_id": "ERP-00456"
}| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| filename | string | ✅ | Nome do arquivo |
| content_type | string | — | MIME type. Padrão: application/pdf |
| document_type | string | — | document, contract ou others |
| external_id | string | — | ID no sistema externo |
{
"upload_url": "https://storage.supabase.co/...",
"storage_path": "api/tenant-id/uuid-contrato-grande.pdf",
"token": "eyJ...",
"expires_in": 3600,
"next_step": "POST /v1/documents/complete-upload",
"hint": {
"storage_path": "api/tenant-id/uuid-contrato-grande.pdf",
"filename": "contrato-grande.pdf",
"document_type": "contract",
"external_id": "ERP-00456"
}
}upload_url e faça PUT diretamente nessa URL com o conteúdo do arquivo. 2) Use storage_path e token para chamar /complete-upload.Passo 2: Registra o documento no banco após o upload direto ao storage ter sido concluído.
{
"storage_path": "api/tenant-id/uuid-contrato-grande.pdf",
"filename": "contrato-grande.pdf",
"document_type": "contract",
"external_id": "ERP-00456",
"external_source": "sap",
"metadata": {}
}| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| storage_path | string | ✅ | Retornado por /upload-url |
| filename | string | ✅ | Nome do arquivo |
| document_type | string | — | Tipo do documento |
| external_id | string | — | ID no sistema externo |
| external_source | string | — | Sistema de origem |
| metadata | object | — | Campos livres |
Mesmo formato do POST /v1/documents.
Lista documentos do tenant com paginação e filtros.
| Parâmetro | Tipo | Descrição |
|---|---|---|
| page | integer | Página atual. Padrão: 1 |
| per_page | integer | Itens por página (máx. 100). Padrão: 20 |
| status | string | draft | pending | partially_signed | fully_signed | expired |
| document_type | string | document | contract | others |
| external_id | string | Filtrar por ID externo exato |
| created_from | ISO 8601 | Documentos criados após esta data |
| created_to | ISO 8601 | Documentos criados antes desta data |
GET /v1/documents?status=pending&page=1&per_page=20&created_from=2024-01-01T00:00:00Z
{
"data": [
{
"id": "3f7a8b2c-...",
"name": "contrato-joao.pdf",
"document_type": "contract",
"signing_status": "pending",
"total_signers": 2,
"signed_count": 1,
"external_id": "ERP-00123",
"external_source": "totvs",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T11:00:00Z"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 47,
"total_pages": 3
}
}Retorna os detalhes completos de um documento, incluindo o status de cada signatário.
{
"document_id": "3f7a8b2c-...",
"external_id": "ERP-00123",
"external_source": "totvs",
"name": "contrato-joao.pdf",
"document_type": "contract",
"signing_status": "partially_signed",
"total_signers": 2,
"signed_count": 1,
"metadata": {
"cliente": "João Silva"
},
"signers": [
{
"sign_request_id": "uuid-da-solicitacao",
"name": "João Silva",
"email": "joao@empresa.com",
"status": "signed",
"auth_methods": ["email"],
"require_selfie": false,
"sent_at": "2024-01-15T10:31:00Z",
"signed_at": "2024-01-15T14:20:00Z"
},
{
"sign_request_id": "uuid-da-solicitacao-2",
"name": "Maria Santos",
"email": "maria@empresa.com",
"status": "pending",
"auth_methods": ["email", "whatsapp"],
"require_selfie": true,
"sent_at": "2024-01-15T10:31:00Z",
"signed_at": null
}
],
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T14:20:00Z"
}signing_status| Valor | Descrição |
|---|---|
| draft | Documento enviado, sem signatários configurados |
| pending | Aguardando assinaturas |
| partially_signed | Ao menos um signatário assinou |
| fully_signed | Todos os signatários assinaram |
| expired | Prazo expirado |
status (signatário)| Valor | Descrição |
|---|---|
| pending | Aguardando assinatura |
| signed | Assinou com sucesso |
| cancelled | Solicitação cancelada |
Gera uma URL pré-assinada (válida por 1 hora) para download do PDF assinado.
{
"document_id": "3f7a8b2c-...",
"name": "contrato-joao.pdf",
"download_url": "https://storage.supabase.co/...?token=...",
"expires_in": 3600
}| Código | HTTP | Descrição |
|---|---|---|
| not_signed | 409 | Documento sem assinaturas concluídas |
| pdf_not_ready | 404 | PDF ainda está sendo gerado |
Envia links de assinatura para um ou mais destinatários. O sistema notifica por e-mail e, opcionalmente, por WhatsApp.
{
"document_id": "3f7a8b2c-...",
"recipients": [
{
"name": "João Silva",
"email": "joao@empresa.com",
"phone": "+5511999998888",
"auth_methods": ["email"],
"require_selfie": false,
"send_link_via_whatsapp": false
},
{
"name": "Maria Santos",
"email": "maria@empresa.com",
"phone": "+5511977776666",
"auth_methods": ["email", "whatsapp"],
"require_selfie": true,
"send_link_via_whatsapp": true
}
]
}| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| document_id | string | ✅ (ou external_id) | UUID do documento |
| external_id | string | ✅ (ou document_id) | ID externo do documento |
| recipients | array | ✅ | Lista de destinatários |
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| string | ✅ | E-mail do signatário | |
| name | string | — | Nome completo |
| phone | string | Cond. | E.164 (ex: +5511999998888). Obrigatório se auth inclui whatsapp |
| auth_methods | string[] | — | ["email"] ou ["email","whatsapp"]. Padrão: ["email"] |
| require_selfie | boolean | — | Exige selfie no momento da assinatura. Padrão: false |
| send_link_via_whatsapp | boolean | — | Envia link também via WhatsApp. Padrão: false |
{
"document_id": "3f7a8b2c-...",
"external_id": "ERP-00123",
"sign_request": {
"results": [
{
"email": "joao@empresa.com",
"success": true,
"signing_url": "https://integraid.com.br/assinar/uuid-do-token"
},
{
"email": "maria@empresa.com",
"success": false,
"error": "phone é obrigatório quando auth_methods inclui \"whatsapp\"."
}
]
}
}Cancela uma solicitação de assinatura pendente. Não é possível cancelar assinaturas já concluídas.
| Parâmetro | Descrição |
|---|---|
| id | UUID da solicitação de assinatura (sign_request_id) |
{
"reason": "Contrato substituído por versão atualizada"
}| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| reason | string | — | Motivo do cancelamento (registrado em auditoria) |
{
"sign_request_id": "uuid-da-solicitacao",
"status": "cancelled",
"reason": "Contrato substituído por versão atualizada"
}| Código | HTTP | Descrição |
|---|---|---|
| already_signed | 409 | Signatário já assinou — não é possível cancelar |
| already_cancelled | 409 | Já estava cancelada |
| not_found | 404 | Solicitação não encontrada neste tenant |
Reenvia a notificação de assinatura (e-mail e/ou WhatsApp) para uma solicitação pendente. Não cancela nem cria nova solicitação; apenas dispara os lembretes usando o mesmo link.
| Parâmetro | Descrição |
|---|---|
| id | UUID da solicitação de assinatura (sign_request_id) |
{
"sign_request_id": "uuid-da-solicitacao",
"status": "notifications_sent",
"email_sent": true,
"wa_sent": true
}email_sent e wa_sent indicam quais notificações o backend tentou disparar com base no que havia salvo no momento do envio send original.| Código | HTTP | Descrição |
|---|---|---|
| already_signed | 409 | Signatário já assinou |
| already_cancelled | 409 | Solicitação cancelada |
| not_found | 404 | Solicitação não encontrada |
| notification_failed | 500 | Falha na comunicação com os webhooks de notificação |
Envia um documento em Base64 para certificação de autenticidade. Recomendado para arquivos até ~4.5 MB (payload Base64 equivalente de ~6 MB). Para arquivos maiores, utilize o fluxo de dois passos: /certifications/upload-url + /certifications/certify. O sistema insere no PDF uma página com hashes criptográficos e QR code de verificação.
{
"document_title": "Contrato de NDA.pdf",
"description": "Versão final para homologação",
"issuer_name": "Empresa XYZ",
"file_base64": "<conteúdo base64 do PDF>",
"custom_fields": {
"Contrato nº": "A192B4",
"Setor": "Jurídico"
}
}| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| document_title | string | ✅ | Nome do documento |
| file_base64 | string | ✅ | Conteúdo do PDF em Base64 |
| description | string | — | Descrição do documento |
| issuer_name | string | — | Sobrescreve o nome do emissor (dono da API Key) |
| custom_fields | object | — | Campos personalizados exibidos no certificado |
{
"cert_id": "CERT-8HJ2MDQ1",
"document_title": "Contrato de NDA.pdf",
"original_hash": "a1b2c3...",
"certified_hash": "d4e5f6...",
"download_url": "https://api.integraid.com.br/... (expira em 1h)",
"expires_in": 3600
}Passo 1 para certificar arquivos pesados. Gera URL pré-assinada para upload direto ao Storage Provisório.
{
"upload_url": "https://storage.supabase.co/...",
"storage_path": "uploads/api_...",
"token": "eyJ...",
"next_step": "POST /v1/certifications/certify"
}Passo 2: Efetiva a certificação de um documento grande já enviado para o storage.
{
"storage_path": "uploads/api_...",
"document_title": "Relatório Volumétrico.pdf",
"description": "Anexo I",
"custom_fields": {
"Ano": "2024"
}
}| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| storage_path | string | ✅ | Retornado por /certifications/upload-url |
| document_title | string | ✅ | Nome do documento |
| description | string | — | Descrição do documento |
| custom_fields | object | — | Campos personalizados |
Mesmo formato do POST /v1/certifications (com os hashes e download_url).
Lista documentos certificados. Retorna apenas metadados — guarde o PDF original durante a geração.
Retorna os detalhes de uma certificação específica por ID.
07 Webhooks de saída
Registre uma URL no painel (Configurações → Webhooks) para receber notificações em tempo real.
{
"event": "signature.completed",
"tenant_id": "uuid-do-tenant",
"occurred_at": "2024-01-15T14:20:00Z",
"data": {
"document_id": "3f7a8b2c-...",
"document_name": "contrato-joao.pdf",
"external_id": "ERP-00123",
"sign_request_id": "uuid",
"signer": {
"email": "joao@empresa.com",
"name": "João Silva"
},
"signed_at": "2024-01-15T14:20:00Z",
"document_hash": "sha256-do-pdf"
}
}Se você configurou um secret ao cadastrar o webhook, cada requisição inclui os headers de segurança:
X-Integra-Signature: sha256=<hmac-hex> X-Integra-Timestamp: <unix-ms> X-Integra-Event: signature.completed X-Integra-Delivery: <uuid-da-entrega>
import hmac, hashlib
def verify_signature(secret, timestamp, body, signature_header):
message = f"{timestamp}.{body}"
expected = hmac.new(secret.encode(), message.encode(), hashlib.sha256).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature_header)async function verifySignature(secret, timestamp, body, signatureHeader) {
const encoder = new TextEncoder()
const key = await crypto.subtle.importKey(
'raw', encoder.encode(secret),
{ name: 'HMAC', hash: 'SHA-256' }, false, ['sign']
)
const sig = await crypto.subtle.sign('HMAC', key, encoder.encode(`${timestamp}.${body}`))
const hex = Array.from(new Uint8Array(sig)).map(b => b.toString(16).padStart(2, '0')).join('')
return signatureHeader === `sha256=${hex}`
}| Propriedade | Valor |
|---|---|
| Timeout | 10 segundos por tentativa |
| Política | Best-effort (sem reenvio automático) |
| Resposta esperada | Qualquer HTTP 2xx confirma o recebimento |
| Log | Painel → Configurações → Webhooks → Log |
08 Códigos de erro
| Status | Significado |
|---|---|
| 200 | Sucesso |
| 201 | Criado com sucesso |
| 401 | Não autenticado (API Key inválida, expirada ou revogada) |
| 403 | Sem permissão (escopo insuficiente) |
| 404 | Recurso não encontrado |
| 409 | Conflito (duplicata, já assinado, já cancelado) |
| 422 | Payload inválido (campo obrigatório ausente ou malformado) |
| 429 | Rate limit excedido |
| 500 | Erro interno do servidor |
error.code)| Código | Descrição |
|---|---|
| missing_api_key | Header X-Api-Key não enviado |
| invalid_api_key | Chave com formato inválido ou não encontrada |
| revoked_api_key | Chave foi revogada |
| expired_api_key | Chave expirou |
| insufficient_scope | Escopo necessário não está na chave |
| rate_limit_exceeded | Limite de requisições excedido |
| idempotency_key_conflict | Idempotency-Key usada com payload diferente |
| invalid_payload | Campo obrigatório ausente ou inválido |
| document_not_found | Documento não existe ou pertence a outro tenant |
| duplicate_external_id | external_id já cadastrado |
| not_found | Recurso não encontrado |
| already_signed | Tentativa de cancelar assinatura já concluída |
| already_cancelled | Tentativa de cancelar o que já está cancelado |
| not_signed | Download solicitado antes de qualquer assinatura |
| pdf_not_ready | PDF assinado ainda sendo gerado |
| storage_error | Erro no Supabase Storage |
| database_error | Erro interno de banco de dados |
| notification_failed | Falha na comunicação com webhooks de notificação |
09 Exemplos
# 1. Upload do documento
curl -X POST https://api.integraid.com.br/functions/v1/public-api/v1/documents \
-H "X-Api-Key: iid_live_a1b2c3d4..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"filename": "contrato-2024-001.pdf",
"file_base64": "'$(base64 -i contrato.pdf)'",
"document_type": "contract",
"external_id": "ERP-2024-001",
"external_source": "totvs"
}'
# Resposta: { "document_id": "3f7a8b2c-...", ... }
# 2. Enviar para assinatura
curl -X POST https://api.integraid.com.br/functions/v1/public-api/v1/signatures/send \
-H "X-Api-Key: iid_live_a1b2c3d4..." \
-H "Content-Type: application/json" \
-d '{
"document_id": "3f7a8b2c-...",
"recipients": [
{
"name": "João Silva",
"email": "joao@empresa.com",
"auth_methods": ["email"]
}
]
}'
# 3. Consultar status
curl https://api.integraid.com.br/functions/v1/public-api/v1/documents/3f7a8b2c-... \
-H "X-Api-Key: iid_live_a1b2c3d4..."
# 4. Download após assinatura
curl https://api.integraid.com.br/functions/v1/public-api/v1/documents/3f7a8b2c-.../download \
-H "X-Api-Key: iid_live_a1b2c3d4..."# Passo 1: Solicitar URL pré-assinada
RESPONSE=$(curl -s -X POST https://api.integraid.com.br/functions/v1/public-api/v1/documents/upload-url \
-H "X-Api-Key: iid_live_a1b2c3d4..." \
-H "Content-Type: application/json" \
-d '{
"filename": "relatorio-grande.pdf",
"document_type": "document",
"external_id": "REL-2024-050"
}')
UPLOAD_URL=$(echo $RESPONSE | jq -r '.upload_url')
STORAGE_PATH=$(echo $RESPONSE | jq -r '.storage_path')
# Passo 2: Upload direto para o storage
curl -X PUT "$UPLOAD_URL" \
-H "Content-Type: application/pdf" \
--data-binary @relatorio-grande.pdf
# Passo 3: Registrar no banco
curl -X POST https://api.integraid.com.br/functions/v1/public-api/v1/documents/complete-upload \
-H "X-Api-Key: iid_live_a1b2c3d4..." \
-H "Content-Type: application/json" \
-d "{
\"storage_path\": \"$STORAGE_PATH\",
\"filename\": \"relatorio-grande.pdf\",
\"document_type\": \"document\",
\"external_id\": \"REL-2024-050\",
\"external_source\": \"sistema-bi\"
}"curl "https://api.integraid.com.br/functions/v1/public-api/v1/documents?status=pending&per_page=50" \ -H "X-Api-Key: iid_live_a1b2c3d4..."
curl -X POST https://api.integraid.com.br/functions/v1/public-api/v1/signatures/uuid-da-solicitacao/cancel \
-H "X-Api-Key: iid_live_a1b2c3d4..." \
-H "Content-Type: application/json" \
-d '{ "reason": "Erro no documento original" }'curl -X POST https://api.integraid.com.br/functions/v1/public-api/v1/signatures/uuid-da-solicitacao/resend \ -H "X-Api-Key: iid_live_a1b2c3d4..."