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/v1Base URL · Sandbox
https://api-sandbox.kliper.ai/v1Rate limit
60 req/min por chaveIntroduçã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 é:
- 1POST o documento para
/documents→ recebe oide o statusqueued. - 2GET
/documents/{id}até o status virarsuccessourequires_review. - 3GET
/documents/{id}/resultpara 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:
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
/document-typesLista 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.
curl https://api.kliper.ai/v1/document-types \
-H "Authorization: Bearer kp_live_a1b2c3d4e5f6..."Resposta 200 OK
{
"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
/documentsAceita 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.
| Campo | Tipo | Descrição |
|---|---|---|
| file | arquivo | PDF a processar (modo multipart). |
| url | string | URL https pública para o PDF (modo JSON, alternativa ao file). |
| documentType * | string | Slug do tipo (ex.: nota-fiscal) ou "auto". |
| callbackUrl | string | URL https para receber o webhook ao finalizar (opcional). |
| metadata | objeto | Metadados livres, devolvidos no webhook (opcional). |
Requisição
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
{
"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:
{
"error": "Could not automatically detect the document type. Please specify documentType.",
"documentTypes": "https://api.kliper.ai/v1/document-types"
}Consultar status
/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).
curl https://api.kliper.ai/v1/documents/665f9a8b7c6d5e4f3a2b1c0d \
-H "Authorization: Bearer kp_live_a1b2c3d4e5f6..."Resposta 200 OK
{
"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
/documents/{id}/resultDisponí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).
curl https://api.kliper.ai/v1/documents/665f9a8b7c6d5e4f3a2b1c0d/result \
-H "Authorization: Bearer kp_live_a1b2c3d4e5f6..."Resposta 200 OK
{
"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
{
"error": "Result not yet available",
"status": "processing",
"hint": "Aguarde a conclusão e consulte novamente, ou use um callbackUrl para ser notificado."
}Listar documentos
/documentsLista 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.
curl "https://api.kliper.ai/v1/documents?limit=20&status=success" \
-H "Authorization: Bearer kp_live_a1b2c3d4e5f6..."Resposta 200 OK
{
"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
{
"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.
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.
| Status | Significado |
|---|---|
| 400 | Requisição malformada (JSON inválido, cursor inválido). |
| 401 | Chave ausente, inválida ou revogada. |
| 402 | Créditos insuficientes para processar o documento. |
| 404 | Documento ou tipo de documento não encontrado. |
| 409 | Resultado ainda não disponível (documento em processamento). |
| 422 | Entrada inválida: arquivo faltando, fora do limite, ou tipo não detectado no modo auto. |
| 429 | Rate limit excedido ou limite diário do sandbox atingido. |
{ "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.
/mcpEm clientes que suportam MCP por HTTP, basta a URL e o header de autorização:
{
"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:
| Ferramenta | Descrição |
|---|---|
| list_document_types | Lista os tipos de documento disponíveis. |
| submit_document | Envia um PDF por URL (com documentType ou "auto"). |
| get_document_status | Consulta o status de um documento pelo id. |
| get_document_result | Busca 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.