> ## Documentation Index
> Fetch the complete documentation index at: https://developers.googa.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# NovelAI API — visão geral

> Catálogo, capítulos liberados pelo drip diário, progresso de leitura e finais ramificados — a API específica de produto do NovelAI.

<Info>
  Hoje o catálogo, os capítulos e o progresso de leitura do NovelAI são consumidos diretamente
  pelo app oficial (Web/PWA — não há apps nativos) contra o projeto Supabase "Novel", via Row Level Security.
  Esta página e a [Referência de API](/novelai/reference) descrevem o contrato para um sistema
  terceiro ler esses dados sem acesso direto ao banco.
</Info>

A API do NovelAI é específica de produto: catálogo, capítulos, progresso de leitura e finais.
Ela **não** repete Entitlements, Billing ou SSO — isso é resolvido uma única vez pela
[Platform API](/platform/overview), comum a todos os produtos Googa. Um parceiro integrando o
NovelAI usa a Platform API para saber *quem pode acessar* e *quanto cobrar*, e a API descrita
aqui para saber *o que o assinante está lendo*.

## O modelo de conteúdo

Cada novela é uma série fechada de **7 capítulos de conteúdo**, e cada capítulo tem **7 páginas
de leitura** liberadas juntas — o drip controla o capítulo, não a página. O desfecho é um
**capítulo final próprio** (o 8º em `novel_chapters`, só metadado — a tela de escolha de final,
sem páginas de conteúdo), liberado **no mesmo dia** em que o 7º capítulo libera — o leitor não
espera um dia a mais pelo final. `novel_pages` guarda o conteúdo com granularidade de página
(`chapter_number` + `page_in_chapter`) e `novel_chapters` guarda o metadado por capítulo (título,
duração estimada) usado tanto pelo menu de leitura quanto pelo player de áudio do NovelAudio.

<Steps>
  <Step title="1 capítulo por dia, a partir do primeiro acesso">
    O relógio do drip começa a contar quando o assinante abre a novela pela primeira vez — não
    na publicação da obra. A partir daí, um novo capítulo (7 páginas) libera a cada 06:00
    (horário de Brasília). Isso é calculado sob demanda por uma função no banco
    (`unlocked_chapter_count`), não é um valor armazenado — não existe uma coluna "capítulos
    liberados" que possa ficar desatualizada, porque ela nunca existiu; o número é recalculado a
    cada leitura.
  </Step>

  <Step title="Plano com early access lê 1 capítulo adiantado">
    Um assinante em qualquer plano com o benefício "acesso antecipado" (vendido hoje só no plano
    VIP do NovelAudio, mas o mecanismo é do NovelAI) enxerga o capítulo seguinte um dia antes dos
    demais — a mesma função de drip soma 1 ao resultado quando detecta esse benefício ativo.
  </Step>

  <Step title="Capítulo final (o 8º) libera no mesmo dia do 7º, com até 4 finais">
    Os finais (`novel_choices`) vivem em um capítulo final próprio, sem conteúdo de páginas — só
    a escolha de desfecho — liberado junto com o 7º capítulo, no mesmo dia. Eles só ficam
    visíveis — mesmo para o próprio assinante — quando esse capítulo libera. A API de parceiro
    reproduz exatamente essa regra: `GET /novels/{id}/choices` devolve `available: false` até lá.
  </Step>

  <Step title="Limite de 3 novelas ativas por assinante">
    Um leitor não pode manter mais de 3 novelas simultaneamente em andamento (não finalizadas) —
    aplicado no servidor, não é uma regra só de UI. Terminar uma novela (escolher um final) ou
    removê-la de "Continuar lendo" libera a vaga.
  </Step>
</Steps>

Nenhuma dessas regras muda para o parceiro: a API não oferece um jeito de "pular a fila" ou ver
um capítulo antes da hora para um assinante que não tem o benefício — o parceiro vê exatamente o
que o assinante veria no app oficial, no mesmo instante. Uma nota de honestidade: existem
mecanismos internos, do lado do servidor, que liberam o catálogo inteiro para fins de demonstração
e teste (modo demo do ambiente, contas internas de teste e liberações pontuais por obra) — eles
não são expostos por esta API nem contratáveis por parceiro; citamos para que "não há bypass"
não seja lido como "não existe nenhum mecanismo de bypass no sistema".

## Recursos

<CardGroup cols={2}>
  <Card title="Catálogo" icon="books">
    `GET /categories`, `GET /novels`, `GET /novels/{id}` — metadados de catálogo: título,
    sinopse, categoria, tags editoriais, contagem de capítulos e se existe edição em áudio.
  </Card>

  <Card title="Capítulos" icon="book-open">
    `GET /novels/{id}/chapters` — metadado editorial de cada capítulo e, com `subscriber_id`, o
    estado de liberação (drip) daquele assinante especificamente.
  </Card>

  <Card title="Progresso de leitura" icon="bookmark">
    `GET /subscriber/{id}/reading-progress` — capítulo atual, capítulos liberados e novelas em
    andamento de um assinante, respeitando o limite de 3 ativas.
  </Card>

  <Card title="Finais" icon="git-branch">
    `GET /novels/{id}/choices` — os até 4 desfechos de uma novela, só quando o drip já liberou o
    último capítulo para aquele assinante.
  </Card>

  <Card title="Analytics agregado" icon="chart-line">
    `GET /analytics/engagement` — leitores ativos, taxa de conclusão e distribuição de finais
    escolhidos, sempre agregado por parceiro/período. Depende de `partner_id` por leitor — ver a
    [Referência de API](/novelai/reference) para o pré-requisito.
  </Card>

  <Card title="Webhook: novela concluída" icon="webhook">
    `novel.finished` dispara quando um assinante escolhe um final. Não existe (e não é trivial de
    construir) um webhook de "capítulo liberado" — o drip é calculado, não é uma escrita; ver a
    nota na Referência de API.
  </Card>
</CardGroup>

<Warning>
  **Lacuna conhecida — capas do catálogo.** `NovelSummary.cover_image_url` está desenhado no
  contrato, mas hoje sempre retorna `null`: as \~112 capas do catálogo são assets estáticos
  embutidos no build do app oficial (`src/data/covers.ts`), não arquivos servidos por um bucket
  ou CDN. Um parceiro que queira renderizar o catálogo com capas reais (o caso de uso mais
  provável desta API) precisa que isso seja resolvido primeiro — migrar as capas para o Supabase
  Storage (ou um CDN próprio) é um pré-requisito não desenhado ainda, não apenas um campo
  pendente de implementação.
</Warning>

## Autenticação

Toda chamada de servidor-a-servidor usa OAuth2 **client credentials**, com escopos próprios do
NovelAI (`novelai:catalog:read`, `novelai:chapters:read`, `novelai:progress:read`,
`novelai:choices:read`, `novelai:analytics:read`) — mas o token é emitido **uma única vez**, de
forma centralizada, pela Platform API (`POST https://api.googa.com.br/v1/oauth2/token`), com
esses mesmos escopos incluídos na mesma troca. Este domínio (`api.novelai.com.br`) só valida o
token — via a chave pública do projeto Platform — nunca emite um token próprio; isso evita
duplicar a verificação de credenciais em três projetos Supabase diferentes. Ver [Modelo de
autenticação sobre Supabase](/architecture/supabase-auth-model) para o desenho completo do
Partner Gateway e do roteamento cross-projeto.

Para o caso mais simples e de menor risco — leitura pública de catálogo, sem dado de nenhum
assinante — está **planejada** (ainda não suportada: nenhum endpoint verifica esse header hoje)
uma alternativa de API key estática (`X-Googa-Api-Key`), restrita ao escopo
`novelai:catalog:read`.

## Domínio

```
https://api.novelai.com.br/v1
```

Este é o mesmo domínio/backend que atende o NovelAudio (os dois produtos compartilham o projeto
Supabase "Novel") — a Edge Function resolve o recurso pela rota, não pelo domínio. Os recursos
específicos de áudio (streaming, posição de reprodução)
estão documentados na aba [NovelAudio](/novelaudio/overview), não aqui, ainda que fisicamente
sejam a mesma API. Ver [Os três produtos, uma superfície de API](/index#os-três-produtos-uma-superfície-de-api)
para o panorama completo dos três domínios (`api.googa.com.br`, `api.novelai.com.br`,
`api.historinhai.com.br`).
