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

# Listar respostas do Flow

> Os formulários que os clientes enviaram para UM Flow, os mais novos primeiro. O Flow é resolvido primeiro dentro da WABA da própria chave, e essa resolução é a única coisa que escopa o resto — um Flow de outra WABA (inclusive outra WABA do mesmo tenant) responde 404 e nenhuma resposta chega a ser lida.

Respostas fora da janela de retenção são excluídas AQUI, não só pela tarefa de poda, para que ninguém leia um envio que a janela publicada diz ter sumido. `contactPhone` vem `null` quando o telefone já não é nosso para publicar. `externalMessageId` é o `wamid` da Meta e é NOMEADO como id de provedor de propósito — todo outro id desta superfície é local.

`notice: "FLOW_RESPONSES_WINDOW_TRUNCATED"` aparece na página quando o Flow cunhou mais envios do que uma requisição correlaciona (teto de 10.000 sessões). Uma resposta curta que não diz que é curta é o que faz o cliente concluir que perdeu envios. Permissão `flows:read`.

**Exige chave com escopo de número.** Uma chave de tenant precisa nomear o número no header `x-whatsapp-number-id`, senão recebe 403 `TENANT_SCOPE_NOT_ALLOWED`.

`media[]` leva os arquivos que a pessoa ANEXOU dentro do formulário (`PhotoPicker` / `DocumentPicker`). Eles NÃO estão em `response`: um picker exige `data_exchange`, portanto as referências chegam no pedido que o nosso endpoint decifra — uma troca HTTP diferente do `nfm_reply` que produziu a linha — e este array é a cópia re-hospedada, ligada pelo `flowToken`. É o único lugar onde um chamador alcança os bytes: a Meta apaga o original após 20 dias. É SEMPRE um array, `[]` quando nada foi anexado. `url` é um link estável nosso e está presente assim que a linha existe, INCLUSIVE enquanto `status` for `"PENDING"`. Buscá-lo antes de a re-hospedagem terminar não dá 404: a rota segura o pedido enquanto espera pelo arquivo e então o serve, toda busca posterior é um redirect, e uma espera que estoura responde 404 com o cabeçalho `Retry-After`. O valor não muda depois de os bytes chegarem, portanto é seguro guardá-lo logo na chegada, e o `status` (`PENDING`/`STORED`/`FAILED`) continua sendo como o chamador sabe se eles chegaram. É a ordem que justifica esse link: o evento é emitido assim que o envio é guardado e a re-hospedagem roda depois dele, portanto o anúncio precede normalmente os bytes. `url` só é nulo quando a instalação não tem segredo de assinatura configurado (aí volta ao comportamento antigo, a URL direta do objeto assim que ficar `STORED`), quando a Meta não enviou `media_id` para assinar uma identidade em cima, ou num número `RELAY_ONLY` onde nada foi guardado — nunca apenas porque a transferência ainda não terminou. Trate-o como opaco: busque, nunca construa um. `mimeType` é farejado dos bytes decifrados e nunca do nome do arquivo, e ele e `sizeBytes` são `null` até o arquivo ficar guardado. Nem `cdn_url` nem material de cifra são alguma vez publicados.

`submitted[]` é o que a pessoa de fato ESCREVEU, tela a tela. ⛔ Num Flow `data_exchange` é o ÚNICO lugar onde essas respostas existem: ali o `response` é o `nfm_reply` da Meta, um envelope que leva o `flow_token` e mais nada — quem abre o `response` num Flow desses encontra uma sala vazia e conclui que o envio se perdeu. Num Flow SIMPLES, sem endpoint, as respostas CHEGAM no `response` e o `submitted` vem `[]`.

Cada entrada é um pedido `data_exchange` que a META NOS ENVIOU: `screen` (a tela em que a pessoa estava, ou `null`), `at` (ISO 8601), `data` (o objeto já parseado) e `omitted`. Nunca é o que o SEU endpoint respondeu — o `extension_message_response` não é publicado em lugar nenhum do Pilot Status. E só as trocas `data_exchange` são capturadas: o `INIT` devolve o estado que NÓS semeamos quando o Flow foi enviado, e o `BACK` é navegação, portanto esta lista é legitimamente MAIS CURTA do que o tráfego que o seu próprio endpoint viu. Essa diferença não é perda.

NESTE endpoint o `submitted` é sempre um array e nunca `null` — `[]` tanto quando não há nada como quando o número não guarda conteúdo de cliente, porque "nada foi capturado" e "não conseguimos olhar" seriam senão o mesmo valor. (No webhook `flow.response_received` é o contrário, `null` e nunca `[]`, porque lá o redator só apaga um campo que tenha algo dentro.) Nada é truncado em silêncio: ou a entrada leva `data` com `omitted: null`, ou leva `data: null` e diz o PORQUÊ. `DATA_TOO_LARGE` é uma troca grande demais, que mantém a linha e o lugar dela na sequência — o teto que ela passou conta-se em BYTES, não em caracteres, portanto texto com acentos chega lá antes do que o comprimento sugere. `LIMIT_REACHED` é o teto de 50 trocas por formulário: uma entrada final de marcação, e nada depois dela ficou guardado. `UNREADABLE` é uma troca que ficou guardada mas cujo conteúdo não se conseguiu reler. Não há terceira forma.

A lista só cresce e nunca é de-duplicada: quem volta atrás numa tela e responde de novo produz uma segunda entrada GENUÍNA, e é o `at` que distingue duas passagens debaixo do mesmo `flowToken`. As trocas ficam 30 dias + 1 — um dia a MAIS do que a linha da resposta — porque a troca é capturada enquanto a pessoa ainda está preenchendo, minutos ANTES do envio que cria a linha; com uma janela igual elas expirariam primeiro, e uma resposta ainda dentro da retenção dela publicaria `submitted: []` nos seus últimos minutos. Num número com `piiMode: "RELAY_ONLY"` não fica aqui nada: nem uma entrada ocultada, nenhuma entrada.



## OpenAPI

````yaml openapi.pt.json GET /v1/flows/{id}/responses
openapi: 3.1.0
info:
  title: API Pilot Status
  version: 1.0.0
  license:
    name: Pilot Status Terms of Service
    url: https://pilotstatus.com.br/terms
  description: >-
    API REST pública do Pilot Status. Autentique com o header `x-api-key:
    ps_...` (ou `x-api-key-id`). Base URL: https://pilotstatus.com.br
servers:
  - url: https://pilotstatus.com.br
security:
  - apiKey: []
  - apiKeyId: []
paths:
  /v1/flows/{id}/responses:
    get:
      tags:
        - Flows
      summary: Listar respostas do Flow
      description: >-
        Os formulários que os clientes enviaram para UM Flow, os mais novos
        primeiro. O Flow é resolvido primeiro dentro da WABA da própria chave, e
        essa resolução é a única coisa que escopa o resto — um Flow de outra
        WABA (inclusive outra WABA do mesmo tenant) responde 404 e nenhuma
        resposta chega a ser lida.


        Respostas fora da janela de retenção são excluídas AQUI, não só pela
        tarefa de poda, para que ninguém leia um envio que a janela publicada
        diz ter sumido. `contactPhone` vem `null` quando o telefone já não é
        nosso para publicar. `externalMessageId` é o `wamid` da Meta e é NOMEADO
        como id de provedor de propósito — todo outro id desta superfície é
        local.


        `notice: "FLOW_RESPONSES_WINDOW_TRUNCATED"` aparece na página quando o
        Flow cunhou mais envios do que uma requisição correlaciona (teto de
        10.000 sessões). Uma resposta curta que não diz que é curta é o que faz
        o cliente concluir que perdeu envios. Permissão `flows:read`.


        **Exige chave com escopo de número.** Uma chave de tenant precisa nomear
        o número no header `x-whatsapp-number-id`, senão recebe 403
        `TENANT_SCOPE_NOT_ALLOWED`.


        `media[]` leva os arquivos que a pessoa ANEXOU dentro do formulário
        (`PhotoPicker` / `DocumentPicker`). Eles NÃO estão em `response`: um
        picker exige `data_exchange`, portanto as referências chegam no pedido
        que o nosso endpoint decifra — uma troca HTTP diferente do `nfm_reply`
        que produziu a linha — e este array é a cópia re-hospedada, ligada pelo
        `flowToken`. É o único lugar onde um chamador alcança os bytes: a Meta
        apaga o original após 20 dias. É SEMPRE um array, `[]` quando nada foi
        anexado. `url` é um link estável nosso e está presente assim que a linha
        existe, INCLUSIVE enquanto `status` for `"PENDING"`. Buscá-lo antes de a
        re-hospedagem terminar não dá 404: a rota segura o pedido enquanto
        espera pelo arquivo e então o serve, toda busca posterior é um redirect,
        e uma espera que estoura responde 404 com o cabeçalho `Retry-After`. O
        valor não muda depois de os bytes chegarem, portanto é seguro guardá-lo
        logo na chegada, e o `status` (`PENDING`/`STORED`/`FAILED`) continua
        sendo como o chamador sabe se eles chegaram. É a ordem que justifica
        esse link: o evento é emitido assim que o envio é guardado e a
        re-hospedagem roda depois dele, portanto o anúncio precede normalmente
        os bytes. `url` só é nulo quando a instalação não tem segredo de
        assinatura configurado (aí volta ao comportamento antigo, a URL direta
        do objeto assim que ficar `STORED`), quando a Meta não enviou `media_id`
        para assinar uma identidade em cima, ou num número `RELAY_ONLY` onde
        nada foi guardado — nunca apenas porque a transferência ainda não
        terminou. Trate-o como opaco: busque, nunca construa um. `mimeType` é
        farejado dos bytes decifrados e nunca do nome do arquivo, e ele e
        `sizeBytes` são `null` até o arquivo ficar guardado. Nem `cdn_url` nem
        material de cifra são alguma vez publicados.


        `submitted[]` é o que a pessoa de fato ESCREVEU, tela a tela. ⛔ Num Flow
        `data_exchange` é o ÚNICO lugar onde essas respostas existem: ali o
        `response` é o `nfm_reply` da Meta, um envelope que leva o `flow_token`
        e mais nada — quem abre o `response` num Flow desses encontra uma sala
        vazia e conclui que o envio se perdeu. Num Flow SIMPLES, sem endpoint,
        as respostas CHEGAM no `response` e o `submitted` vem `[]`.


        Cada entrada é um pedido `data_exchange` que a META NOS ENVIOU: `screen`
        (a tela em que a pessoa estava, ou `null`), `at` (ISO 8601), `data` (o
        objeto já parseado) e `omitted`. Nunca é o que o SEU endpoint respondeu
        — o `extension_message_response` não é publicado em lugar nenhum do
        Pilot Status. E só as trocas `data_exchange` são capturadas: o `INIT`
        devolve o estado que NÓS semeamos quando o Flow foi enviado, e o `BACK`
        é navegação, portanto esta lista é legitimamente MAIS CURTA do que o
        tráfego que o seu próprio endpoint viu. Essa diferença não é perda.


        NESTE endpoint o `submitted` é sempre um array e nunca `null` — `[]`
        tanto quando não há nada como quando o número não guarda conteúdo de
        cliente, porque "nada foi capturado" e "não conseguimos olhar" seriam
        senão o mesmo valor. (No webhook `flow.response_received` é o contrário,
        `null` e nunca `[]`, porque lá o redator só apaga um campo que tenha
        algo dentro.) Nada é truncado em silêncio: ou a entrada leva `data` com
        `omitted: null`, ou leva `data: null` e diz o PORQUÊ. `DATA_TOO_LARGE` é
        uma troca grande demais, que mantém a linha e o lugar dela na sequência
        — o teto que ela passou conta-se em BYTES, não em caracteres, portanto
        texto com acentos chega lá antes do que o comprimento sugere.
        `LIMIT_REACHED` é o teto de 50 trocas por formulário: uma entrada final
        de marcação, e nada depois dela ficou guardado. `UNREADABLE` é uma troca
        que ficou guardada mas cujo conteúdo não se conseguiu reler. Não há
        terceira forma.


        A lista só cresce e nunca é de-duplicada: quem volta atrás numa tela e
        responde de novo produz uma segunda entrada GENUÍNA, e é o `at` que
        distingue duas passagens debaixo do mesmo `flowToken`. As trocas ficam
        30 dias + 1 — um dia a MAIS do que a linha da resposta — porque a troca
        é capturada enquanto a pessoa ainda está preenchendo, minutos ANTES do
        envio que cria a linha; com uma janela igual elas expirariam primeiro, e
        uma resposta ainda dentro da retenção dela publicaria `submitted: []`
        nos seus últimos minutos. Num número com `piiMode: "RELAY_ONLY"` não
        fica aqui nada: nem uma entrada ocultada, nenhuma entrada.
      operationId: get_flows_id_responses
      parameters:
        - name: id
          in: path
          required: true
          description: >-
            O id **local** do Flow — o campo `id` que `GET /v1/flows` devolve,
            nunca o `metaFlowId`.
          schema:
            type: string
          example: cmf1a2b3c4d5e6f7g8h9i0j1
        - name: page
          in: query
          required: false
          description: Número da página, começando em 1.
          schema:
            type: integer
            minimum: 1
            default: 1
          example: 1
        - name: pageSize
          in: query
          required: false
          description: Linhas por página. Padrão 30, máximo 100.
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 30
          example: 30
      responses:
        '200':
          description: Listar respostas do Flow
          content:
            application/json:
              schema:
                type: object
                properties:
                  responses:
                    type: array
                    description: Os envios desta página, os mais novos primeiro.
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          description: Id local do envio.
                        flowId:
                          type: string
                          description: >-
                            O id LOCAL do Flow por onde isto foi lido, ecoado do
                            caminho — uma resposta nomeia sempre o recurso por
                            onde foi lida.
                        contactPhone:
                          type:
                            - string
                            - 'null'
                          description: >-
                            Telefone de quem respondeu. `null` quando o telefone
                            já não é nosso para publicar — a sessão por trás do
                            token foi podada, ou a janela de retenção dela
                            fechou. A resposta sobrevive ao telefone por
                            desenho, portanto o envio continua listado e
                            contado; só o telefone vai embora.
                        flowToken:
                          type: string
                          description: >-
                            O `flow_token` sob o qual este envio chegou. É ele
                            que liga `media[]` e `submitted[]` à linha.
                        externalMessageId:
                          type: string
                          description: >-
                            O `wamid` da Meta da mensagem que carregou o envio.
                            NOMEADO como id de provedor de propósito — todo
                            outro id desta superfície é local — e é o mesmo
                            valor que `/v1/messages` publica como
                            `externalMessageId`.
                        response:
                          type:
                            - object
                            - 'null'
                          description: >-
                            O que o endpoint do próprio cliente devolveu para o
                            envio, já parseado. ⚠️ Num Flow com endpoint
                            `data_exchange` isto vem vazio mesmo num número que
                            guarda: o `nfm_reply` da Meta leva apenas o
                            `flow_token`, e o que a pessoa escreveu está no
                            `submitted`. `null` quando o payload guardado estava
                            corrompido ou não era um conjunto de respostas,
                            quando a Meta não entregou `response_json` nenhum,
                            ou quando o número não guarda conteúdo de cliente.
                            Nada distingue os três aqui, de propósito: um
                            discriminador publicaria, por envio, se um número
                            guarda conteúdo de cliente.
                        media:
                          type: array
                          description: >-
                            Os arquivos que a pessoa ANEXOU dentro do formulário
                            (`PhotoPicker` / `DocumentPicker`) — a cópia
                            re-hospedada, e o único lugar onde um chamador
                            alcança os bytes, já que a Meta apaga o original
                            após 20 dias. É SEMPRE um array, `[]` quando nada
                            foi anexado: "sem anexos" e "não conseguimos olhar"
                            seriam senão o mesmo valor. ⚠️ Eles NÃO estão no
                            `response`.
                          items:
                            type: object
                            properties:
                              field:
                                type: string
                                description: >-
                                  A chave do formulário sob a qual o arquivo foi
                                  listado — o nome que o AUTOR do Flow deu ao
                                  componente. Os anexos são casados por FORMA e
                                  nunca por nome, portanto `photo_picker` é o
                                  exemplo da documentação da Meta e não uma
                                  palavra reservada.
                              fileName:
                                type:
                                  - string
                                  - 'null'
                                description: >-
                                  O nome que o aparelho de quem enviou reportou,
                                  quando reportou algum.
                              mimeType:
                                type:
                                  - string
                                  - 'null'
                                description: >-
                                  Farejado dos bytes DECIFRADOS, nunca tirado do
                                  nome do arquivo. `null` enquanto o `status`
                                  for `PENDING`: os bytes de onde ele se lê
                                  ainda não existem.
                              sizeBytes:
                                type:
                                  - integer
                                  - 'null'
                                description: >-
                                  Tamanho do arquivo DECIFRADO, em bytes. `null`
                                  enquanto o `status` for `PENDING`, pela mesma
                                  razão que o `mimeType` é.
                              status:
                                type: string
                                description: >-
                                  `PENDING` enquanto a transferência está em
                                  curso, depois `STORED` ou `FAILED`. De
                                  propósito não é um conjunto fechado: um estado
                                  novo tem de ser gravável no dia em que
                                  existir.
                              url:
                                type:
                                  - string
                                  - 'null'
                                description: >-
                                  Um link estável NOSSO, presente desde o
                                  momento em que a linha existe — INCLUSIVE
                                  enquanto o `status` for `PENDING`. Trate-o
                                  como opaco: busque, nunca construa nem
                                  interprete um. Ele não muda depois de os bytes
                                  chegarem, portanto é seguro guardá-lo logo na
                                  chegada, e o `status` continua sendo o que diz
                                  se eles chegaram. `null` em três casos, e
                                  nenhum deles é "ainda não transferiu": a
                                  instalação não tem segredo de assinatura nem
                                  URL base para cunhar um link (aí volta à URL
                                  direta do objeto assim que ficar `STORED`), a
                                  Meta não enviou `media_id` para assinar uma
                                  identidade em cima, ou o número não guarda
                                  conteúdo de cliente e não há linha nenhuma.
                                  Nem `cdn_url` nem material de cifra são alguma
                                  vez publicados.
                        submitted:
                          type: array
                          description: >-
                            O QUE A PESSOA ESCREVEU, tela a tela, num Flow
                            `data_exchange` — uma entrada por pedido
                            `data_exchange` que a Meta nos enviou, na ordem de
                            envio. ⛔ NÃO é o `response`: o `response` é o que o
                            SEU endpoint devolveu, isto é o que o APARELHO nos
                            mandou pelo caminho. ⛔ Uma lista e nunca um objeto
                            fundido — cada troca leva apenas os campos DA SUA
                            tela, e fundir deixaria o último campo de nome
                            repetido vencer em silêncio. É SEMPRE um array, `[]`
                            quando nada foi capturado: "nada foi capturado" e
                            "não conseguimos olhar" seriam senão o mesmo valor.
                            ⚠️ `[]` NÃO é "a pessoa não escreveu nada" — é
                            também um Flow só de NAVIGATE (nenhuma troca chegou
                            ao nosso endpoint; as respostas estão todas no
                            `response`), um número que não guarda conteúdo de
                            cliente, ou um envio anterior a isto existir. ⚠️
                            Legitimamente MAIS CURTA do que o registro de trocas
                            que o painel de diagnóstico de um Flow mostra: só o
                            `data_exchange` produz uma entrada, o `INIT` devolve
                            o estado que NÓS semeamos no envio e o `BACK` é
                            navegação. Cada entrada tem uma de exatamente duas
                            formas, e não há terceira: `data` com `omitted:
                            null`, ou `data: null` com o `omitted` dizendo o
                            porquê.
                          items:
                            oneOf:
                              - type: object
                                title: Respondida
                                description: A troca leva `data`, e o `omitted` vem `null`.
                                properties:
                                  screen:
                                    type:
                                      - string
                                      - 'null'
                                    description: >-
                                      A tela em que a pessoa estava, ou `null`
                                      quando a Meta não nomeou nenhuma. ⚠️ Um
                                      nome de tela repetido NÃO é duplicata:
                                      quem envia uma tela, volta atrás e envia
                                      de novo produz duas entradas para ela, em
                                      ordem, com respostas diferentes.
                                  at:
                                    type: string
                                    format: date-time
                                    description: >-
                                      Quando o NOSSO proxy viu a troca — minutos
                                      ANTES do `receivedAt`, porque a pessoa
                                      ainda estava preenchendo o formulário.
                                  data:
                                    type: object
                                    description: >-
                                      Os campos DAQUELA tela, exatamente como o
                                      aparelho os enviou. As chaves são o que o
                                      autor do Flow chamou aos componentes dele.
                                  omitted:
                                    type: 'null'
                                    description: '`null` porque o `data` está lá.'
                              - type: object
                                title: Não guardada
                                description: >-
                                  A troca leva `data: null` e DIZ o porquê. Ela
                                  mantém a linha, a ordem e o nome da tela —
                                  meio documento JSON não é meia resposta.
                                properties:
                                  screen:
                                    type:
                                      - string
                                      - 'null'
                                    description: >-
                                      A tela em que a pessoa estava, ou `null`
                                      quando a Meta não nomeou nenhuma. ⚠️ Um
                                      nome de tela repetido NÃO é duplicata:
                                      quem envia uma tela, volta atrás e envia
                                      de novo produz duas entradas para ela, em
                                      ordem, com respostas diferentes.
                                  at:
                                    type: string
                                    format: date-time
                                    description: >-
                                      Quando o NOSSO proxy viu a troca — minutos
                                      ANTES do `receivedAt`, porque a pessoa
                                      ainda estava preenchendo o formulário.
                                  data:
                                    type: 'null'
                                    description: '`null`; o `omitted` diz o porquê.'
                                  omitted:
                                    type: string
                                    description: >-
                                      Por que o `data` é `null`. Hoje estão
                                      definidos três valores — `DATA_TOO_LARGE`,
                                      esta troca sozinha passou do teto por
                                      troca; `LIMIT_REACHED`, o teto por
                                      formulário foi atingido NESTA troca,
                                      portanto a entrada é uma marcação, nada
                                      depois dela ficou guardado e ela é sempre
                                      a última entrada da lista; e `UNREADABLE`,
                                      bytes guardados que já não se leem como um
                                      objeto JSON. ⚠️ De propósito NÃO é um
                                      conjunto fechado, pela mesma razão que o
                                      `media[].status` não é: um motivo de que o
                                      seu cliente nunca ouviu falar tem de
                                      chegar mesmo assim em vez de rebentar um
                                      parse, e um cliente gerado é regerado
                                      raramente.
                        receivedAt:
                          type: string
                          format: date-time
                          description: Quando a resposta CHEGOU.
                        expiresAt:
                          type: string
                          format: date-time
                          description: >-
                            Quando esta resposta deixa de ser legível — 30 dias
                            a contar da chegada. Linhas fora dela são excluídas
                            desta própria listagem, não só pela tarefa de poda.
                  total:
                    type: integer
                    description: >-
                      Envios que casam com a leitura em todas as páginas, não o
                      tamanho desta página.
                  page:
                    type: integer
                  pageSize:
                    type: integer
                  totalPages:
                    type: integer
                  notice:
                    type: string
                    enum:
                      - FLOW_RESPONSES_WINDOW_TRUNCATED
                    description: >-
                      Presente APENAS quando o Flow cunhou mais envios do que
                      uma requisição correlaciona (teto de 10.000 sessões);
                      ausente caso contrário. A página fica então CURTA — leia
                      isso como "pode haver mais", nunca como "estes são todos
                      os envios".
              example:
                responses:
                  - id: cmf9z8y7x6w5v4u3t2s1r0q9
                    flowId: cmf1a2b3c4d5e6f7g8h9i0j1
                    contactPhone: '5564999978874'
                    flowToken: b7c1e4f2a9d84c6e8f0a1b2c3d4e5f60
                    externalMessageId: wamid.HBgNNTU2NDk5OTc4ODc0FQIAERgSN0E5...
                    response:
                      flow_token: b7c1e4f2a9d84c6e8f0a1b2c3d4e5f60
                    submitted:
                      - screen: WELCOME_SCREEN
                        at: '2026-09-01T18:21:44.318Z'
                        data:
                          screen_0_nome: Amanda
                          screen_0_nota: '9'
                        omitted: null
                      - screen: COMENTARIO_SCREEN
                        at: '2026-09-01T18:22:03.907Z'
                        data: null
                        omitted: DATA_TOO_LARGE
                    media:
                      - field: photo_picker
                        fileName: documento.jpg
                        mimeType: image/jpeg
                        sizeBytes: 184320
                        status: STORED
                        url: >-
                          https://media.pilotstatus.com.br/public/tenants/tenant_01HZX.../flow-media/8f2c1a4b9d.jpg
                      - field: document_picker
                        fileName: comprovante.pdf
                        mimeType: null
                        sizeBytes: null
                        status: PENDING
                        url: >-
                          https://pilotstatus.com.br/api/flows/media/eyJ0IjoiY21xc2N4MXczIiwiayI6ImZvdG8ifQ.9f2c1a4b8e0d6c73
                    receivedAt: '2026-09-01T18:22:11.000Z'
                    expiresAt: '2026-10-01T18:22:11.000Z'
                total: 1
                page: 1
                pageSize: 30
                totalPages: 1
        '400':
          description: Paginação profunda demais (`page` × `pageSize` além do teto)
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    description: Metade em português
                  errorEN:
                    type: string
                    description: Metade em inglês
                  code:
                    type: string
              example:
                error: >-
                  Paginação profunda demais: page × pageSize não pode passar de
                  10000.
                errorEN: 'Pagination too deep: page × pageSize must not exceed 10000.'
                code: INVALID_PAGINATION
        '401':
          description: Header `x-api-key` / `x-api-key-id` ausente ou inválido
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  code:
                    type: string
              example:
                error: Unauthorized
        '403':
          description: >-
            Chave com escopo de tenant usada em endpoint com escopo de número,
            ou o papel da chave não tem a permissão
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  code:
                    type: string
              example:
                error: Tenant-scoped keys cannot call number endpoints
                code: TENANT_SCOPE_NOT_ALLOWED
        '404':
          description: >-
            Nenhum Flow com esse id dentro da WABA da própria chave. Nunca 403:
            um Flow de outro tenant é indistinguível de um que não existe, de
            propósito — um 403 confirmaria o id alheio a quem o adivinhou
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    description: Metade em português
                  errorEN:
                    type: string
                    description: Metade em inglês
                  code:
                    type: string
              example:
                error: Flow não encontrado para o número desta chave.
                errorEN: Flow not found for this key's number.
                code: FLOW_NOT_FOUND
        '422':
          description: >-
            O número da chave não é Meta (API Oficial), ou não tem WABA
            associada
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    description: Metade em português
                  errorEN:
                    type: string
                    description: Metade em inglês
                  code:
                    type: string
              example:
                error: >-
                  Flows existem apenas em números Meta (API Oficial). O número
                  desta chave não é Meta ou não tem uma WABA associada — use uma
                  chave de um número Meta.
                errorEN: >-
                  Flows only exist on Meta (Cloud API) numbers. This key's
                  number is not a Meta number, or has no WABA behind it — use a
                  key bound to a Meta number.
                code: FLOW_REQUIRES_META_NUMBER
        '429':
          description: Limite de taxa excedido
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  code:
                    type: string
              example:
                error: Too many requests
        '500':
          description: Erro interno. Nunca carrega a mensagem interna — essa fica no log
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    description: Metade em português
                  errorEN:
                    type: string
                    description: Metade em inglês
                  code:
                    type: string
              example:
                error: Erro interno do servidor.
                errorEN: Internal server error.
                code: INTERNAL_ERROR
components:
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: x-api-key
      description: Sua chave de API ps_
    apiKeyId:
      type: apiKey
      in: header
      name: x-api-key-id
      description: Id da chave de API (alternativa ao x-api-key)

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.