Documentação

Guia completo para integrar a API do SimpleSigner — assinatura com certificado digital (ICP-Brasil / PAdES) e coleta de assinaturas por WhatsApp, e-mail ou SMS.

Introdução

A API SimpleSigner permite assinar documentos PDF com certificado digital ICP-Brasil (PAdES) e coletar assinaturas de terceiros por WhatsApp, e-mail ou SMS. A API segue os princípios REST e retorna respostas em JSON.

Base URL: https://simplesigner.com.br/

Formato de Resposta: JSON

Protocolo: HTTPS recomendado para produção

Nota: Antes de utilizar a API, certifique-se de ter um certificado digital A1 (.pfx) configurado na sua conta.

Autenticação

Todas as chamadas de API requerem autenticação via header X-Auth-Token. Este token é único para cada empresa e pode ser obtido no painel de controle.

Header de Autenticação
X-Auth-Token: SEU_TOKEN_AQUI
Erros de Autenticação
Status CodeDescrição
401Token inválido ou ausente
403Token válido mas acesso negado ao recurso

Assinar Documento (Upload)

Envia um arquivo PDF para ser assinado digitalmente com o certificado A1 configurado na sua conta.

Política de Retenção: Os arquivos assinados estarão disponíveis no sistema por 180 dias, após este período serão excluídos automaticamente. Certifique-se de salvar o arquivo assinado em seu sistema.
POST /Sign/Upload
Headers Obrigatórios
HeaderValor
X-Auth-TokenSeu token de autenticação
Content-Typemultipart/form-data
Headers Opcionais
HeaderDescrição
X-Caller-KeyIdentificador do sistema chamador (para rastreamento nos logs). Padrão: Desconhecido
X-Include-QRCodeAlternativa ao parâmetro include_qrcode via header. Valores: true / false
Parâmetros (Multipart/Form-Data)
CampoTipoObrigatórioDescrição
fileFileSimArquivo PDF a ser assinado (máx. 50MB)
include_qrcodeBooleanNãoDefine se o QR Code de validação será adicionado na última página. Padrão: true
clinicidcompanyIntegerNãoID da clínica associada ao documento — isenta do controle de quota mensal
Exemplo de Resposta (Sucesso - 200)
{
  "success": true,
  "message": "Arquivo assinado com sucesso",
  "link": "https://simplesigner.com.br/Sign/DownloadDoc/abc123def456...",
  "validationCode": "abc123def456",
  "secretCode": "472819",
  "qrCodeUrl": "https://simplesigner.com.br/Sign/Validate/abc123def456"
}
CampoDescrição
linkURL para download do PDF assinado
validationCodeCódigo UUID para validação pública do documento
secretCodeCódigo numérico de 6 dígitos exibido no rodapé do documento assinado
qrCodeUrlURL de validação embutida no QR Code do documento
Possíveis Erros
StatusRespostaDescrição
400{"success": false, "message": "Nenhum arquivo enviado"}Arquivo não foi incluído no request
400{"success": false, "message": "Arquivo vazio"}Arquivo enviado está vazio
400{"success": false, "message": "O arquivo excede o limite..."}Arquivo maior que 50MB
401{"success": false, "message": "Não autorizado..."}Token inválido ou ausente
403{"success": false, "message": "Limite mensal atingido..."}Quota mensal do plano esgotada
500{"success": false, "message": "Certificado digital não encontrado..."}Certificado não configurado na conta
500{"success": false, "message": "Erro interno ao processar..."}Erro ao processar assinatura

Upload de Certificado

Atualiza ou cadastra o certificado digital A1 (.pfx) da empresa. Este certificado será usado para assinar todos os documentos.

O certificado anterior será substituído pelo novo. Certifique-se de que o certificado é válido e a senha está correta.
POST /Sign/UploadCertificate
Headers Obrigatórios
HeaderValor
X-Auth-TokenSeu token de autenticação
Parâmetros
CampoTipoObrigatórioDescrição
fileFileSimArquivo .pfx do certificado digital A1
passwordStringNãoSenha do arquivo .pfx (pode ser vazio se o certificado não tiver senha)
Exemplo de Resposta (Sucesso - 200)
{
  "success": true,
  "message": "Certificado salvo com sucesso"
}
Possíveis Erros
StatusRespostaDescrição
400{"success": false, "message": "Nenhum arquivo enviado"}Arquivo não incluído
400{"success": false, "message": "Formato inválido..."}Arquivo não é .pfx
401{"success": false, "message": "Não autorizado..."}Token inválido
500{"success": false, "message": "Erro ao salvar..."}Erro ao processar certificado

Verificar Status do Certificado

Verifica se há um certificado cadastrado, se está válido e ativo.

GET /Sign/CheckCertificateStatus
Headers Obrigatórios
HeaderValor
X-Auth-TokenSeu token de autenticação
Exemplo de Resposta (Certificado Válido - 200)
{
  "success": true,
  "certificateRegistered": true,
  "certificateValid": true,
  "certificateActive": true,
  "message": "Certificado válido até 15/12/2026 10:30:00",
  "subject": "EMPRESA EXEMPLO LTDA",
  "issuer": "AC CERTISIGN G6",
  "notBefore": "2024-12-15T10:30:00",
  "notAfter": "2026-12-15T10:30:00",
  "daysUntilExpiration": 320
}
Exemplo de Resposta (Certificado Expirado - 200)
{
  "success": true,
  "certificateRegistered": true,
  "certificateValid": false,
  "certificateActive": false,
  "message": "O certificado expirou em 15/01/2025 10:30:00"
}
Exemplo de Resposta (Sem Certificado - 200)
{
  "success": true,
  "certificateRegistered": false,
  "certificateValid": false,
  "certificateActive": false,
  "message": "Certificado não cadastrado"
}
Possíveis Erros
StatusRespostaDescrição
401{"success": false, "message": "Não autorizado..."}Token inválido ou ausente
500{"success": false, "message": "Erro interno..."}Erro ao validar credenciais

API de Coleta de Assinaturas

Envie um PDF, defina os signatários (com canal WhatsApp, e-mail ou SMS) e gerencie toda a coleta programaticamente. Consulte status, reenvie convites, cancele e baixe o PDF final com trilha de auditoria.

Criar Coleta POST

POST /ApiSignRequests/Create

Cria uma nova coleta de assinaturas e dispara os convites para os signatários.

Headers
X-Auth-Token: SEU_TOKEN
X-Caller-Key: identificador-opcional
Body (multipart/form-data)
CampoTipoObrigatórioDescrição
pdffilesimArquivo PDF a ser assinado.
signersJsonstring (JSON)simArray de signatários. Ver exemplo abaixo.
titlestringnãoTítulo da coleta. Default = nome do arquivo.
signingModestringnãoparallel (default) ou sequential.
expiresInDaysintnãoPrazo em dias (1–365). Default 7.
vaultIdintnãoID de um cofre/categoria desta empresa.
clinicidcompanyintnãoSe informado, bypassa a cota mensal (integrações clínicas).
externalRefstringnãoSeu ID externo (ex: ContractId). Ecoa na resposta, Status e webhooks — use pra correlacionar com seu sistema.
webhookUrlstring (URL)nãoURL sua pra receber POST quando status mudar. Ver seção "Webhook de Callback".
Formato de signersJson
[
  {
    "name": "João da Silva",
    "phone": "11999999999",
    "email": "joao@email.com",
    "cpf": "12345678900",
    "channel": "whatsapp"
  },
  {
    "name": "Maria Souza",
    "email": "maria@empresa.com",
    "channel": "email"
  }
]
  • channel: whatsapp (default), email ou sms.
  • phone é obrigatório para whatsapp e sms; email é obrigatório para email.
  • Telefone aceita vários formatos (com/sem DDI). Exemplo: (11) 99999-9999, 5511999999999.
Resposta 200 (sucesso)
{
  "success": true,
  "requestId": 123,
  "validationCode": "9a8b7c...",
  "secretCode": "9A8B7C6D",
  "externalRef": "42",
  "status": "in_progress",
  "title": "Contrato 2026",
  "originalFileName": "contrato.pdf",
  "originalHash": "f4e3...sha256...",
  "signingMode": "parallel",
  "expiresAt": "2026-04-27T00:00:00",
  "vaultId": 5,
  "signers": [
    {
      "id": 1,
      "name": "João da Silva",
      "phone": "5511****99",
      "email": "joao@email.com",
      "channel": "whatsapp",
      "order": 1,
      "status": "sent",
      "signedAt": null,
      "signerToken": "aBc123_Xyz_abc...",
      "signUrl": "https://simplesigner.com.br/s/aBc123_Xyz_abc..."
    }
  ],
  "statusUrl": "https://simplesigner.com.br/ApiSignRequests/Status?id=123",
  "downloadUrl": "https://simplesigner.com.br/ApiSignRequests/Download?id=123"
}

Consultar Status da Coleta GET

GET /ApiSignRequests/Status?{id|validationCode|signerToken|externalRef}=...

Retorna o status completo da coleta, incluindo quem já assinou e quem falta.

Query string (use exatamente UM destes)
CampoTipoQuando usar
idintID interno da coleta (retornado no Create).
validationCodestring GUIDCódigo público da coleta (útil p/ integrar com URL de validação).
signerTokenstringToken do signatário (extraído da signUrl). Ideal quando você recebeu só o link do portal.
externalRefstringSeu identificador externo informado no Create (ex: ContractSessionId). Retorna a coleta mais recente.
Resposta 200
{
  "success": true,
  "id": 123,
  "validationCode": "9a8b7c...",
  "title": "Contrato 2026",
  "originalFileName": "contrato.pdf",
  "status": "in_progress",        // pending | in_progress | completed | canceled | expired
  "signingMode": "parallel",
  "createdAt": "2026-04-20T10:15:00",
  "expiresAt": "2026-04-27T00:00:00",
  "completedAt": null,
  "signedCount": 1,
  "pendingCount": 1,
  "totalSigners": 2,
  "signers": [
    { "id": 1, "name": "João", "channel": "whatsapp", "status": "signed",
      "signedAt": "2026-04-20T14:22:00", "order": 1,
      "signerToken": "aBc123_Xyz...", "signUrl": "https://simplesigner.com.br/s/aBc..." },
    { "id": 2, "name": "Maria", "channel": "email", "status": "sent",
      "signedAt": null, "order": 2,
      "signerToken": "xYz789_Abc...", "signUrl": "https://simplesigner.com.br/s/xYz..." }
  ],
  "pendingSigners": [
    { "id": 2, "name": "Maria", "channel": "email", "status": "sent" }
  ],
  "downloadUrl": null               // preenchido quando status=completed
}
Status possíveis da coleta
pendingCriada mas nenhum convite enviado ainda.
in_progressConvites enviados, aguardando assinaturas.
completedTodos assinaram; PDF final disponível.
canceledCancelada manualmente ou via API.
expiredPrazo expiresAt excedido.
Status possíveis de cada signatário
pendingCriado, ainda não convidado (modo sequencial esperando a vez).
sentConvite enviado, aguardando abertura.
openedClicou no link e abriu o documento.
verifiedValidou o OTP recebido no canal escolhido.
signedAssinou o documento.
declinedRecusou assinar.

Listar Coletas GET

GET /ApiSignRequests/List?status={opcional}&limit={opcional}

Retorna as últimas coletas da empresa (ordenadas por criação, mais recentes primeiro).

Query string
statusFiltra por status (pending, in_progress, completed, etc.).
limit1–500. Default 50.
Resposta 200
{
  "success": true,
  "total": 2,
  "items": [
    { "id": 124, "title": "NDA Consultoria", "status": "completed",
      "signedCount": 2, "totalSigners": 2, "createdAt": "...", "completedAt": "..." },
    { "id": 123, "title": "Contrato 2026", "status": "in_progress",
      "signedCount": 1, "totalSigners": 2, "createdAt": "...", "completedAt": null }
  ]
}

Reenviar Convite POST

POST /ApiSignRequests/Resend

Reenvia o convite para um signatário pelo canal original (WhatsApp/e-mail/SMS).

Body (form-urlencoded)
signerIdID do signatário (do array signers).
Resposta 200
{ "success": true, "signer": { "id": 2, "status": "sent", ... } }
Erros
  • 400 already_signed — signatário já assinou, nada a reenviar.
  • 404 notfound — signer não existe.
  • 403 forbidden — signer de outra empresa.

Cancelar Coleta POST

POST /ApiSignRequests/Cancel

Cancela uma coleta em andamento. Signatários que já assinaram mantêm o registro.

Body (form-urlencoded)
idID da coleta.
Resposta 200
{ "success": true, "id": 123, "status": "canceled" }

Baixar PDF Final GET

GET /ApiSignRequests/Download?id={id}

Baixa o PDF final da coleta (somente quando status=completed). O PDF inclui páginas de assinaturas + trilha de auditoria + selo PAdES com o certificado da empresa.

Resposta
  • 200application/pdf (download direto).
  • 409 not_completed — a coleta ainda não terminou.
  • 404 file_missing — arquivo final não encontrado no servidor.

Webhook de Callback

Se você passar webhookUrl no /ApiSignRequests/Create, o SimpleSigner faz POST application/json nessa URL toda vez que o status mudar. Útil pra seu sistema saber em tempo real quando uma coleta terminou sem precisar fazer polling no /Status.

Eventos
eventQuando dispara
signer.signedUm signatário assinou (dispara 1x por signer).
request.completedTodos assinaram, PDF final pronto pra download.
request.canceledColeta cancelada via API ou dashboard.
request.expiredPrazo expiresAt atingido (detectado quando um signatário tenta abrir o link após a expiração).
Payload (JSON body do POST)
{
  "event": "request.completed",
  "requestId": 123,
  "validationCode": "9a8b7c...",
  "externalRef": "42",
  "status": "completed",
  "completedAt": "2026-04-20T14:35:12",
  "title": "Contrato 2026",
  "extra": null
}

No evento signer.signed, extra vem com { signerId, signerName, channel }.

Headers enviados pelo SimpleSigner
X-SimpleSigner-EventTipo do evento (útil pra rotear sem parsear o body).
X-SimpleSigner-SignatureHMAC-SHA256 do body no formato sha256=hexdigest. Chave = token da empresa (X-Auth-Token). Valide pra confirmar origem.
Validação do HMAC (C#)
using (var h = new HMACSHA256(Encoding.UTF8.GetBytes(companyToken))) {
    var hash = h.ComputeHash(Encoding.UTF8.GetBytes(rawBody));
    var expected = "sha256=" + BitConverter.ToString(hash).Replace("-","").ToLower();
    var received = Request.Headers["X-SimpleSigner-Signature"];
    if (expected != received) return Unauthorized();
}
Entrega: best-effort. Timeout 10s. Sem retry automático. Se seu endpoint retornar não-2xx ou demorar, a falha é registrada em ErrorLog.txt do servidor SimpleSigner mas o evento não é reenviado. Para garantias fortes, faça polling em /ApiSignRequests/Status como fallback.

Códigos de Erro HTTP

A API utiliza códigos de status HTTP padrão para indicar sucesso ou falha das requisições.

Código Status Descrição
200 OK Requisição processada com sucesso
400 Bad Request Parâmetros inválidos ou ausentes
401 Unauthorized Token de autenticação inválido ou ausente
403 Forbidden Acesso negado ao recurso
404 Not Found Recurso não encontrado
500 Internal Server Error Erro interno do servidor
Dica: Todas as respostas incluem um campo "success" (boolean) e "message" (string) para facilitar o tratamento de erros.

Exemplos de Integração

Veja como chamar a API nas principais linguagens.

using System.Net.Http;
using System.Net.Http.Headers;
using System.IO;

var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-Auth-Token", "SEU_TOKEN");

var form = new MultipartFormDataContent();
var fileContent = new ByteArrayContent(File.ReadAllBytes("documento.pdf"));
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/pdf");
form.Add(fileContent, "file", "documento.pdf");

var response = await client.PostAsync("https://simplesigner.com.br/Sign/Upload", form);
var result = await response.Content.ReadAsStringAsync();
$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://simplesigner.com.br/Sign/Upload",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST => true,
  CURLOPT_HTTPHEADER => ["X-Auth-Token: SEU_TOKEN"],
  CURLOPT_POSTFIELDS => [
    'file' => new CURLFile('/path/to/documento.pdf')
  ]
]);

$response = curl_exec($curl);
curl_close($curl);
echo $response;
// Usando OkHttp
OkHttpClient client = new OkHttpClient();

RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
    .addFormDataPart("file", "documento.pdf",
        RequestBody.create(MediaType.parse("application/pdf"), new File("documento.pdf")))
    .build();

Request request = new Request.Builder()
    .url("https://simplesigner.com.br/Sign/Upload")
    .addHeader("X-Auth-Token", "SEU_TOKEN")
    .post(body)
    .build();

Response response = client.newCall(request).execute();
System.out.println(response.body().string());
import requests

url = "https://simplesigner.com.br/Sign/Upload"
headers = {"X-Auth-Token": "SEU_TOKEN"}
files = {"file": open("documento.pdf", "rb")}

response = requests.post(url, headers=headers, files=files)
print(response.json())