Guias de Desenvolvimento

Signing Sessions

Guias dos SDKs

Referência de Erros

SignDocs Brasil External API

Todas as respostas de erro da API SignDocs Brasil seguem o formato RFC 7807 Problem Details (Content-Type: application/problem+json).

Formato da Resposta de Erro

{
  "type": "https://api.signdocs.com.br/errors/<tipo-do-erro>",
  "title": "<Texto do Status HTTP>",
  "status": 400,
  "detail": "<explicação legível do erro>",
  "instance": "/v1/transactions/abc-123"
}
Campo Tipo Descrição
type string URI que identifica o tipo do erro. Estável entre versões da API.
title string Texto curto do status HTTP (ex.: "Bad Request").
status number Código de status HTTP.
detail string Explicação legível sobre o que deu errado nesta requisição.
instance string Caminho da requisição que gerou o erro.

Campos adicionais podem estar presentes dependendo do tipo de erro (ex.: issues para erros de validação de certificado).


400 Bad Request

Tipo: https://api.signdocs.com.br/errors/bad-request

Quando ocorre

A requisição contém dados inválidos, campos obrigatórios ausentes ou valores em formato incorreto. Exemplos comuns:

Exemplo de resposta

{
  "type": "https://api.signdocs.com.br/errors/bad-request",
  "title": "Bad Request",
  "status": 400,
  "detail": "signer.cpf must be exactly 11 digits",
  "instance": "/v1/transactions"
}

Como resolver


401 Unauthorized

Tipo: https://api.signdocs.com.br/errors/unauthorized

Quando ocorre

A requisição não possui credenciais válidas de autenticação. Causas comuns:

Exemplo de resposta

{
  "type": "https://api.signdocs.com.br/errors/unauthorized",
  "title": "Unauthorized",
  "status": 401,
  "detail": "Invalid or missing authentication",
  "instance": "/v1/transactions"
}

Como resolver


403 Forbidden

Tipo: https://api.signdocs.com.br/errors/forbidden

Quando ocorre

A autenticação foi aceita, mas o usuário/credencial não tem permissão para a operação. Causas comuns:

Exemplo de resposta

{
  "type": "https://api.signdocs.com.br/errors/forbidden",
  "title": "Forbidden",
  "status": 403,
  "detail": "Insufficient permissions",
  "instance": "/v1/transactions/tx_abc123"
}

Como resolver


404 Not Found

Tipo: https://api.signdocs.com.br/errors/not-found

Quando ocorre

O recurso solicitado não existe ou não pertence ao tenant autenticado. Causas comuns:

Exemplo de resposta

{
  "type": "https://api.signdocs.com.br/errors/not-found",
  "title": "Not Found",
  "status": 404,
  "detail": "Transaction not found",
  "instance": "/v1/transactions/tx_nao_existe"
}

Como resolver


409 Conflict

Tipo: https://api.signdocs.com.br/errors/conflict

Quando ocorre

A requisição conflita com o estado atual do recurso. Esta é a classe de erro mais comum em operações de fluxo da transação. Cenários típicos:

Conflitos de estado de transação:

Conflitos de etapas (steps):

Conflitos de documento:

Conflitos de idempotência:

Exemplo de resposta

{
  "type": "https://api.signdocs.com.br/errors/conflict",
  "title": "Conflict",
  "status": 409,
  "detail": "Transaction cannot be finalized in status: CREATED",
  "instance": "/v1/transactions/tx_abc123/finalize"
}

Como resolver


422 Unprocessable Entity

Tipo: https://api.signdocs.com.br/errors/unprocessable-entity

Quando ocorre

A requisição é sintaticamente válida, mas não pode ser processada por regras de negócio ou pré-condições não atendidas. Causas comuns:

Documentos e finalização:

Certificados digitais:

Configuração do tenant:

OTP e biometria:

Validação de qualidade do PDF:

Feature flags não habilitadas:

Geolocalização:

Exemplo de resposta

{
  "type": "https://api.signdocs.com.br/errors/unprocessable-entity",
  "title": "Unprocessable Entity",
  "status": 422,
  "detail": "Certificate validation failed",
  "instance": "/v1/signing/prepare",
  "issues": [
    "Certificate CN does not match signer name",
    "Certificate expired on 2025-01-15T00:00:00Z"
  ]
}

Como resolver


429 Too Many Requests

Tipo: https://api.signdocs.com.br/errors/too-many-requests

Quando ocorre

O tenant excedeu os limites de taxa da API. A SignDocs Brasil aplica dois tipos de limites:

Headers incluídos

Header Descrição
Retry-After Segundos até o limite ser resetado.
RateLimit-Limit Limite total configurado para a janela.
RateLimit-Remaining Requisições restantes na janela atual.
RateLimit-Reset Segundos até o reset da janela atual.

Exemplo de resposta

{
  "type": "https://api.signdocs.com.br/errors/too-many-requests",
  "title": "Too Many Requests",
  "status": 429,
  "detail": "Daily transaction quota exceeded (100/100)",
  "instance": "/v1/transactions"
}
Retry-After: 3600
RateLimit-Limit: 100
RateLimit-Remaining: 0
RateLimit-Reset: 3600

Como resolver


500 Internal Server Error

Tipo: https://api.signdocs.com.br/errors/internal-server-error

Quando ocorre

Um erro inesperado ocorreu no servidor. Por segurança, detalhes internos nunca são expostos ao cliente. Causas possíveis (internas):

Exemplo de resposta

{
  "type": "https://api.signdocs.com.br/errors/internal-server-error",
  "title": "Internal Server Error",
  "status": 500,
  "instance": "/v1/transactions"
}

Note que o campo detail está ausente intencionalmente para não expor informações internas.

Como resolver


503 Service Unavailable

Tipo: https://api.signdocs.com.br/errors/service-unavailable

Quando ocorre

Um serviço downstream está temporariamente indisponível. A API mapeia automaticamente erros transientes da AWS para 503:

Headers incluídos

Header Descrição
Retry-After Segundos recomendados para aguardar antes de retry.

Exemplo de resposta

{
  "type": "https://api.signdocs.com.br/errors/service-unavailable",
  "title": "Service Unavailable",
  "status": 503,
  "detail": "A downstream service is temporarily unavailable. Please retry.",
  "instance": "/v1/transactions/tx_abc123/finalize"
}
Retry-After: 5

Como resolver


Headers de Segurança

Todas as respostas da API (inclusive erros) incluem os seguintes headers de segurança:

Header Valor
Strict-Transport-Security max-age=31536000; includeSubDomains
X-Content-Type-Options nosniff
X-Frame-Options DENY
Referrer-Policy strict-origin-when-cross-origin
Cache-Control no-store
API-Version 1.0

Boas Práticas para Tratamento de Erros

1. Sempre verifique o campo status

Use o código de status HTTP (campo status) para determinar a categoria do erro. O campo detail fornece contexto legível mas pode mudar entre versões.

2. Use o campo type para tratamento programático

O campo type é estável e pode ser usado em lógica condicional:

const error = await response.json();

switch (error.type) {
  case 'https://api.signdocs.com.br/errors/too-many-requests':
    await aguardarRetryAfter(response.headers.get('Retry-After'));
    break;
  case 'https://api.signdocs.com.br/errors/conflict':
    await recarregarEstadoDoRecurso();
    break;
  case 'https://api.signdocs.com.br/errors/unauthorized':
    await renovarToken();
    break;
}

3. Classifique erros como retentáveis ou não

Status Retentável? Ação recomendada
400 Não Corrigir a requisição.
401 Sim* Renovar token e tentar novamente.
403 Não Verificar permissões/escopos.
404 Não Verificar ID do recurso.
409 Não** Consultar estado atual e ajustar fluxo.
422 Não Verificar pré-condições do negócio.
429 Sim Aguardar Retry-After + backoff.
500 Sim Retry com backoff.
503 Sim Aguardar Retry-After + backoff.

* Renovar o token antes de retentar.
** Exceto TransactionConflictException mapeado para 503, que é retentável.


Estratégia de Retry com Exponential Backoff

Para erros retentáveis (429, 500, 503), implemente a seguinte estratégia:

import time
import random

def request_com_retry(fazer_request, max_tentativas=5):
    for tentativa in range(max_tentativas):
        response = fazer_request()

        if response.status_code < 400:
            return response

        if response.status_code in (429, 503):
            retry_after = int(response.headers.get('Retry-After', 0))
            espera = max(retry_after, (2 ** tentativa) + random.uniform(0, 1))
            time.sleep(espera)
            continue

        if response.status_code >= 500:
            espera = (2 ** tentativa) + random.uniform(0, 1)
            time.sleep(espera)
            continue

        # Erros 4xx (exceto 429) não são retentáveis
        raise ApiError(response)

    raise MaxRetryError(f"Falhou após {max_tentativas} tentativas")

Regras da estratégia:

  1. Base: 2^tentativa segundos (1s, 2s, 4s, 8s, 16s).
  2. Jitter: adicione um valor aleatório entre 0 e 1 segundo para evitar thundering herd.
  3. Retry-After: quando presente, use o maior valor entre o header e o cálculo de backoff.
  4. Máximo de tentativas: 5 tentativas é um bom padrão. Após isso, registre o erro e alerte o operador.
  5. Timeout total: considere um timeout total de 60 segundos para evitar que o processo fique preso indefinidamente.

Como Reportar Problemas ao Suporte SignDocs Brasil

Ao entrar em contato com o suporte, inclua as seguintes informações para agilizar a resolução:

  1. Código de status HTTP e corpo completo da resposta de erro (JSON).
  2. Campo instance da resposta -- identifica o endpoint e o recurso.
  3. Horário exato da requisição (UTC, formato ISO 8601).
  4. client_id utilizado (nunca envie o client_secret).
  5. Ambiente: sandbox (api-hml.signdocs.com.br) ou produção (api.signdocs.com.br).
  6. ID da requisição se disponível nos headers de resposta.
  7. Passos para reproduzir o problema, incluindo o corpo da requisição (remova dados sensíveis como CPF, documentos e tokens).

Canal de suporte: suporte@signdocs.com.br

Severidades: