> ## 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.

# Atualiza a posição de reprodução do assinante em uma novela

> Upsert por (assinante, novela) — equivalente ao `onConflict: "user_id,novel_id"` já usado pelo app oficial. Chamar de novo com o mesmo `novel_id` substitui a posição anterior; não acumula histórico — por isso repetir a chamada é seguro, sem precisar de header de idempotência (o mecanismo de `Idempotency-Key` chegou a ser proposto, mas não está implementado em nenhuma API Googa).



## OpenAPI

````yaml /novelaudio/openapi.yaml put /subscribers/{id}/playback-position
openapi: 3.1.0
info:
  title: Googa NovelAudio API
  version: 1.0.0
  summary: >-
    Catálogo em áudio, streaming de capítulo e posição de reprodução do
    NovelAudio. Vive no MESMO domínio e no MESMO backend físico do NovelAI —
    NovelAI e NovelAudio compartilham um único projeto Supabase ("Novel"), e
    esta API só existe como uma superfície de recursos diferente (áudio, não
    texto) dentro dele. Não existe `api.novelaudio.com.br`.
  description: >-
    Hoje o único cliente do NovelAudio é o próprio app oficial, falando
    diretamente com o Supabase do projeto "Novel" (PostgREST + Edge Functions +
    Storage). Esta especificação é o contrato para um parceiro (ex: uma
    operadora) embutir o player de áudio no próprio app ou puxar métricas de
    escuta sem acesso direto ao banco.

    Por que o domínio é `api.novelai.com.br` e não um domínio próprio: ver
    [Visão geral do NovelAudio](/novelaudio/overview) e [Modelo de autenticação
    sobre Supabase](/architecture/supabase-auth-model). Em resumo — NovelAI e
    NovelAudio são dois apps sobre o mesmo projeto Supabase; a Edge Function
    resolve por rota/recurso (texto vs. áudio), não por domínio, então um
    `api.novelaudio.com.br` separado bateria na mesma infraestrutura sem
    necessidade.

    Honestidade sobre o gap entre o prometido e o real (importante para quem for
    implementar contra este contrato): a proposta técnica original (RFP Livros
    Digitais 2026) promete narração neural com múltiplas vozes selecionáveis e
    streaming adaptativo HLS/DASH. O que existe hoje é bem mais modesto — ver a
    descrição de cada endpoint abaixo, e a seção "Como o áudio é produzido hoje"
    em [/novelaudio/overview](/novelaudio/overview).

    Esta especificação é um **contrato proposto, ainda não implementado** —
    nenhum destes endpoints existe em produção.

    Autenticação: o token de parceiro é emitido **uma única vez, pela Platform
    API** (`POST https://api.googa.com.br/v1/oauth2/token` — ver [Platform —
    OAuth2](/platform/reference/oauth2/troca-client-credentials-por-um-token-de-acesso-de-parceiro));
    nem o NovelAudio nem o NovelAI têm endpoint de token próprio. Este arquivo
    não repete essa operação; ele só declara os escopos `novelaudio:*` que
    também podem ser solicitados nessa mesma troca, ao lado dos escopos
    `novelai:*`. Um parceiro que integra catálogo de texto e áudio no mesmo
    cliente pede os dois conjuntos de escopo numa única chamada ao endpoint de
    token da Platform.
  contact:
    name: Googa — Suporte a parceiros
    email: developers@googa.com.br
  license:
    name: Uso restrito — ver Política de Uso da API
    url: https://developers.googa.com.br/security/api-usage-policy
servers:
  - url: https://api.novelai.com.br/v1
    description: >-
      Produção (proposto). Mesmo domínio e mesmo backend físico do NovelAI — NÃO
      é um domínio separado do NovelAudio. Roteamento por recurso, não por host.
  - url: https://sandbox.novelai.com.br/v1
    description: Sandbox (proposto) — dados fictícios, sem impacto em billing real.
security:
  - partnerOAuth2: []
tags:
  - name: Audio Metadata
    description: >-
      Metadados de áudio por novela e por capítulo — vozes, duração, status de
      renderização.
  - name: Streaming
    description: >-
      Emissão de URL de reprodução de um capítulo específico, com verificação de
      entitlement.
  - name: Playback
    description: Posição de reprodução do assinante, para retomar entre dispositivos.
  - name: Voices
    description: >-
      Catálogo de vozes de narração disponíveis. Hoje inteiramente Roadmap — ver
      descrição do endpoint.
paths:
  /subscribers/{id}/playback-position:
    put:
      tags:
        - Playback
      summary: Atualiza a posição de reprodução do assinante em uma novela
      description: >-
        Upsert por (assinante, novela) — equivalente ao `onConflict:
        "user_id,novel_id"` já usado pelo app oficial. Chamar de novo com o
        mesmo `novel_id` substitui a posição anterior; não acumula histórico —
        por isso repetir a chamada é seguro, sem precisar de header de
        idempotência (o mecanismo de `Idempotency-Key` chegou a ser proposto,
        mas não está implementado em nenhuma API Googa).
      operationId: setPlaybackPosition
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
          description: Identificador do assinante no sistema do parceiro.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PlaybackPositionUpdate'
      responses:
        '200':
          description: Posição gravada.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlaybackPosition'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
components:
  schemas:
    PlaybackPositionUpdate:
      type: object
      required:
        - novel_id
        - chapter_id
        - position_seconds
      properties:
        novel_id:
          type: string
        chapter_id:
          type: string
        position_seconds:
          type: integer
          minimum: 0
    PlaybackPosition:
      type: object
      properties:
        subscriber_id:
          type: string
        novel_id:
          type: string
        chapter_id:
          type: string
          description: >-
            Identificador do capítulo no formato do catálogo do player (ex.
            `t1-ch3`) — não é só o número do capítulo.
        position_seconds:
          type: integer
          minimum: 0
        updated_at:
          type: string
          format: date-time
    Error:
      type: object
      description: >-
        Mesmo formato de erro (estilo OAuth2, RFC 6749 §5.2) usado pela Platform
        API.
      properties:
        error:
          type: string
          example: invalid_request
        error_description:
          type: string
          example: Capítulo ainda não liberado pela cadência de drip
  responses:
    BadRequest:
      description: Corpo da requisição inválido.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Credenciais ausentes, inválidas ou expiradas.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    partnerOAuth2:
      type: oauth2
      description: >-
        Client credentials — emitido **uma única vez**, de forma centralizada,
        pela Platform API (`POST https://api.googa.com.br/v1/oauth2/token`, ver
        [Platform —
        OAuth2](/platform/reference/oauth2/troca-client-credentials-por-um-token-de-acesso-de-parceiro)).
        Este domínio (`api.novelai.com.br`, que também atende NovelAudio) só
        valida o token — via a chave pública do projeto Platform — nunca emite
        um token próprio. Este arquivo não redefine a operação de emissão, só
        declara os escopos `novelaudio:*` que também podem ser pedidos na mesma
        troca, ao lado dos `novelai:*`.
      flows:
        clientCredentials:
          tokenUrl: https://api.googa.com.br/v1/oauth2/token
          scopes:
            novelaudio:audio:read: Consultar metadados de áudio e emitir URLs de streaming
            novelaudio:playback:read: Consultar posição de reprodução
            novelaudio:playback:write: Atualizar posição de reprodução
            novelaudio:voices:read: >-
              Consultar o catálogo de vozes de narração (roadmap — ver `GET
              /voices`)

````