{"openapi":"3.0.0","paths":{"/integracao/ia/v1/token":{"post":{"operationId":"ApiPublicaController_token","summary":"Troca a asserção assinada pela chave privada do integrador por um token de 10 minutos","description":"Padrão `private_key_jwt` (RFC 7523). O integrador assina um JWT curto com a chave privada dele (`iss` = `sub` = id do integrador, `aud` = a URL desta rota, `jti` único, `exp` ≤ 5 min) e manda aqui junto da serventia (`cns`) para a qual quer o token. Conferimos a assinatura pela chave PÚBLICA cadastrada, recusamos `jti` repetido e só devolvemos o token se aquela serventia tiver autorizado este integrador. Toda recusa responde a mesma frase: dizer o que falhou contaria a um desconhecido o que ele acertou.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrocarTokenDto"}}}},"responses":{"200":{"description":"{ access_token, token_type, expires_in, scope }"},"401":{"description":"Credencial de integração inválida."}},"tags":["API de integração"]}},"/integracao/ia/v1/naturezas":{"get":{"operationId":"ApiPublicaController_naturezas","summary":"O catálogo de naturezas e subnaturezas da serventia — para o de/para do seu lado","description":"A árvore de naturezas ATIVAS do cartório, com a mãe de cada uma. É por estes códigos que a análise é pedida: quem integra mantém, do seu lado, a correspondência entre o código dele e o daqui. Nós não guardamos essa tabela — e é de propósito: uma tradução mantida por nós seria uma segunda cópia do catálogo dele, desatualizando em silêncio. A UF não é parâmetro: ela sai da serventia do token, porque quem pergunta não deve escolher contra qual catálogo lê. `atualizadoEm` diz de quando é a leitura — releia periodicamente, porque o catálogo muda quando o cartório personaliza ou o estado publica natureza nova.","parameters":[],"responses":{"200":{"description":"{ uf, atualizadoEm, naturezas: [{ codigo, rotulo, naturezaMaeCodigo, especialidade, conteudoFinanceiroObrigatorio, posicoesJuridicasMinimas }] }"},"401":{"description":"Credencial de integração inválida."},"409":{"description":"A serventia ainda não tem UF configurada — nada a catalogar."}},"tags":["API de integração"],"security":[{"bearer":[]}]}},"/integracao/ia/v1/arquivos/preparar":{"post":{"operationId":"ApiPublicaController_prepararArquivo","summary":"PASSO 1 — pede a URL para mandar o arquivo DIRETO ao armazenamento","description":"O arquivo não passa por esta aplicação. Devolvemos uma autorização curta para UMA chave, e quem integra faz `PUT` direto na URL. É o que permite documento grande sem prender um processo que atende o balcão ao mesmo tempo — e sem esbarrar no tempo limite do gateway. Depois do `PUT`, chame `POST /arquivos/{id}/confirmar`. Preparar não gasta crédito; só a análise gasta.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrepararEnvioDto"}}}},"responses":{"200":{"description":"{ arquivoId, url, metodo, expiraEm, tetoBytes } — `url` nula só no ambiente de disco local"},"400":{"description":"Nome sem extensão, ou tamanho declarado acima do teto"},"401":{"description":"Credencial de integração inválida."}},"tags":["API de integração"],"security":[{"bearer":[]}]}},"/integracao/ia/v1/arquivos/{id}/confirmar":{"post":{"operationId":"ApiPublicaController_confirmarArquivo","summary":"PASSO 3 — confirma que o arquivo chegou, e só então ele existe","description":"Conferimos que o objeto chegou, qual o tamanho REAL (o declarado no preparo não é acreditado) e se os primeiros bytes são de um formato aceito. Arquivo recusado é apagado do armazenamento. Confirmar duas vezes devolve o mesmo arquivo — a repetição de uma chamada de rede é normal. Depois daqui a leitura do arquivo roda em segundo plano: se você cadastrou webhook, recebe `arquivo.pronto` quando ele puder ser analisado. Você NÃO precisa esperar por isso para pedir a análise — pedir cedo faz a análise nascer `aguardando_ocr` e começar sozinha.","parameters":[{"name":"id","required":true,"in":"path","description":"o `arquivoId` devolvido no preparo","schema":{"type":"string"}}],"responses":{"200":{"description":"{ arquivoId, nome, mime, tamanho, sha256 }"},"400":{"description":"Não chegou, chegou vazio, passou do teto, ou formato não aceito"},"404":{"description":"Envio não encontrado para esta serventia."}},"tags":["API de integração"],"security":[{"bearer":[]}]}},"/integracao/ia/v1/arquivos/{id}":{"get":{"operationId":"ApiPublicaController_estadoDoArquivo","summary":"Em que pé está a LEITURA do arquivo — se já dá para analisar","description":"A leitura acontece em segundo plano depois da confirmação, e demora mais que as chamadas do envio. Esta rota existe para quem quiser acompanhar: `pendente` (ainda lendo), `concluida` (pronta) ou `falhou`. VOCÊ NÃO PRECISA ESPERAR POR ELA para pedir a análise — pedir cedo faz a análise nascer `aguardando_ocr` e começar sozinha. Esta rota é para quem prefere ver o passo, e para entender o que houve quando algo dá errado.","parameters":[{"name":"id","required":true,"in":"path","description":"o `arquivoId` devolvido no preparo","schema":{"type":"string"}}],"responses":{"200":{"description":"{ arquivoId, nome, leitura, paginas, temAssinatura, assinaturas }"},"401":{"description":"Credencial de integração inválida."},"404":{"description":"Arquivo não encontrado para esta serventia."}},"tags":["API de integração"],"security":[{"bearer":[]}]}},"/integracao/ia/v1/analises":{"post":{"operationId":"ApiPublicaController_pedirAnalise","summary":"Pede a análise de um documento e devolve o id na hora (202)","description":"202, e não 200: o pedido foi ACEITO, não concluído. Guarde o `id` e consulte GET /integracao/ia/v1/analises/{id}, ou espere o webhook. O crédito é do CARTÓRIO e é separado agora — se não couber, a recusa vem nesta mesma resposta, e não depois da espera. DOCUMENTO: mande `arquivoId` OU `teor` (o texto já extraído do seu lado) — nunca os dois. NÃO ESPERE ANTES DE PEDIR: se a leitura do arquivo ainda não terminou, a análise nasce `aguardando_ocr` e entra na fila sozinha quando o texto fica pronto. REPETIR O MESMO PEDIDO NÃO CRIA OUTRA ANÁLISE: enquanto o mesmo arquivo estiver aguardando, na fila ou analisando, você recebe de volta a MESMA análise e o mesmo id, sem custo novo. ESTA ROTA NÃO REGISTRA, NÃO SELA E NÃO LAVRA.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PedirAnalisePelaApiDto"}}}},"responses":{"202":{"description":"Pedido aceito. GUARDE o `id` (UUID completo: 36 caracteres, formato 8-4-4-4-12) e use-o inteiro em GET analises/{id}, ou espere o webhook.","content":{"application/json":{"schema":{"example":{"id":"3fa85f64-5717-4562-b3fc-2c963f66afa6","situacao":"na_fila","criadoEm":"2026-10-13T14:25:00.000Z"}}}}},"403":{"description":"Teto de gasto diário desta serventia já alcançado."},"404":{"description":"Documento não encontrado."}},"tags":["API de integração"],"security":[{"bearer":[]}]},"get":{"operationId":"ApiPublicaController_reconciliar","summary":"O que mudou desde a última leitura — a reconciliação sem webhook","description":"A análise roda em segundo plano. Se você cadastrou webhook, o aviso chega sozinho; se não cadastrou, ou se perdeu algum, é por aqui que se reconcilia. Guarde o `atualizadoAte` da resposta e mande-o como `desde` na próxima chamada: nada escapa e você lê só o que mudou. NÃO pagine por posição — item concluído entre duas páginas escorrega entre elas, e ninguém percebe. Só aparecem as análises PEDIDAS POR VOCÊ: as que o cartório fez pela tela são dele.","parameters":[{"name":"desde","required":false,"in":"query","description":"o `atualizadoAte` que você recebeu da última vez (ISO 8601). Ausente = desde o começo.","schema":{"type":"string"}},{"name":"situacao","required":false,"in":"query","description":"na_fila | analisando | pronta | falhou","schema":{"type":"string"}},{"name":"limite","required":false,"in":"query","description":"1 a 200 · padrão 50","schema":{"type":"string"}}],"responses":{"200":{"description":"{ analises: [...], atualizadoAte, temMais } — `temMais` true significa chamar de novo com o `atualizadoAte` devolvido, sem esperar."},"401":{"description":"Credencial de integração inválida."}},"tags":["API de integração"],"security":[{"bearer":[]}]}},"/integracao/ia/v1/analises/{id}":{"get":{"operationId":"ApiPublicaController_obterAnalise","summary":"Em que pé está a análise, e o resultado quando ela estiver pronta","description":"Enquanto a situação for `na_fila` ou `analisando`, ainda não há resultado — NÃO é erro, e repetir o pedido custaria outro crédito. Quando for `pronta`, vem junto a ficha extraída, os achados e o checklist respondido.","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"O pedido e, quando pronta, o resultado inteiro."},"400":{"description":"O id não é um UUID válido (ex.: truncado na cópia). Use o id completo devolvido ao criar a análise."},"404":{"description":"Análise não encontrada para esta serventia."}},"tags":["API de integração"],"security":[{"bearer":[]}]}}},"info":{"title":"API de análise de documentos por IA","description":"A porta para os cartórios que mantêm o sistema que já têm e contratam apenas a análise de documentos por IA. O integrador assina uma asserção com a chave privada dele, troca por um token curto, sobe o documento DIRETO ao armazenamento e pede a análise — recebendo o resultado por aviso (webhook) ou por consulta. Esta API não registra, não sela e não lavra. O guia passo a passo está em /integracao/ia/v1/guia.","version":"1","contact":{}},"tags":[],"servers":[],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"JWT","type":"http","description":"O token devolvido por POST /integracao/ia/v1/token. Vale 10 minutos."}},"schemas":{"TrocarTokenDto":{"type":"object","properties":{"client_assertion":{"type":"string","description":"o JWT assinado com a chave privada do integrador"},"cns":{"type":"string","description":"O IDENTIFICADOR da serventia — um uuid, NÃO o número do CNS. Ele está no Console Nacional, no botão \"Credenciais\" da ficha do cartório ou da empresa, como \"identificador da serventia\". O nome do campo é herança e será trocado para `serventiaId`.","example":"8c2b1d40-5f3e-4a7b-9c61-2e8f4a9d3b70"}},"required":["client_assertion","cns"]},"PrepararEnvioDto":{"type":"object","properties":{"nome":{"type":"string","example":"contrato-locacao.pdf","description":"Com extensão — é dela que sai o primeiro sinal do formato, e sem ela o preparo é recusado."},"tamanho":{"type":"number","example":4718592,"description":"Tamanho em bytes, se souber. Declarar permite a recusa antes da transferência."}},"required":["nome"]},"PedirAnalisePelaApiDto":{"type":"object","properties":{"arquivoId":{"description":"O `arquivoId` devolvido no preparo e confirmado. Obrigatório, A MENOS que você mande `teor`. Pode ser UM id (string) ou uma LISTA de ids (array) — nesse caso TODOS os documentos entram juntos na MESMA análise (o primeiro é o principal, os demais são complementares), como no exame do balcão. Se a leitura de algum arquivo ainda não terminou, a análise entra como `aguardando_ocr` e começa sozinha — você não precisa esperar antes de pedir.","oneOf":[{"type":"string","example":"1a2b3c4d-..."},{"type":"array","items":{"type":"string"},"example":["1a2b...","5e6f..."]}]},"anexoId":{"deprecated":true,"description":"Alias de `arquivoId`, mantido por compatibilidade. Prefira `arquivoId`.","oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"teor":{"type":"string","description":"O texto do documento, já extraído por você — alternativa a `arquivoId`, não complemento. Quem manda o teor não sobe arquivo e não espera leitura. A resposta marca `origemDoTeor: \"informado\"`: a análise passa a ser sobre o que você afirmou, não sobre o papel.","maxLength":1000000},"nomeDoDocumento":{"type":"string","description":"Como chamar esta análise na lista do cartório, quando não há arquivo com nome."},"especieAto":{"type":"string","example":"registro_integral","description":"A espécie do ATO pretendido. Código desconhecido é recusado com a lista dos válidos."},"naturezaCodigo":{"type":"string","example":"LOCACAO_PREDIO_COMERCIAL","description":"O código da natureza NO NOSSO catálogo — consulte GET /integracao/ia/v1/naturezas. É você quem mantém a correspondência com o código do seu sistema. Código que o catálogo desta serventia não conhece é recusado: aceitá-lo faria a análise rodar com a lista geral do estado e devolver um parecer completo e cego para o que aquela natureza exige. Sem o campo, vale a lista geral — e a resposta diz isso."}},"required":["especieAto"]}}}}