KivoSign

Primeira chamada à API

Crie e envie um documento para assinatura usando a API da KivoSign, do envio do PDF à inclusão de destinatários e distribuição para assinatura.

Documentos e modelos estão sendo descontinuados e substituídos por envelopes. Leia o guia de migração.

Pré-requisitos

Antes de começar, você precisa de:

Tokens de API têm acesso total à sua conta. Guarde-os em local seguro e nunca faça commit deles no controle de versão.

Limitações

A API não consegue:

  • Assinar documentos em nome dos destinatários (cada destinatário assina por conta própria)
  • Converter arquivos que não sejam PDF (envie sempre PDF)
  • Baixar o PDF assinado antes de todos os destinatários concluírem a assinatura

URL base

Todas as requisições usam a seguinte URL base:

AmbienteURL base
Produçãohttps://app.kivosign.com.br/api/v2

Exemplo 1: listar seus documentos

Comece com um GET simples para confirmar que o token funciona.

curl -X GET "https://app.kivosign.com.br/api/v2/envelope" \
  -H "Authorization: SEU_TOKEN_DE_API"

Uma resposta de sucesso traz a lista dos seus documentos (envelopes):

{
  "data": [
    {
      "id": "envelope_abc123",
      "status": "DRAFT",
      "title": "Contrato de prestação de serviços",
      "createdAt": "2025-01-15T10:30:00.000Z"
    }
  ],
  "count": 1,
  "currentPage": 1,
  "perPage": 10,
  "totalPages": 1
}

Se receber o erro 401 Unauthorized, confira se o token está correto e começa com o prefixo api_.

Exemplo 2: criar um documento com destinatário e campo de assinatura

A API V2 usa um único endpoint para criar o documento com destinatários e campos na mesma requisição. Esse é o padrão mais comum para enviar documentos.

curl -X POST "https://app.kivosign.com.br/api/v2/envelope/create" \
  -H "Authorization: SEU_TOKEN_DE_API" \
  -H "Content-Type: multipart/form-data" \
  -F 'payload={
    "type": "DOCUMENT",
    "title": "Contrato de prestação de serviços",
    "recipients": [
      {
        "email": "signatario@exemplo.com",
        "name": "João Silva",
        "role": "SIGNER",
        "fields": [
          {
            "identifier": 0,
            "type": "SIGNATURE",
            "page": 1,
            "positionX": 10,
            "positionY": 80,
            "width": 30,
            "height": 5
          },
          {
            "identifier": 0,
            "type": "DATE",
            "page": 1,
            "positionX": 50,
            "positionY": 80,
            "width": 20,
            "height": 3
          }
        ]
      }
    ]
  }' \
  -F "files=@./contrato.pdf;type=application/pdf"

Posicionamento dos campos

As posições dos campos usam percentuais (0 a 100) relativos ao tamanho da página do PDF:

ParâmetroDescrição
positionXPosição horizontal a partir da borda esquerda (0 = esquerda, 100 = direita)
positionYPosição vertical a partir do topo (0 = topo, 100 = rodapé)
widthLargura do campo em percentual da largura da página
heightAltura do campo em percentual da altura da página
pageNúmero da página (começa em 1)
identifierÍndice do arquivo (0 para o primeiro arquivo, 1 para o segundo etc.)

Para colocar uma assinatura perto do canto inferior esquerdo da página, use positionX: 10 e positionY: 80.

Papéis dos destinatários

PapelDescrição
SIGNERPrecisa assinar o documento
APPROVERPrecisa aprovar antes que os signatários possam assinar
CCRecebe uma cópia, mas não assina
VIEWERPode ver o documento, mas não realiza nenhuma ação

Veja a página papéis dos destinatários para mais informações.

Exemplo 3: enviar o documento para assinatura

Depois de criado, o documento fica com status DRAFT (rascunho). Para enviá-lo aos destinatários, use o endpoint de distribuição:

curl -X POST "https://app.kivosign.com.br/api/v2/envelope/distribute" \
  -H "Authorization: SEU_TOKEN_DE_API" \
  -H "Content-Type: application/json" \
  -d '{
    "envelopeId": "envelope_abc123"
  }'

Após a distribuição, os destinatários recebem um e-mail com o link para assinar. O status do documento muda de DRAFT para PENDING.

Exemplo completo

Script completo que cria e envia um documento:

const fs = require('fs');
const FormData = require('form-data');

const API_TOKEN = process.env.KIVOSIGN_API_TOKEN;
const BASE_URL = 'https://app.kivosign.com.br/api/v2';

async function createAndSendDocument(pdfPath, recipientEmail, recipientName) {
  // Passo 1: criar o envelope com destinatário e campos
  const form = new FormData();

  const payload = {
    type: 'DOCUMENT',
    title: 'Contrato de prestação de serviços',
    recipients: [
      {
        email: recipientEmail,
        name: recipientName,
        role: 'SIGNER',
        fields: [
          {
            identifier: 0,
            type: 'SIGNATURE',
            page: 1,
            positionX: 10,
            positionY: 80,
            width: 30,
            height: 5,
          },
          {
            identifier: 0,
            type: 'NAME',
            page: 1,
            positionX: 10,
            positionY: 75,
            width: 30,
            height: 3,
          },
          {
            identifier: 0,
            type: 'DATE',
            page: 1,
            positionX: 50,
            positionY: 80,
            width: 20,
            height: 3,
          },
        ],
      },
    ],
  };

  form.append('payload', JSON.stringify(payload));
  form.append('files', fs.createReadStream(pdfPath), {
    contentType: 'application/pdf',
  });

  const createResponse = await fetch(`${BASE_URL}/envelope/create`, {
    method: 'POST',
    headers: {
      'Authorization': API_TOKEN,
    },
    body: form,
  });

  if (!createResponse.ok) {
    const error = await createResponse.json();
    throw new Error(`Falha ao criar o envelope: ${JSON.stringify(error)}`);
  }

  const envelope = await createResponse.json();
  console.log('Envelope criado:', envelope.id);

  // Passo 2: enviar o documento para assinatura
  const distributeResponse = await fetch(`${BASE_URL}/envelope/distribute`, {
    method: 'POST',
    headers: {
      'Authorization': API_TOKEN,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ envelopeId: envelope.id }),
  });

  if (!distributeResponse.ok) {
    const error = await distributeResponse.json();
    throw new Error(`Falha ao distribuir o envelope: ${JSON.stringify(error)}`);
  }

  console.log('Documento enviado para assinatura!');
  return envelope.id;
}

createAndSendDocument(
  './contrato.pdf',
  'signatario@exemplo.com',
  'João Silva'
).catch(console.error);

Tratamento de erros

A API retorna códigos de status HTTP padrão e respostas de erro em JSON:

CódigoSignificado
400Requisição inválida - confira o payload
401Não autorizado - token de API inválido ou ausente
404Não encontrado - o recurso não existe
429Limite de requisições ou cota do plano. Se houver Retry-After, repita a requisição.
500Erro no servidor - tente de novo ou fale com o suporte

Formato da resposta de erro

{
  "error": "Descrição do que deu errado",
  "code": "ERROR_CODE",
  "statusCode": 400
}

Erros comuns

Tipo de arquivo inválido:

{
  "error": "Invalid file type. Only PDF files are supported.",
  "statusCode": 400
}

Campo obrigatório ausente:

{
  "error": "Recipient email is required",
  "statusCode": 400
}

Envelope não encontrado:

{
  "error": "Envelope not found",
  "statusCode": 404
}

Limites de requisições

A API aceita até 1000 requisições por minuto por endereço IP, e sua organização pode ter um limite menor. Cada resposta traz X-RateLimit-Remaining e X-RateLimit-Reset (timestamp epoch em segundos). Uma resposta 429 por limite de janela traz Retry-After: espere esse número de segundos antes de enviar a requisição de novo. Uma resposta 429 por cota não traz Retry-After, porque esperar não resolve o erro de cota. Sem Retry-After, não repita a requisição automaticamente.

Veja Padrões de tratamento de erros para mais detalhes sobre novas tentativas.

async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.status === 429) {
      const retryAfter = response.headers.get('Retry-After');

      if (!retryAfter) {
        return response;
      }

      const retryAfterSeconds = Number.parseInt(retryAfter, 10);
      console.log(`Limite atingido. Aguardando ${retryAfterSeconds} segundos...`);
      await new Promise((resolve) => setTimeout(resolve, retryAfterSeconds * 1000));
      continue;
    }

    return response;
  }

  throw new Error('Número máximo de tentativas excedido');
}

Próximos passos

  • Especificação OpenAPI - Documentação completa dos endpoints, com schemas de requisição e resposta
  • Webhooks - Seja notificado quando documentos forem assinados
  • Modelos - Crie modelos de documento reutilizáveis
  • SDKs - Use bibliotecas cliente tipadas

SDKs

Para aplicações em produção, considere usar um SDK. Configure a URL do servidor como https://app.kivosign.com.br/api/v2:

Nesta página