kliper
Obter chave
Kliper API · v1

Extração de documentos com IA,
direto na sua aplicação.

Envie um PDF, receba dados estruturados. A API do Kliper expõe o mesmo motor de extração do painel — autenticação por token, envio assíncrono por arquivo ou URL, detecção automática do tipo de documento e resultados em JSON.

Base URL · Produção

https://api.kliper.ai/v1

Base URL · Sandbox

https://api-sandbox.kliper.ai/v1

Rate limit

60 req/min por chave

Introdução

Todas as requisições usam https e retornam JSON. O processamento é assíncrono: você envia um documento, recebe um id, faz polling do status e, quando concluído, busca o resultado. O fluxo típico é:

  1. 1POST o documento para /documents → recebe o id e o status queued.
  2. 2GET /documents/{id} até o status virar success ou requires_review.
  3. 3GET /documents/{id}/result para obter os dados extraídos.

Cada resposta traz um objeto links com URLs absolutas para os próximos passos, então você raramente precisa montar caminhos à mão. Prefere não fazer polling? Informe um callbackUrl no envio e receba um webhook assinado quando o processamento terminar.

Autenticação

A API usa chaves de portador (Bearer). Crie uma chave na página Desenvolvedor do painel. A chave completa é exibida apenas uma vez na criação — guarde-a com segurança. Envie-a no header Authorization de toda requisição:

http
Authorization: Bearer kp_live_a1b2c3d4e5f6...

Há dois tipos de chave. As de produção começam com kp_live_ e consomem créditos. As de sandbox começam com kp_test_, são gratuitas e limitadas a 25 documentos a cada 24h — ideais para homologar a integração antes de ir para produção. Use a chave kp_test_ contra a Base URL de sandbox (https://api-sandbox.kliper.ai/v1) e a kp_live_ contra a de produção. O contrato é idêntico nos dois.

Requisições sem chave válida retornam 401 Unauthorized. Cada chave tem limite de 60 requisições por minuto.

Tipos de documento

GET/document-types

Lista os tipos de documento disponíveis para a sua organização. Use o slug de cada tipo como valor de documentType ao enviar um documento. O id também é aceito, mas o slug é o identificador recomendado por ser estável e legível.

bash
curl https://api.kliper.ai/v1/document-types \
  -H "Authorization: Bearer kp_live_a1b2c3d4e5f6..."

Resposta 200 OK

json
{
  "data": [
    {
      "id": "665f1a2b3c4d5e6f7a8b9c0d",
      "slug": "nota-fiscal",
      "name": "Nota Fiscal",
      "description": "Notas fiscais eletrônicas (NF-e).",
      "maxFileSizeMB": 75,
      "maxPages": 50
    }
  ]
}

Se você não sabe de antemão qual é o tipo, envie documentType: "auto" e o Kliper identifica o tipo do PDF automaticamente antes de processar.

Enviar documento

POST/documents

Aceita duas formas de envio: multipart/form-data com o arquivo em file, ou application/json com uma url pública para o PDF (o Kliper busca o arquivo por você). Em ambos os casos, informe o documentType pelo slug ou use "auto" para detecção automática.

CampoTipoDescrição
filearquivoPDF a processar (modo multipart).
urlstringURL https pública para o PDF (modo JSON, alternativa ao file).
documentType *stringSlug do tipo (ex.: nota-fiscal) ou "auto".
callbackUrlstringURL https para receber o webhook ao finalizar (opcional).
metadataobjetoMetadados livres, devolvidos no webhook (opcional).

Requisição

bash
curl -X POST https://api.kliper.ai/v1/documents \
  -H "Authorization: Bearer kp_live_a1b2c3d4e5f6..." \
  -F "file=@nota-fiscal.pdf" \
  -F "documentType=nota-fiscal" \
  -F "callbackUrl=https://seu-app.com/webhooks/kliper"

Resposta 201 Created

json
{
  "id": "665f9a8b7c6d5e4f3a2b1c0d",
  "status": "queued",
  "documentType": "nota-fiscal",
  "links": {
    "self": "https://api.kliper.ai/v1/documents/665f9a8b7c6d5e4f3a2b1c0d",
    "result": "https://api.kliper.ai/v1/documents/665f9a8b7c6d5e4f3a2b1c0d/result"
  }
}

Com documentType: "auto", se o Kliper não conseguir identificar o tipo com segurança, a resposta é 422 pedindo que você informe o documentType explicitamente:

json
{
  "error": "Could not automatically detect the document type. Please specify documentType.",
  "documentTypes": "https://api.kliper.ai/v1/document-types"
}

Consultar status

GET/documents/{id}

Faça polling deste endpoint até o status indicar conclusão. Status possíveis incluem queued, processing, success, requires_review, partial_success e failed. O campo progress vai de 0 a 100 (ou null antes de começar).

bash
curl https://api.kliper.ai/v1/documents/665f9a8b7c6d5e4f3a2b1c0d \
  -H "Authorization: Bearer kp_live_a1b2c3d4e5f6..."

Resposta 200 OK

json
{
  "id": "665f9a8b7c6d5e4f3a2b1c0d",
  "status": "processing",
  "documentType": "nota-fiscal",
  "progress": 60,
  "createdAt": "2026-06-30T12:00:00.000Z",
  "links": {
    "self": "https://api.kliper.ai/v1/documents/665f9a8b7c6d5e4f3a2b1c0d",
    "result": "https://api.kliper.ai/v1/documents/665f9a8b7c6d5e4f3a2b1c0d/result"
  }
}

Obter resultado

GET/documents/{id}/result

Disponível quando o status é success, requires_review ou partial_success. Antes disso retorna 409 Conflict. Os dados extraídos vêm no campo data, dentro de um envelope estável. O campo schemaVersion refere-se à versão do contrato da API (não do documento).

bash
curl https://api.kliper.ai/v1/documents/665f9a8b7c6d5e4f3a2b1c0d/result \
  -H "Authorization: Bearer kp_live_a1b2c3d4e5f6..."

Resposta 200 OK

json
{
  "schemaVersion": "1.0",
  "documentId": "665f9a8b7c6d5e4f3a2b1c0d",
  "documentType": "nota-fiscal",
  "status": "success",
  "data": {
    "numeroNota": "000.123.456",
    "dataEmissao": "2026-06-15",
    "valorTotal": 1540.90,
    "emitente": { "cnpj": "12.345.678/0001-90", "razaoSocial": "Acme Ltda" }
  },
  "meta": {
    "pageCount": 2,
    "processedAt": "2026-06-30T12:03:11.000Z"
  }
}

Ainda processando 409 Conflict

json
{
  "error": "Result not yet available",
  "status": "processing",
  "hint": "Aguarde a conclusão e consulte novamente, ou use um callbackUrl para ser notificado."
}

Listar documentos

GET/documents

Lista os documentos da sua organização com paginação por cursor. Use limit (padrão 20, máx. 100) e passe o nextCursor da resposta anterior no parâmetro cursor para buscar a próxima página. Você também pode filtrar por status.

bash
curl "https://api.kliper.ai/v1/documents?limit=20&status=success" \
  -H "Authorization: Bearer kp_live_a1b2c3d4e5f6..."

Resposta 200 OK

json
{
  "data": [
    {
      "id": "665f9a8b7c6d5e4f3a2b1c0d",
      "filename": "nota-fiscal.pdf",
      "status": "success",
      "documentType": "nota-fiscal",
      "pageCount": 2,
      "createdAt": "2026-06-30T12:00:00.000Z",
      "links": {
        "self": "https://api.kliper.ai/v1/documents/665f9a8b7c6d5e4f3a2b1c0d",
        "result": "https://api.kliper.ai/v1/documents/665f9a8b7c6d5e4f3a2b1c0d/result"
      }
    }
  ],
  "pagination": {
    "limit": 20,
    "hasMore": true,
    "nextCursor": "665f9a8b7c6d5e4f3a2b1c0d"
  }
}

Webhooks

Se você informar um callbackUrl no envio, o Kliper faz um POST para essa URL quando o documento chega a um status terminal — dispensando o polling. O corpo segue o mesmo envelope do resultado, com o metadata que você enviou ecoado de volta.

Corpo do webhook

json
{
  "schemaVersion": "1.0",
  "documentId": "665f9a8b7c6d5e4f3a2b1c0d",
  "documentType": "nota-fiscal",
  "status": "success",
  "data": {
    "numeroNota": "000.123.456",
    "valorTotal": 1540.90
  },
  "metadata": { "pedidoId": "abc-123" }
}

Verificar a assinatura

Cada webhook traz o header X-Kliper-Signature: sha256=<hmac>, um HMAC-SHA256 do corpo bruto usando o segredo do seu webhook. Compare-o com a assinatura que você calcula do lado do servidor antes de confiar no payload.

Esse segredo é exclusivo da sua organização — nenhum outro cliente Kliper usa o mesmo valor. Busque-o com GET /v1/webhook-secret (a primeira chamada já cria e devolve o segredo, se sua organização ainda não tiver um). Se ele for exposto, gere um novo com POST /v1/webhook-secret — o anterior deixa de valer imediatamente.

javascript
import crypto from 'crypto';

function verifyKliperWebhook(rawBody, signatureHeader, secret) {
  // signatureHeader = "sha256=<hmac>"
  const expected =
    'sha256=' +
    crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
  const a = Buffer.from(signatureHeader);
  const b = Buffer.from(expected);
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

// Express: use o corpo BRUTO, não o JSON já parseado.
app.post('/webhooks/kliper', express.raw({ type: '*/*' }), (req, res) => {
  const ok = verifyKliperWebhook(
    req.body,
    req.header('X-Kliper-Signature'),
    process.env.KLIPER_WEBHOOK_SECRET
  );
  if (!ok) return res.status(401).end();

  const event = JSON.parse(req.body.toString('utf8'));
  // ... processe event.data
  res.status(200).end();
});

Erros

Erros retornam um código HTTP apropriado e um corpo JSON com o campo error descrevendo o problema.

StatusSignificado
400Requisição malformada (JSON inválido, cursor inválido).
401Chave ausente, inválida ou revogada.
402Créditos insuficientes para processar o documento.
404Documento ou tipo de documento não encontrado.
409Resultado ainda não disponível (documento em processamento).
422Entrada inválida: arquivo faltando, fora do limite, ou tipo não detectado no modo auto.
429Rate limit excedido ou limite diário do sandbox atingido.
json
{ "error": "Document not found" }

Rate limits

Cada chave tem limite de 60 requisições por minuto, em janela deslizante. Requisições acima do limite retornam 429 Too Many Requests — aguarde alguns segundos e tente de novo, idealmente com backoff exponencial.

Chaves de sandbox (kp_test_) têm um limite adicional de 25 documentos a cada 24h. Ao atingi-lo, o envio retorna 429 até a janela renovar.

MCP — Model Context Protocol

O Kliper expõe um servidor MCP nativo para conectar assistentes de IA (Claude, Cursor e outros) diretamente à API. É um endpoint JSON-RPC 2.0 sobre HTTP — sem instalar nada. Aponte o cliente para https://api.kliper.ai/v1/mcp e autentique com a mesma chave Bearer da API.

POST/mcp

Em clientes que suportam MCP por HTTP, basta a URL e o header de autorização:

json
{
  "mcpServers": {
    "kliper": {
      "url": "https://api.kliper.ai/v1/mcp",
      "headers": {
        "Authorization": "Bearer kp_live_a1b2c3d4e5f6..."
      }
    }
  }
}

O servidor expõe quatro ferramentas, que usam exatamente os mesmos endpoints REST descritos acima:

FerramentaDescrição
list_document_typesLista os tipos de documento disponíveis.
submit_documentEnvia um PDF por URL (com documentType ou "auto").
get_document_statusConsulta o status de um documento pelo id.
get_document_resultBusca os dados extraídos de um documento.

Com isso, o assistente envia documentos, acompanha o status e busca resultados em linguagem natural. Detalhes de conexão também aparecem no painel, em Desenvolvedor.