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.
Pré-requisitos
Antes de começar, você precisa de:
- Uma conta KivoSign
- Um token de API (crie um nas configurações da equipe)
- Um arquivo PDF para enviar para assinatura
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:
| Ambiente | URL base |
|---|---|
| Produção | https://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âmetro | Descrição |
|---|---|
positionX | Posição horizontal a partir da borda esquerda (0 = esquerda, 100 = direita) |
positionY | Posição vertical a partir do topo (0 = topo, 100 = rodapé) |
width | Largura do campo em percentual da largura da página |
height | Altura do campo em percentual da altura da página |
page | Nú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
| Papel | Descrição |
|---|---|
SIGNER | Precisa assinar o documento |
APPROVER | Precisa aprovar antes que os signatários possam assinar |
CC | Recebe uma cópia, mas não assina |
VIEWER | Pode 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ódigo | Significado |
|---|---|
400 | Requisição inválida - confira o payload |
401 | Não autorizado - token de API inválido ou ausente |
404 | Não encontrado - o recurso não existe |
429 | Limite de requisições ou cota do plano. Se houver Retry-After, repita a requisição. |
500 | Erro 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:

