Pular para conteúdo

Beta

A API está em Beta — endpoints e contratos podem mudar. O conteúdo abaixo é a fonte única de verdade (GUIA_CONSUMO_API.md), incluído aqui automaticamente no build.

Guia de Consumo da API — Arkivu

Como consumir a plataforma apenas por chamadas de API, reproduzindo o que a interface faz.

Organização: a Parte 2 (Blocos) documenta cada capacidade uma única vez; a Parte 3 (Fluxos) apenas encadeia esses blocos. Sempre que um fluxo disparar uma operação assíncrona, ele aponta para o bloco Acompanhamento.

Status: todos os pontos foram confirmados contra o código.


1. Introdução

  • Base URL: https://api.arkivu.com.br/api
  • Autenticação: todas as chamadas exigem o header Authorization: Bearer <access_token>. Exceção: GET /filtros/ é público (sem token) — é o único endpoint do fluxo sem autenticação.
  • Padrão das operações longas: assíncrono — iniciar devolve um operationId, e o resultado é obtido por polling (ver bloco Acompanhamento). Os endpoints síncronos existem, mas não são o caminho recomendado para o consumidor.

2. Blocos de construção

2.1 Autenticação

Objetivo: obter e manter um access_token válido.

Ação Método + Endpoint Corpo Resposta
Login POST /auth/login/ { username, password } { access, refresh, user }
Renovar token POST /auth/token/refresh/ { refresh } { access }
Logout POST /auth/logout/ { refresh }

Observações: o access expira; ao receber 401, renove com o refresh e repita a chamada.


2.2 Certificados (pré-requisito de pesquisa)

Objetivo: ter um certificado digital cadastrado para autenticar perante a Receita.

Ação Método + Endpoint Parâmetros Resposta / extrair
Cadastrar POST /certificados/ (multipart/form-data) certificado (arquivo .pfx/.p12), password objeto com id (CNPJ extraído automaticamente)
Listar GET /certificados/ lista com id de cada certificado
Remover DELETE /certificados/{id}/

Saída-chave: certificate_id. RBAC: operator.


2.3 Filtros (descoberta de opções)

Objetivo: descobrir os ids válidos (sistema, tipo_arquivo, tipo_pesquisa) e os campos esperados em criterios. É a referência viva do que a plataforma suporta.

GET /api/filtros/público (sem token).

Retorna a estrutura hierárquica: sistemas → tipos → pesquisas → campos. Cada campo descreve id, nome, descricao, tipo (DATA / CNPJ / TEXTO / BOOLEANO / LISTA), obrigatorio, tamanhoMaximo?, opcoes? — ou seja, diz exatamente o que montar no criterios de cada pesquisa.

Sistemas suportados: SPED Contribuições, SPED Contábil, SPED ECF, SPED EFD-Reinf e SPED Fiscal (EFD ICMS IPI) — a resposta ao vivo é a fonte de verdade.

Ressalva (drift): esse catálogo é mantido à mão no backend e pode divergir do que a Receita oferece. Para o consumidor é a referência correta (é o que o backend aceita); o risco prático é uma pesquisa aceita aqui falhar no processamento se a Receita tiver mudado. É manutenção interna, não do integrador.


2.4 Pesquisa

Objetivo: disparar a busca dos documentos disponíveis.

POST /async/pesquisa/iniciar

Campo Obrigatório Origem do valor
certificate_id sim bloco Certificados (2.2)
profile_type sim CONTRIBUINTE ou PROCURADOR
target_type / target_doc PROCURADOR CPF/CNPJ e o documento alvo
identificador sim texto livre do consumidor (ex.: LOTE_2024_001)
sistema, tipo_arquivo, tipo_pesquisa sim bloco Filtros (2.3)
criterios sim campos da pesquisa escolhida em /filtros/ (cada campo com tipo/obrigatorio/opcoes)

Flag "últimos transmitidos": não é parâmetro da pesquisa manual — a plataforma aplica esse filtro client-side. Um consumidor de API que queira esse comportamento filtra o resultado por conta própria. O equivalente server-side existe apenas na consulta salva (campo apenasUltimoDocumento, ver 3.2).

Resposta: { operationId, status: "PENDING" }. Em seguida, Acompanhamento (2.6); o resultado traz a lista de arquivos encontrados. RBAC: operator.


2.5 Solicitação de documentos

Objetivo: colocar os arquivos encontrados na fila de download.

Na interface isso é implícito. Na API é uma chamada explícita.

POST /async/solicitacao/iniciar

Campo Obrigatório Origem do valor
arquivosSelecionados sim ids dos arquivos do resultado da pesquisa
arquivos_metadata sim metadados correspondentes do resultado da pesquisa

O pedido_id NÃO é enviado no request. Ele é o PedidoSped.id, gerado pela Receita, e retorna no resultado desta operação em resultado.pedido.id — é esse valor que alimenta o passo de ZIP (2.7).

Resposta: { operationId, status }. Em seguida, Acompanhamento (2.6) → resultado.pedido.id.


2.6 Acompanhamento (polling)

Objetivo: aguardar o término de qualquer operação assíncrona. Reutilizado por Pesquisa, Solicitação e Download.

GET /async/operacao/{operationId}/status

  • Repetir em intervalo fixo (sugestão: 5s) até um status terminal.
  • resultado só é preenchido em COMPLETED.
  • A resposta traz o identificador que você enviou no iniciar (útil para correlacionar a operação com o seu lote/pedido) e o consultaSalvaId quando a operação veio de uma consulta salva. Ambos são null quando não se aplicam.
  • Cancelar uma operação em andamento: POST /async/operacao/{operationId}/cancelar.
  • Listar operações do usuário: GET /async/operacoes (inclui as disparadas por uma consulta salva; também retorna identificador/consultaSalvaId em cada item).
Status Significado
PENDING registrada, não iniciada
QUEUED aguardando vaga (cota de agentes do plano excedida)
PROCESSING em execução
COMPLETED concluída — ver resultado
FAILED falhou — ver resultado
CANCELLED cancelada

2.7 Download

Objetivo: recuperar os arquivos já processados.

ZIP do pedido inteiro: POST /async/pedidos/{pedido_id}/zip/iniciarAcompanhamentoresultado.download_url. É uma URL assinada (presigned MinIO) que expira em ~1h. O pedido_id vem do resultado da Solicitação (2.5). Não é via /download/{id}/.

Arquivo individual: GET /download/{fila_id}/ → URL assinada. O fila_id é o FileSped.id ("ID SPED" do arquivo; o nome "fila" é legado). Você o obtém como documentos[].id em GET /pedidos/{pedido_id}/ (ou GET /pedidos/) — é o mesmo id usado em arquivosSelecionados/arquivos_metadata.

Alternativa: cada item de documentos[] já traz urlDownload e fileObjectId, então também dá para baixar via GET /files/{fileObjectId}/download.


3. Fluxos

Cada fluxo é só uma sequência de blocos. A coluna "passa/extrai" mostra o que liga um passo ao seguinte.

3.1 Consulta Manual

Objetivo: pesquisar, solicitar e baixar documentos sob demanda. Pré-requisito: certificado (2.2). RBAC: operator.

# Bloco Passa / extrai
1 Autenticação (2.1) obtém access_token
2 Certificados (2.2) obtém certificate_id
3 Filtros (2.3) ids válidos + estrutura do criterios
4 Pesquisa (2.4) envia critérios → recebe operationId
5 Acompanhamento (2.6) aguarda COMPLETED → extrai lista de arquivos
6 Solicitação (2.5) envia arquivosSelecionados + metadados → recebe operationId
7 Acompanhamento (2.6) aguarda COMPLETED → extrai resultado.pedido.id (= pedido_id)
8 Download → ZIP (2.7) dispara ZIP com pedido_idoperationId
9 Acompanhamento (2.6) aguarda COMPLETEDresultado.download_url → baixa

Variação Procurador: no passo 4, incluir target_type e target_doc.


3.2 Consulta salva

Objetivo: salvar um conjunto de consultas (template reutilizável) e executá-lo sob demanda com uma única chamada, sem precisar remontar os criterios a cada vez. Pré-requisito: certificado (2.2). RBAC: operator.

Anteriormente chamada de "automação (agendada)". O agendamento por cron foi descontinuado — a consulta salva é disparada sob demanda pelo consumidor.

# Bloco / Endpoint Observação
1 Autenticação (2.1)
2 Certificados (2.2) certificate_id
3 Filtros (2.3) ids para montar as consultas[]
4 POST /consultas-salvas/ corpo: nome, certificadoId, tipoCertificado, consultas[], ativa, apenasUltimoDocumento, dataCompartilhada?
5 POST /consultas-salvas/{id}/executar one-shot: pesquisa + solicitação automática por consulta; ver abaixo
6 Acompanhamento (2.6) operationIds de pesquisa; solicitações criadas automaticamente e descobríveis em GET /async/operacoes?tipo=SOLICITACAO

Execução one-shot — POST /consultas-salvas/{id}/executar:

  • Sem corpo: executa exatamente o que está salvo (incluindo apenasUltimoDocumento e data compartilhada).
  • Com corpo (overrides opcionais): dataInicio/dataFim sobrescrevem o período das consultas que exigem intervalo de datas; identificador e certificadoId ajustam a execução na hora.
  • Resposta: { consultaSalvaId, operationIds: [...], total, message }. Os operationIds correspondem às operações de pesquisa — uma por consulta do template.
  • Fluxo automático (one-shot): para cada pesquisa que retorna arquivos, o backend encadeia automaticamente via Celery uma solicitação de download (respeitando apenasUltimoDocumento). Nenhuma chamada adicional é necessária. As operações de solicitação aparecem em GET /async/operacoes?tipo=SOLICITACAO e podem ser acompanhadas normalmente pelo bloco Acompanhamento (2.6).
  • Arquivos prontos: quando todos os arquivos de um pedido estiverem no storage, eles aparecem em GET /pedidos/ com situacao: DISPONIVEL e podem ser baixados.

Gerenciamento: GET /consultas-salvas/, GET /consultas-salvas/{id}/, PUT /consultas-salvas/{id}/, DELETE /consultas-salvas/{id}/.


3.3 Download individual

Objetivo: baixar um arquivo específico, em vez do ZIP completo.

  1. GET /pedidos/{pedido_id}/ → lista documentos[], cada um com id (= fila_id), urlDownload e fileObjectId.
  2. GET /download/{fila_id}/ → URL assinada. (Ou use direto o urlDownload, ou GET /files/{fileObjectId}/download.)

3.4 Cancelamento

Objetivo: interromper uma operação em andamento.

POST /async/operacao/{operationId}/cancelar — válido enquanto o status for PENDING, QUEUED ou PROCESSING.


3.5 Notificação por webhook (opt-in)

Objetivo: receber um POST no seu sistema quando um pedido de download estiver totalmente disponível no storage.

Configuração

  1. No painel Configurações (ou via PATCH /tenant/me/ com o campo config.webhook_url), informe a URL de destino. Deve usar https:// e apontar para um IP público — URLs internas são bloqueadas.
  2. Um webhook_secret é gerado automaticamente ao salvar a primeira URL. Para rotacionar: POST /tenant/me/rotacionar-webhook-secret/ (resposta: { webhook_secret }).

Evento disparado

POST <webhook_url> quando todos os arquivos de um PedidoSped tiverem storage_path preenchido.

Payload:

{
  "event": "pedido.disponivel",
  "identificador": "meu-identificador",
  "pedido_id": 42,
  "situacao": "DISPONIVEL",
  "arquivos": [
    { "file_id": "160101543", "nome": "arquivo.txt", "storage_path": "tenant/.../arquivo.txt" }
  ]
}

Headers enviados:

Content-Type: application/json
X-Webhook-Signature: hmac-sha256=<hex>

Verificação da assinatura

import hmac, hashlib

def verificar_assinatura(body_bytes: bytes, header: str, secret: str) -> bool:
    expected = "hmac-sha256=" + hmac.new(
        secret.encode(), body_bytes, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, header)

Importante: compare com hmac.compare_digest para evitar timing attacks. Use o body bruto (bytes), antes de parsear o JSON.

Garantias

  • Disparo idempotente: um pedido só gera um evento, mesmo sob uploads paralelos.
  • Retry automático com backoff exponencial em falhas de rede ou respostas 5xx (até 5 tentativas).
  • Se webhook_url não estiver configurado, o pedido fica disponível normalmente — sem efeito.

4. Referência rápida

4.1 Status de operação

Ver tabela no bloco Acompanhamento (2.6).

4.2 Erros comuns

Código Causa provável Ação
401 token ausente/expirado renovar via token/refresh/
403 papel sem permissão revisar RBAC do fluxo
422 payload inválido conferir campos obrigatórios e ids (ver /filtros/)