convertajá

Guia 6 de 8

Assinatura eletrônica pela API

Seu sistema gera o contrato; a API manda o convite por e-mail, cada pessoa confirma um código e assina, e você recebe o PDF assinado com o relatório de evidências.

15 min · Intermediário · atualizado em 16/10/2026

O que você vai construir

Um fluxo completo: criar o envelope com o PDF, um cliente e uma testemunha, posições das assinaturas e webhook; acompanhar; baixar o PDF final e o relatório quando todos assinarem.

Antes de começar

  • Uma chave de API em CONVERTAJA_KEY (veja Primeiros passos).
  • Um PDF sem senha, de até 20 MB e 100 páginas.
  • Um endpoint de webhook (opcional, mas recomendado; veja Webhooks).

Antes de começar: custo e cota

  • Créditos: 20 créditos por envelope enviado (até 10 signatários). Rascunho, consultas, lembretes, cancelamento e downloads são grátis. Se o envio falhar, os créditos voltam; cancelar um envelope já enviado não devolve.
  • Cota mensal: quem tem um plano pago da API é limitado só pelos créditos. Sem plano pago da API, vale a cota de documentos do plano do site (Grátis 3, Pro 30, Empresas 200 por mês); acima dela, 402 esign_quota, sem cobrança.
  • Chaves de teste não gastam créditos, mas os e-mails são enviados de verdade e o envio conta na cota.
402: cota do mês esgotada
{
  "error": {
    "code": "esign_quota",
    "message": "Você já enviou 3 de 3 documentos para assinatura este mês no plano Grátis. Assine um plano maior ou aguarde o próximo mês.",
    "quota_limit": 3,
    "quota_used": 3,
    "request_id": "req_UkbrW3QRi59d"
  }
}

Passo 1: Defina quem assina e onde

Cada signatário tem name (nome completo), email e, opcionalmente, role (sign, approve ou witness), cpf (a pessoa precisa digitar o mesmo), ask_cpf e rubrica_all (rubrica em todas as páginas).

Os campos (fields) dizem onde cada pessoa assina, em frações da página (0 a 1) a partir do canto superior esquerdo, com page começando em 0. Tipos: signature, initials, date, name, cpf. Sem campos, as assinaturas aparecem só no relatório.

{ "signer": 0, "type": "signature", "page": 0, "x": 0.1, "y": 0.75, "w": 0.3, "h": 0.07 }
// pessoa 0, primeira página, começa a 10% da esquerda e 75% do topo, 30% de largura, 7% de altura

Passo 2: Crie e envie o envelope

Envie o PDF no campo file e o resto em data (JSON). Por padrão os convites saem na hora (send: true) e, com sequential: true (padrão), uma pessoa por vez, na ordem da lista:

curl -X POST "https://convertaja.com.br/v1/esign/envelopes" \
  -H "Authorization: Bearer $CONVERTAJA_KEY" \
  -F "file=@contrato.pdf" \
  -F 'data={
    "name": "Contrato de prestação de serviços",
    "message": "Olá! Segue o contrato para assinatura.",
    "signers": [
      { "name": "Ana Souza", "email": "ana@cliente.com.br" },
      { "name": "Bruno Lima", "email": "bruno@empresa.com.br", "role": "witness" }
    ],
    "fields": [
      { "signer": 0, "type": "signature", "page": 0, "x": 0.1, "y": 0.75, "w": 0.3, "h": 0.07 },
      { "signer": 1, "type": "signature", "page": 0, "x": 0.55, "y": 0.75, "w": 0.3, "h": 0.07 }
    ],
    "webhook_url": "https://seusite.com.br/webhooks/convertaja"
  }'

A resposta é 201 com o envelope. A primeira pessoa fica pending (convidada) e a testemunha, waiting (aguardando a vez):

Resposta 201 (trecho)
{
  "id": "JCGM-BEMM-8SYT-2JFL",
  "object": "envelope",
  "name": "Contrato de prestação de serviços",
  "status": "pending",
  "status_label": "Aguardando",
  "pages": 1,
  "signed_count": 0,
  "signer_count": 2,
  "sent_at": "2026-10-16T20:26:30.228Z",
  "expires_at": "2026-11-15T20:26:30.222Z",
  "original_sha256": "081010e21aaf012336eff1e0171f41f268c7180391d01809c71c07a01972538e",
  "signers": [
    {
      "id": 1,
      "position": 0,
      "name": "Ana Souza",
      "email": "ana@cliente.com.br",
      "role": "sign",
      "status": "pending",
      "notified_at": "2026-10-16T20:26:30.230Z",
      "signed_at": null
    },
    {
      "id": 2,
      "position": 1,
      "name": "Bruno Lima",
      "email": "bruno@empresa.com.br",
      "role": "witness",
      "status": "waiting",
      "notified_at": null,
      "signed_at": null
    }
  ],
  "files": null,
  "credits_charged": 20,
  "webhook_url": "https://seusite.com.br/webhooks/convertaja",
  "url": "https://convertaja.com.br/v1/esign/envelopes/JCGM-BEMM-8SYT-2JFL"
}

Outros campos de data: message (texto do convite), expires_at (prazo, de 1 hora a 90 dias; padrão 30 dias) e return_links: true, que devolve signers[].sign_url para você mandar o link pelo seu próprio canal (WhatsApp, área do cliente). Prefere JSON? Mande "file": { "base64": "…", "name": "contrato.pdf" } ou { "url": "https://…" } no mesmo corpo.

Variação: rascunho primeiro, envio depois

Com send: false, o envelope fica como rascunho (draft), grátis, até você chamar POST …/send:

# 1) Cria o rascunho (grátis, nada é enviado ainda)
curl -X POST "https://convertaja.com.br/v1/esign/envelopes" \
  -H "Authorization: Bearer $CONVERTAJA_KEY" \
  -F "file=@proposta.pdf" \
  -F 'data={"name":"Proposta comercial","signers":[{"name":"Carla Dias","email":"carla@cliente.com.br"}],"send":false}'

# 2) Quando estiver tudo certo, envia (cobra 20 créditos)
curl -X POST "https://convertaja.com.br/v1/esign/envelopes/74W7-E8AV-X86B-67GZ/send" \
  -H "Authorization: Bearer $CONVERTAJA_KEY"

Passo 3: Acompanhe a assinatura

O ideal é esperar o webhook (próximo passo). Para consultar a qualquer momento:

curl "https://convertaja.com.br/v1/esign/envelopes/JCGM-BEMM-8SYT-2JFL" \
  -H "Authorization: Bearer $CONVERTAJA_KEY"

# Com a trilha de auditoria (quem abriu, confirmou o código, assinou; IP, porta e dispositivo)
curl "https://convertaja.com.br/v1/esign/envelopes/JCGM-BEMM-8SYT-2JFL?events=true" \
  -H "Authorization: Bearer $CONVERTAJA_KEY"

Situações do envelope: draft → pending → completed, ou refused (alguém recusou), expired (passou o prazo) e canceled. Cada signatário tem notified_at, viewed_at, verified_at (confirmou o código do e-mail) e signed_at.

Passo 4: Receba o aviso de conclusão

Com webhook_url, avisamos uma vez quando o envelope chega a um estado final: esign.envelope.completed, refused, expired ou canceled. Conferimos a situação a cada 30 segundos, então o aviso pode levar até meio minuto. A assinatura X-Convertaja-Signature é a mesma das tarefas: use o código do guia Webhooks sem mudar nada.

Corpo do aviso esign.envelope.completed
{
  "id": "evt_03885356524f1746b2ed",
  "type": "esign.envelope.completed",
  "created_at": "2026-10-16T20:26:46.869Z",
  "data": {
    "id": "JCGM-BEMM-8SYT-2JFL",
    "object": "envelope",
    "name": "Contrato de prestação de serviços",
    "file_name": "contrato.pdf",
    "status": "completed",
    "status_label": "Assinado",
    "source": "api",
    "sequential": true,
    "message": "Olá! Segue o contrato para assinatura.",
    "pages": 1,
    "signed_count": 2,
    "signer_count": 2,
    "created_at": "2026-10-16T20:26:30.222Z",
    "updated_at": "2026-10-16T20:26:44.036Z",
    "sent_at": "2026-10-16T20:26:30.228Z",
    "completed_at": "2026-10-16T20:26:43.891Z",
    "closed_at": "2026-10-16T20:26:43.891Z",
    "expires_at": "2026-11-15T20:26:30.222Z",
    "purge_at": "2027-01-14T20:26:43.891Z",
    "original_sha256": "081010e21aaf012336eff1e0171f41f268c7180391d01809c71c07a01972538e",
    "final_sha256": "9d0b6a1db020d48f1a2da2b06622b1d7dab0f9942ba9b091dc2dafc15f8a13a0",
    "verify_url": "https://convertaja.com.br/verificar/JCGM-BEMM-8SYT-2JFL",
    "signers": [
      {
        "id": 1,
        "position": 0,
        "name": "Ana Souza",
        "email": "ana@cliente.com.br",
        "role": "sign",
        "status": "signed",
        "ask_cpf": false,
        "cpf_masked": null,
        "rubrica_all": false,
        "notified_at": "2026-10-16T20:26:30.230Z",
        "viewed_at": "2026-10-16T20:26:41.554Z",
        "verified_at": "2026-10-16T20:26:41.929Z",
        "signed_at": "2026-10-16T20:26:41.950Z",
        "refused_at": null,
        "refuse_reason": null
      },
      {
        "id": 2,
        "position": 1,
        "name": "Bruno Lima",
        "email": "bruno@empresa.com.br",
        "role": "witness",
        "status": "signed",
        "ask_cpf": false,
        "cpf_masked": null,
        "rubrica_all": false,
        "notified_at": "2026-10-16T20:26:41.951Z",
        "viewed_at": "2026-10-16T20:26:43.517Z",
        "verified_at": "2026-10-16T20:26:43.870Z",
        "signed_at": "2026-10-16T20:26:43.891Z",
        "refused_at": null,
        "refuse_reason": null
      }
    ],
    "fields": [
      {
        "type": "signature",
        "signer": 0,
        "page": 0,
        "x": 0.1,
        "y": 0.75,
        "w": 0.3,
        "h": 0.07
      },
      {
        "type": "signature",
        "signer": 1,
        "page": 0,
        "x": 0.55,
        "y": 0.75,
        "w": 0.3,
        "h": 0.07
      }
    ],
    "files": {
      "final": "https://convertaja.com.br/v1/esign/envelopes/JCGM-BEMM-8SYT-2JFL/files/final",
      "audit": "https://convertaja.com.br/v1/esign/envelopes/JCGM-BEMM-8SYT-2JFL/files/audit"
    },
    "credits_charged": 20,
    "webhook_url": "https://seusite.com.br/webhooks/convertaja",
    "url": "https://convertaja.com.br/v1/esign/envelopes/JCGM-BEMM-8SYT-2JFL"
  }
}

Passo 5: Baixe o PDF assinado e o relatório

Com o envelope em completed, files.final é o PDF com as assinaturas aplicadas e files.audit é o relatório de assinaturas (IP e porta, dispositivo, horários, hashes SHA-256 e QR Code de verificação). Antes disso, a API responde 409 envelope_not_completed.

# PDF assinado
curl -f -o contrato-assinado.pdf "https://convertaja.com.br/v1/esign/envelopes/JCGM-BEMM-8SYT-2JFL/files/final" \
  -H "Authorization: Bearer $CONVERTAJA_KEY"

# Relatório de assinaturas (evidências)
curl -f -o contrato-relatorio.pdf "https://convertaja.com.br/v1/esign/envelopes/JCGM-BEMM-8SYT-2JFL/files/audit" \
  -H "Authorization: Bearer $CONVERTAJA_KEY"

Qualquer pessoa pode conferir a autenticidade em verify_url. Os arquivos ficam guardados por 90 dias depois da conclusão (purge_at): copie para o seu armazenamento.

Lembrar, cancelar e listar

# Lembrar quem ainda não assinou (no máximo 1 vez a cada 30 minutos)
curl -X POST "https://convertaja.com.br/v1/esign/envelopes/74W7-E8AV-X86B-67GZ/remind" \
  -H "Authorization: Bearer $CONVERTAJA_KEY"

# Cancelar (os links deixam de funcionar; os créditos de um envelope enviado não voltam)
curl -X POST "https://convertaja.com.br/v1/esign/envelopes/74W7-E8AV-X86B-67GZ/cancel" \
  -H "Authorization: Bearer $CONVERTAJA_KEY"

# Listar os envelopes concluídos (20 por página; use next_cursor para a próxima)
curl "https://convertaja.com.br/v1/esign/envelopes?status=completed&limit=20" \
  -H "Authorization: Bearer $CONVERTAJA_KEY"
Lembrete enviado
{
  "id": "74W7-E8AV-X86B-67GZ",
  "reminded": 1
}
429: lembrete repetido
{
  "error": {
    "code": "reminder_too_soon",
    "message": "Você já enviou um lembrete há pouco. Tente de novo em 30 minutos.",
    "request_id": "req_UkbrW3QRi59d"
  }
}

Para excluir de vez: DELETE /v1/esign/envelopes/{id} (ou POST …/delete).

Erros e o que fazer

HTTPcodeQuando
400invalid_requestDado de signatário ou campo inválido. error.param diz qual (ex.: signer_name, signer_email, fields).
400invalid_webhook_urlURL sem HTTPS, de rede interna ou com domínio que não existe.
402esign_quota / insufficient_creditsCota do mês ou créditos esgotados. Nada é cobrado.
404envelope_not_foundId errado, excluído ou de outra conta.
409invalid_stateAção incompatível (ex.: enviar de novo um envelope já enviado).
413 / 422file_too_large / invalid_pdfPDF acima de 20 MB, com senha, corrompido ou com mais de 100 páginas.
400: nome incompleto
{
  "error": {
    "code": "invalid_request",
    "message": "Digite o nome da pessoa 1.",
    "param": "signer_name",
    "request_id": "req_UkbrW3QRi59d"
  }
}

Base legal: assinatura eletrônica nos termos da MP 2.200-2/2001, art. 10, § 2º, e da Lei 14.063/2020. Não é assinatura qualificada com certificado ICP-Brasil.

Próximos passos

Todos os endpoints e opções: referência da API. Dúvidas? Fale com a gente e informe o X-Request-Id da chamada.