Changelog

Um registro público das mudanças da API. Mudanças aditivas e compatíveis com versões anteriores (novos campos opcionais); mudanças incompatíveis são sinalizadas explicitamente — as integrações existentes continuam funcionando sem alterações.

2026-07-28 — Renomeado para ChunkChef

O produto agora se chama ChunkChef. Três mudanças são visíveis no protocolo; o resto é interno.

  • Quebra — cabeçalhos de assinatura de webhook renomeados. X-Hotdoc-Timestamp e X-Hotdoc-Signature passam a ser X-Chunkchef-Timestamp e X-Chunkchef-Signature. O esquema de assinatura não muda; apenas os nomes dos cabeçalhos. Atualize a sua verificação.
  • Quebra — o prefixo da chave de API mudou. Novas chaves são emitidas como chunkchef_<id>.<secret> em vez de hotdoc_<id>.<secret>. As chaves existentes deixam de autenticar; gere uma nova no painel.
  • Quebra — o discriminador de erro tipado mudou. Dentro de Status.details, @type agora é type.googleapis.com/chunkchef.v1.billing.QuotaExceededDetail. Se você compara com essa string, atualize-a.

Endpoints, formatos de requisição e resposta e os domínios hotdoc.io / api.hotdoc.io permanecem inalterados.

2026-07-28 — Especificação OpenAPI

  • Especificação legível por máquina publicada em /openapi.yaml — OpenAPI 3.0.3, gerada a partir das definições protobuf do serviço e cobrindo as cinco operações públicas de Jobs (POST /v1/jobs/upload, POST /v1/jobs, GET /v1/jobs/{id}, GET /v1/jobs/{id}/result, GET /v1/jobs). Passe o arquivo para qualquer gerador compatível com OpenAPI para construir um cliente; esta referência escrita à mão continua sendo a documentação em prosa.
  • Mudança de comportamento — o tamanho de página de GET /v1/jobs agora é limitado. pageSize vale 50 por padrão e é limitado a 200. Antes, uma chamada que omitia pageSize devolvia todo o histórico de trabalhos em uma única resposta. Se você dependia disso, percorra as páginas com pageToken.
  • Mudança de comportamento — um pageToken que não resolve mais devolve 400. Antes esse token reiniciava a listagem a partir da primeira página sem nenhum sinal, o que podia lhe entregar registros já vistos. Trate o 400 como “o cursor não se aplica mais, recomece sem pageToken”.
  • Corrigido — percorrer GET /v1/jobs por páginas não pula nem repete mais trabalhos. O cursor se ancorava em uma coluna diferente daquela pela qual a lista era ordenada, de modo que uma listagem de várias páginas podia perder alguns trabalhos e devolver outros duas vezes.

2026-07-24 — Confiança por consenso (k-consensus)

  • Novo campo consensus (opcional) em POST /v1/jobs — opcional, requer responseSchema (senão rejeitado com 400). consensus.mode define o número de execuções: CONSENSUS_MODE_TWO_RUNS (2, uma sondagem de instabilidade), CONSENSUS_MODE_THREE_RUNS (3, recomendado) ou CONSENSUS_MODE_FIVE_RUNS (5, escrutínio máximo). O hotdoc executa cada chunk k vezes com a sua chave e vota campo a campo (por pluralidade) na resposta.
  • Novo campo de resultado llm[].consensusk, runsVotable, minAgreement, incomplete e disagreements[] (variants[] concorrentes com a contagem de execuções e se cada uma included — venceu a votação). Permite ver em quais campos o modelo foi estável e em quais hesitou, ao custo de k vezes os tokens na sua chave. Veja “Execuções de consenso” na documentação do Job API.

2026-07-15 — Mesclagem de chunks

  • Novo campo merge (opcional) em POST /v1/jobs — mesclagem opcional no servidor das respostas do modelo por chunk em um único resultado para o documento inteiro. merge.scope escolhe mesclagem por arquivo (MERGE_SCOPE_FILE, padrão) ou por todo o job (MERGE_SCOPE_JOB); merge.conflictPolicy decide como valores de campo conflitantes são resolvidos (MERGE_CONFLICT_POLICY_FIRST_NON_NULL, padrão, ou MERGE_CONFLICT_POLICY_MAJORITY); merge.dedupeBy ativa a deduplicação de conteúdo entre arquivos por nomes de campo JSON (apenas JSON + responseSchema; vazio mantém o padrão seguro, só deduplicação técnica).
  • Novo campo de resultado merged[] — uma entrada por arquivo (ou uma por job em scope=job) com o content combinado, schemaValid (quando responseSchema foi definido), conflicts[], os contadores dedupeRemovedTechnical/dedupeRemovedContent, e mergeIncomplete/incompleteChunks quando um chunk não pôde ser mesclado com segurança. As linhas llm[] por chunk existentes permanecem inalteradas e disponíveis. Isso fecha a nota pendente “o serviço continua não mesclando os chunks” de 2026-06-24 — a mesclagem agora está disponível, é opcional e desativada por padrão. Veja “Mesclagem de resultados em chunks” na documentação do Job API.

2026-07-14 — Saída estruturada (JSON Schema)

  • Novo campo responseSchema (opcional) em POST /v1/jobs — um JSON Schema autocontido (string bruta; apenas #/$defs internos, ≤128 KiB, profundidade ≤64, ≤10000 nós) contra o qual o hotdoc valida a resposta JSON do modelo. Para OpenAI/Grok precisa ser compatível com o subconjunto estrito (toda propriedade em required, opcionalidade via type: [..., "null"], additionalProperties: false); um schema escrito nesse subconjunto funciona sem alterações em todos os provedores. Um schema inválido é rejeitado com 400 na criação do job.
  • Novos campos de resultado llm[].schemaValid / llm[].schemaErrors — reportados apenas para arquivos de um único chunk. Uma resposta não conforme ainda é retornada em content, mas o job termina como JOB_STATUS_PARTIAL em vez de JOB_STATUS_COMPLETE. Provedores para os quais o hotdoc emula saídas estruturadas (DeepSeek, Xiaomi) recebem uma tentativa automática de reparo antes da avaliação.

2026-07-09 — Modo de extração

  • Novo campo extractionMode (opcional) em POST /v1/jobsEXTRACTION_MODE_HYBRID (Extração híbrida otimizada, o padrão) deixa o conversor decidir por arquivo entre extrair texto diretamente ou usar OCR; EXTRACTION_MODE_OCR_ALWAYS força OCR neural em todos os arquivos. Além disso, um novo padrão em nível de conta, configurável no painel em Configurações, usado quando um job omite extractionMode.

2026-07-08 — Playground público

  • /playground no site — experimente o hotdoc sem se cadastrar: envie um arquivo, rode um prompt pronto e veja o resultado direto no navegador.
  • Novos endpoints de demo anônimos, /v1/demo/*: enviar um arquivo, criar um job de demo, consultar seu resultado e reivindicá-lo em uma conta real após o cadastro. As sessões são rastreadas por um cookie (sem login) e limitadas a 3 execuções por sessão mais um orçamento diário compartilhado entre todos os visitantes anônimos; os resultados são truncados. Isso é aditivo — a API autenticada /v1/jobs não muda.

2026-06-30 — OCR multiprovedor (BYOK)

Incompatível. O estágio de OCR agora recebe ocr.{provider, model, providerKey} (era ocr.mistralApiKey). Escolha qualquer provedor suportado — o Mistral é o padrão (mistral-ocr-latest). O model é obrigatório. Novos marcadores de erro de OCR (provider_auth_failed, provider_key_required, rate_limited, ocr_timeout, ocr_backend_*, too_many_pages) substituem mistral_key_required.

2026-06-26 — Chaves de idempotência

POST /v1/jobs aceita idempotencyKey. Repetir com a mesma chave e parâmetros idênticos retorna o job original; a mesma chave com parâmetros diferentes retorna 400.

2026-06-24 — webhooks de conclusão de job

  • Novos campos webhookUrl e webhookSecret (ambos opcionais) na criação do job. webhookUrl é um endpoint http/https absoluto; o serviço faz um POST nele uma única vez, com um corpo JSON (job_id, account_id, status, finished_at), quando o job atinge um status terminal. webhookSecret é um segredo HMAC: quando definido, cada requisição inclui os cabeçalhos X-Hotdoc-Timestamp e X-Hotdoc-Signature (sha256=hex(hmac_sha256(secret, "<ts>.<body>"))). Ambos os campos são aceitos apenas como entrada e nunca aparecem nas respostas. Política de retentativas: até 6 tentativas com atrasos de 1 m / 5 m / 15 m / 30 m / 30 m. Veja “Webhooks” para detalhes.

2026-06-24 — chunking consciente da estrutura e tamanho de chunk configurável

  • Chunking de texto consciente da estrutura. O texto reconhecido longo agora é cortado ao longo dos limites da estrutura do seu formato (Markdown / HTML / XML / plain): as tabelas não são rasgadas no meio de uma linha (o cabeçalho de uma tabela é repetido em cada chunk), e o contexto dos títulos de seção é preservado. O comportamento anterior (chunks como linhas llm[] separadas, identificadas por chunkIndex / chunkTotal) permanece inalterado — o serviço continua não mesclando os chunks.
  • Novo campo neural.chunkBudgetTokens (opcional) na criação do job — orçamento de tokens por chunk para a janela de contexto do seu modelo; faixa 160002000000, com padrão no valor conservador do serviço. A resposta ecoa o orçamento efetivo real.
  • Novo campo ocr[].outputFormat no resultado do job — o formato do texto reconhecido (markdown / html / xml / plain).