Primeira Chamada à API de Assinatura com cURL (REST puro)
Você não precisa de um SDK para colocar uma assinatura digital com validade jurídica no ar. A API SignDocs é REST puro sobre HTTPS com payloads JSON, o que significa que qualquer linguagem capaz de fazer uma requisição HTTP — Ruby, Elixir, Rust, Bash, PowerShell ou um simples cURL no terminal — consegue criar uma sessão de assinatura, enviar um documento e receber eventos de conclusão. Este guia mostra o fluxo completo, do token OAuth2 ao webhook validado, usando só cURL.
A proposta aqui é deliberadamente language-agnostic. Em vez de esconder o protocolo atrás de uma biblioteca, vamos expor cada requisição HTTP crua, com cabeçalhos, corpo e resposta reais. Depois que você entende a API neste nível, traduzir o fluxo para a sua linguagem é trivial — e você ganha a capacidade de depurar qualquer integração olhando diretamente para os bytes que trafegam.
Se você procura um caminho ainda mais alto-nível, temos SDKs oficiais e tutoriais dedicados — por exemplo, integração em Node.js e integração em Python. Mas se a sua stack não tem SDK oficial, ou se você quer entender a API por baixo dos panos, REST puro funciona em todo lugar. Este artigo é também um bom complemento ao guia conceitual de o que é uma API de assinatura digital.
Por que (e quando) usar REST puro em vez de um SDK
SDKs existem para economizar tempo: eles encapsulam autenticação, serialização JSON, retries e tipagem. A SignDocs mantém SDKs oficiais para TypeScript/Node, Python, Go, Java, PHP e C#/.NET. Para essas linguagens, usar o SDK é quase sempre a melhor escolha. Mas há cenários claros em que ir direto ao REST é o caminho certo:
- Linguagem sem SDK oficial: Ruby, Elixir, Rust, Kotlin nativo, Dart, Bash/shell scripts. O REST cobre 100% das funcionalidades, então você nunca fica preso por falta de biblioteca.
- Provas de conceito e exploração: uma chamada cURL no terminal é a forma mais rápida de validar credenciais e ver a forma exata de uma resposta.
- Depuração: quando algo falha através de um SDK, reproduzir a requisição em cURL isola se o problema é seu código ou a API.
- Ambientes restritos: funções serverless minimalistas, CI/CD pipelines, runners onde adicionar dependências é indesejável.
- Aprendizado: entender o protocolo cru torna você independente de qualquer SDK específico.
O que você vai precisar
- Um par de credenciais
client_id+client_secret(obtidas no painel — veja como obter sua API key). cURLinstalado (já vem na maioria dos sistemas Unix, macOS e Windows 10+).- Opcionalmente,
jqpara formatar e extrair campos do JSON de resposta. - Um PDF de teste para enviar à assinatura.
Vamos usar o ambiente de homologação ao longo do guia. O host base de HML é api-hml.signdocs.com.br (com hífen — atenção, não é api.hml.signdocs.com.br). Em produção, troque apenas o host base e as credenciais.
Passo 1 — Obter o token OAuth2 (client-credentials)
Toda chamada à API exige um token Bearer. A SignDocs usa o fluxo OAuth2 client-credentials, apropriado para integrações server-to-server: você troca seu client_id e client_secret por um access_token de vida curta. Para o detalhamento do JWT (assinado com ECDSA ES256, chaves em KMS), expiração (15 minutos) e rotação, veja o guia profundo de autenticação OAuth2 na API.
A requisição é um POST com corpo no formato application/x-www-form-urlencoded:
Resposta típica (HTTP 200):
O campo expires_in indica a validade em segundos (900 = 15 minutos). Para automatizar, capture o token em uma variável de shell. Com jq:
client_secret ou o access_token no front-end ou em repositórios. Trate-os como segredos de ambiente. Cacheie o token até perto de expires_in e renove proativamente; não solicite um token novo a cada requisição. Em produção, considere mTLS para clientes enterprise/regulados (BACEN/Open Finance), que adiciona autenticação mútua de certificado por cima do OAuth2.
Passo 2 — Criar a sessão de assinatura (POST /v1/signing-sessions)
A forma mais rápida de produzir uma assinatura é a Assinatura Expressa: uma única chamada a POST /v1/signing-sessions devolve uma sessão pronta com URL de checkout hospedado ou widget incorporável. (Para envelopes com múltiplos signatários, ordem de assinatura e ciclo de vida completo, veja o fluxo transacional da API.)
Repare em um detalhe importante do corpo JSON: você não envia as etapas — o policy.profile as determina. CLICK_PLUS_OTP, por exemplo, gera as etapas CLICK_ACCEPT, OTP_CHALLENGE e OTP_VERIFY; DIGITAL_CERTIFICATE exige certificado ICP-Brasil e gera a etapa DIGITAL_SIGN_A1. As etapas aparecem na resposta, já na ordem correta.
Resposta (HTTP 201 Created):
profile: em policy.profile use DIGITAL_CERTIFICATE. DIGITAL_SIGN_A1 é um tipo de passo (step.type), não um valor de profile — a API rejeita DIGITAL_SIGN_A1 como profile. Via API, a assinatura com certificado usa o A1 (em arquivo), em um protocolo de duas fases em que a chave privada nunca sai do lado do titular; para quem só possui token A3, o aplicativo SignDocs oferece o assinador desktop (Windows/macOS/Linux). A classe real do certificado fica registrada na evidência da assinatura.
Sobre a URL de compartilhamento e o clientSecret
O campo url sozinho não é o link de assinatura completo. Para o checkout hospedado, combine a url com o clientSecret como parâmetro de query ?cs= — esse é o link que o signatário abre. Para embutir a assinatura no seu front-end, o mesmo clientSecret alimenta o SDK oficial @signdocs-brasil/js, que abre o checkout como popup com callbacks de conclusão. Para o panorama do produto, veja a página da API de assinatura digital.
Passo 3 — Duas formas de enviar o PDF
No Passo 2 enviamos o documento inline em base64 (campo document.content), o caminho mais simples para arquivos de até 10 MB — o hash SHA-256 é calculado no servidor. Para arquivos maiores, ou quando você não quer trafegar o binário pelo seu backend, o fluxo transacional oferece o upload em duas etapas via URL pré-assinada, usando o transactionId retornado:
Um HTTP 200 (ou 204) no PUT confirma o envio ao storage; a confirmação fecha o ciclo e o hash é calculado no servidor. A URL pré-assinada tem vida curta — se expirar antes do PUT, basta solicitar outra com o mesmo presign: nada se perde.
owner.email da requisição é diferente do signer.email. Se forem iguais (ou se você omitir o owner), entregue o link você mesmo combinando url + ?cs= + clientSecret. Para reenviar o convite por e-mail, use POST /v1/signing-sessions/{sessionId}/resend-invite.
Passo 4 — Consultar o status da assinatura
Para acompanhar o progresso de forma síncrona, faça um GET no recurso da sessão. (Em produção, prefira webhooks ao invés de polling — mais sobre isso no próximo passo.)
Resposta (HTTP 200) com a assinatura concluída:
| Status | Significado | Próxima ação |
|---|---|---|
ACTIVE |
Sessão criada e pronta; o signatário pode assinar | Entregar o link (url?cs=...) ao signatário |
COMPLETED |
Assinatura concluída; evidências disponíveis | Baixar o .p7m via GET /v1/transactions/{id}/evidence |
CANCELLED |
Sessão cancelada (via POST .../cancel) |
Tratar no fluxo de negócio (renegociar/recriar) |
EXPIRED |
Janela de assinatura encerrou sem conclusão | Recriar a sessão se ainda for necessário |
FAILED |
Uma etapa obrigatória falhou (ex.: biometria reprovada) | Oferecer outro perfil ou tratar a exceção no seu fluxo |
O downloadUrl entrega o pacote de evidências em formato .p7m (PKCS#7/CMS), que serve como prova jurídica completa da assinatura — e a URL é temporária, então baixe e arquive. A finalização também devolve um evidenceId, que qualquer pessoa pode conferir de forma independente via GET /v1/verify/{evidenceId} (sem autenticação) ou no verificador público em verificador.signdocs.com.br. Para entender os padrões por trás dele, veja o glossário (PKCS#7/CMS) e o evidence pack .p7m como prova jurídica.
Passo 5 — Verificar a assinatura de um webhook (HMAC-SHA256)
Polling é útil para testes, mas em produção você quer receber webhooks: a API faz um POST HTTPS para o seu endpoint sempre que um evento ocorre (como SIGNING_SESSION.COMPLETED ou TRANSACTION.COMPLETED). Cada webhook traz uma assinatura HMAC-SHA256 no header, calculada sobre o corpo bruto da requisição usando um segredo compartilhado. Sua tarefa é recalcular o HMAC e comparar — isso garante que o evento veio mesmo da SignDocs e não de um atacante.
Primeiro, registre seu endpoint de webhook via REST:
A resposta inclui um secret — exibido uma única vez, no momento do registro. Guarde-o: é com ele que você valida cada webhook recebido. A verificação não depende de SDK — qualquer biblioteca de criptografia padrão calcula HMAC-SHA256. Mesmo a partir da linha de comando você pode reproduzir o cálculo com openssl para depurar:
No seu servidor, a lógica é a mesma em qualquer linguagem: pegue o corpo bruto (raw body, antes de qualquer parse de JSON), concatene com o timestamp do header, calcule o HMAC-SHA256 com o segredo e compare em modo timing-safe. Em Ruby, por exemplo, sem nenhum SDK:
Rack::Utils.secure_compare em Ruby, hmac.compare_digest em Python, crypto.timingSafeEqual em Node.js). Comparação simples com == é vulnerável a timing attacks. Use também o corpo bruto da requisição no cálculo — reserializar o JSON quase sempre muda os bytes e invalida o HMAC.
O modelo de eventos, idempotência e a estratégia de retry com backoff exponencial estão detalhados no guia de webhooks e eventos da API. A regra de ouro: responda 200 rápido e processe o evento de forma assíncrona em uma fila.
Homologação vs. produção: o que muda no cURL
Todo o fluxo acima rodou em homologação. A boa notícia: o código cURL é praticamente idêntico em produção. O que muda:
| Aspecto | Homologação (HML) | Produção |
|---|---|---|
| Host base | api-hml.signdocs.com.br (com hífen) |
api.signdocs.com.br |
| Credenciais | client_id/secret de teste | client_id/secret de produção |
| Persistência | TTL de 7 dias — entidades de teste são apagadas | Persistência durável de transações e evidências |
| Cobrança | Sem consumo do seu plano | Conta no plano contratado |
| Assinaturas | Válidas para teste de fluxo | Validade jurídica plena (ICP-Brasil) |
Recapitulando o fluxo completo em cURL
Os cinco passos, do zero a uma assinatura com evidência jurídica, em REST puro:
- Token:
POST /oauth2/tokencomgrant_type=client_credentials→ obtém o Bearer token (expira em 15 min). - Sessão:
POST /v1/signing-sessionscom finalidade, política, signatário e documento em base64 → devolvesessionId,transactionId,urleclientSecret. - Upload alternativo: para arquivos maiores,
presign→PUT→confirmna API transacional. - Status:
GET /v1/signing-sessions/{sessionId}(ou webhooks) → acompanha atéCOMPLETED; evidência viaGET /v1/transactions/{id}/evidence. - Webhook: recebe o
POSTde evento e valida o HMAC-SHA256 sobre{timestamp}.{raw_body}.
Esse mesmo contrato sustenta os SDKs oficiais. Quando você estiver pronto para uma camada mais ergonômica na sua linguagem — se ela tiver SDK — a transição é direta: o tutorial de Node.js e o de Python seguem exatamente esses cinco passos, só que com tipos e helpers. E para a visão completa do produto e dos endpoints, a página da API de assinatura digital é o ponto de partida.
Perguntas Frequentes
Preciso de um SDK para integrar a API de assinatura digital?
Não. A API SignDocs é REST puro sobre HTTPS com JSON, então qualquer linguagem capaz de fazer uma requisição HTTP consegue integrar usando apenas cURL ou um cliente HTTP nativo. Existem SDKs oficiais para TypeScript/Node, Python, Go, Java, PHP e C#/.NET que economizam código repetitivo, mas eles são opcionais. Para linguagens sem SDK oficial, como Ruby, Elixir ou Rust, o caminho recomendado é consumir os endpoints REST diretamente, exatamente como mostramos com cURL neste guia.
Como obtenho o token OAuth2 com cURL?
Você faz um POST para o endpoint de token enviando grant_type=client_credentials junto com seu client_id e client_secret no formato application/x-www-form-urlencoded. A resposta traz um access_token do tipo Bearer com tempo de expiração em segundos no campo expires_in. Esse token deve ser enviado no header Authorization: Bearer em todas as chamadas seguintes. O fluxo client-credentials é server-to-server e o token nunca deve ser exposto no front-end.
Qual a diferença entre a Signing Session e a Transaction API?
A Assinatura Expressa (POST /v1/signing-sessions) cria, com uma única chamada, uma sessão de assinatura que devolve uma URL de checkout hospedado ou um widget incorporável — ideal para fluxos simples de um signatário. A Transaction API trabalha com envelopes completos, múltiplos signatários, ordem de assinatura e o ciclo de vida transacional inteiro. Para a primeira chamada e provas de conceito, a Signing Session é o caminho mais rápido; fluxos corporativos complexos costumam usar a Transaction API.
Como envio o PDF a ser assinado pela API REST?
Há dois caminhos. O mais simples é enviar o PDF inline, codificado em base64, no campo document.content (até 10 MB) — o hash SHA-256 é calculado no servidor. Para arquivos maiores, o fluxo transacional oferece o upload em duas etapas: POST /v1/transactions/{id}/document/presign devolve uma URL pré-assinada temporária, você faz um PUT do binário diretamente nela e confirma com POST .../document/confirm. Se a URL pré-assinada expirar, basta solicitar outra — nada se perde.
Como verifico se um webhook veio mesmo da SignDocs usando só REST?
Cada webhook chega como POST HTTPS com um header de assinatura HMAC-SHA256 calculado a partir do corpo bruto da requisição e de um segredo compartilhado. No seu endpoint, você recalcula o HMAC-SHA256 sobre o raw body usando o mesmo segredo e compara, com comparação timing-safe, contra o valor recebido. Se coincidir, o evento é autêntico. Valide também o timestamp para evitar replay. Isso independe de linguagem ou SDK: qualquer biblioteca de criptografia padrão calcula HMAC-SHA256.
Posso testar a API com cURL antes de ir para produção?
Sim. Use o ambiente de homologação com host api-hml.signdocs.com.br (com hífen, não api.hml). As credenciais e os endpoints são os mesmos do fluxo de produção, então o código cURL que funciona em HML funciona em produção apenas trocando o host base e as credenciais. Atenção: no ambiente HML as entidades têm TTL de 7 dias, ou seja, transações e evidências de teste são apagadas automaticamente após esse prazo.
A API de assinatura tem validade jurídica no Brasil mesmo via REST puro?
Sim. A forma de integração (cURL, SDK ou no-code) não altera a validade jurídica. O que confere validade é o padrão de assinatura aplicado e a coleta de evidências: a SignDocs é nativa de ICP-Brasil, ancorada na MP 2.200-2/2001, gera contêineres PAdES/CAdES no nível baseline (assinatura + certificado + carimbo de hora do servidor + trilha de auditoria) e evidence pack .p7m que vincula o hash SHA-256 do documento à identidade do signatário. A mesma assinatura qualificada ou avançada é produzida independentemente de você ter chamado o endpoint por cURL ou por um SDK oficial.
Faça sua primeira chamada à API em minutos
REST puro, SDKs oficiais para 6 linguagens, ambiente de homologação gratuito e validade jurídica nativa de ICP-Brasil. O acesso à API é um plano sob medida — gere suas credenciais de homologação e teste com cURL antes de qualquer contrato.
Fale com o time comercial Conheça a plataforma grátis