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

# Gerar ou importar a chave de endpoint do Flow

> Põe o par de chaves `data_exchange` em UM número, por um de DOIS verbos, distinguidos por um único campo: envie `privateKey` e ele IMPORTA a chave que você já tem; deixe-o de fora e ele GERA um par novo. Responde 200 com a mesma forma que o `GET` devolve, mais `replaced`.

- **GERAR — sem `privateKey`.** Cria o par, guarda a metade privada cifrada e REGISTRA a metade pública na Meta.
- **IMPORTAR — `privateKey`, opcionalmente com `passphrase`.** Guarda uma chave que você JÁ tem, e ⛔ NÃO REGISTRA NADA NA META.

⛔ **GERAR É UMA OPERAÇÃO DESTRUTIVA COM CARA DE CRIAÇÃO.** A Meta guarda exatamente UMA chave pública por phone id: registrar uma segunda não a acrescenta, SUBSTITUI a primeira, e todos os Flows `data_exchange` daquele número deixam de decifrar de uma vez. Do lado do cliente o sintoma é um formulário que não abre mais, sem erro nenhum do nosso lado — o endpoint simplesmente responde 421 a um corpo cifrado para uma chave que já não temos. A metade privada guardada aqui é sobrescrita no mesmo instante e não tem volta.

⛔ **IMPORTAR NÃO REGISTRA NADA NA META, e é exatamente esse o ponto.** A sua chave pública já está registrada — muitas vezes por um sistema anterior a nós — e a Meta guarda exatamente uma chave por phone id, então registrar aqui substituiria justamente a configuração que a importação existe para preservar. O que torna isso seguro é uma LEITURA: derivamos a metade pública da privada que você enviou e comparamos com a chave que a Meta diz ter para o número.

- batem → guardada, `uploadedAt` carimbado, `metaStatus: "VALID"`.
- não batem → 400 `FLOW_ENDPOINT_KEY_IMPORT_MISMATCH`, e NADA é escrito. Guardá-la deixaria um número dizendo `configured: true` sem decifrar coisa nenhuma.
- a Meta não pôde ser consultada, ou não tem chave → **guardada mesmo assim**, com `uploadedAt: null` e `metaStatus` `UNKNOWN`/`NOT_SET`. Esse null É o sinal de "não verificada" e você tem de lê-lo: um 200 sozinho não distingue os dois casos.

Um PEM protegido por passphrase é aceito; a chave é aberta uma vez, aqui, e guardada normalizada. O PEM tem de ser RSA de 2048 bits ou mais — a Meta cifra o `data_exchange` com RSA/OAEP.

⛔ **`confirm` NÃO É SEMPRE OBRIGATÓRIO. Ele é exigido exatamente quando a chamada SUBSTITUI UMA CHAVE VIVA — e essa regra é a mesma para OS DOIS verbos.** Uma única checagem de estado decide: já existe uma chave nossa viva na Meta (`uploadedAt` diferente de `null`). A PRIMEIRA configuração nunca pergunta, seja qual for o verbo, e repetir um par que a Meta nunca aceitou (`uploadedAt: null`) também não — essa chamada reenvia a MESMA metade pública guardada e converge em vez de substituir, então não há o que destruir. Quando ele É exigido, a checagem é `=== true`, então `"true"`, `1` e `{}` são todos recusados.

⚠️ **Importar também tem portão, e o que ele protege é o NOSSO lado, não o da Meta.** Uma importação não registra nada na Meta, mas sobrescreve a metade privada guardada aqui — a chave com que NÓS decifamos. Se o número já tinha uma chave que funcionava e a Meta não conseguir confirmar a importada (indisponível, por exemplo), a importada é guardada assim mesmo e todo `data_exchange` daquele número deixa de decifrar, sem nada ter mudado na Meta para apontar a causa. Por isso os dois verbos partilham o campo e respondem com códigos DIFERENTES: `FLOW_ENDPOINT_KEY_REQUIRES_CONFIRMATION` ao gerar (o que está em jogo é o registro na Meta) e `FLOW_ENDPOINT_KEY_IMPORT_REQUIRES_CONFIRMATION` ao importar (o que está em jogo é a metade privada guardada aqui).

⚠️ `replaced` está no payload porque um 200 sozinho não diz qual das duas coisas aconteceu. `replaced: false` é "agora existe uma chave onde não havia nenhuma viva"; `replaced: true` é "a chave que funcionava acabou, e todo Flow que respondia com o par antigo passa a responder com o novo".

**O corpo aceita três campos — `confirm`, `privateKey` e `passphrase` — e qualquer outro dá 400 `FLOW_UNKNOWN_FIELDS`**. `passphrase` sozinha é RECUSADA, 400 `FLOW_ENDPOINT_KEY_PASSPHRASE_ORPHAN`, e nunca ignorada: um `privateKey` digitado errado cairia senão no GERAR, que registra uma chave nova na Meta e substitui o que lá estava — o resultado mais destrutivo desta rota, alcançado por um erro de digitação e reportado como sucesso. Um `privateKey` que não seja string não vazia, ou um `passphrase` que não seja string, dá 400 `FLOW_ENDPOINT_KEY_IMPORT_INVALID`, respondido antes de qualquer criptografia rodar. Um PEM que não dá para usar é um 400 cujo código nomeia o conserto: `FLOW_ENDPOINT_KEY_PASSPHRASE_REQUIRED`, `FLOW_ENDPOINT_KEY_PASSPHRASE_WRONG` ou `FLOW_ENDPOINT_KEY_PEM_INVALID` (ilegível, não-RSA, ou com menos de 2048 bits).

Corpo truncado não é lido como corpo vazio — o payload é parseado do texto cru, então `{"confirm": true` (uma chave faltando) dá 400 `FLOW_BODY_INVALID` em vez de um confuso "confirmação necessária". Nenhum corpo continua sendo legítimo, e significa GERAR. Nomear o número no corpo — `whatsappNumberId`, `numberId` ou `wabaId` — tem recusa própria, 400 `FLOW_NUMBER_FROM_KEY`, porque o número vem da credencial. Permissão `flows:manage`.

**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`.



## OpenAPI

````yaml openapi.pt.json POST /v1/numbers/{id}/flow-endpoint-key
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/numbers/{id}/flow-endpoint-key:
    post:
      tags:
        - Numbers
      summary: Gerar ou importar a chave de endpoint do Flow
      description: >-
        Põe o par de chaves `data_exchange` em UM número, por um de DOIS verbos,
        distinguidos por um único campo: envie `privateKey` e ele IMPORTA a
        chave que você já tem; deixe-o de fora e ele GERA um par novo. Responde
        200 com a mesma forma que o `GET` devolve, mais `replaced`.


        - **GERAR — sem `privateKey`.** Cria o par, guarda a metade privada
        cifrada e REGISTRA a metade pública na Meta.

        - **IMPORTAR — `privateKey`, opcionalmente com `passphrase`.** Guarda
        uma chave que você JÁ tem, e ⛔ NÃO REGISTRA NADA NA META.


        ⛔ **GERAR É UMA OPERAÇÃO DESTRUTIVA COM CARA DE CRIAÇÃO.** A Meta guarda
        exatamente UMA chave pública por phone id: registrar uma segunda não a
        acrescenta, SUBSTITUI a primeira, e todos os Flows `data_exchange`
        daquele número deixam de decifrar de uma vez. Do lado do cliente o
        sintoma é um formulário que não abre mais, sem erro nenhum do nosso lado
        — o endpoint simplesmente responde 421 a um corpo cifrado para uma chave
        que já não temos. A metade privada guardada aqui é sobrescrita no mesmo
        instante e não tem volta.


        ⛔ **IMPORTAR NÃO REGISTRA NADA NA META, e é exatamente esse o ponto.** A
        sua chave pública já está registrada — muitas vezes por um sistema
        anterior a nós — e a Meta guarda exatamente uma chave por phone id,
        então registrar aqui substituiria justamente a configuração que a
        importação existe para preservar. O que torna isso seguro é uma LEITURA:
        derivamos a metade pública da privada que você enviou e comparamos com a
        chave que a Meta diz ter para o número.


        - batem → guardada, `uploadedAt` carimbado, `metaStatus: "VALID"`.

        - não batem → 400 `FLOW_ENDPOINT_KEY_IMPORT_MISMATCH`, e NADA é escrito.
        Guardá-la deixaria um número dizendo `configured: true` sem decifrar
        coisa nenhuma.

        - a Meta não pôde ser consultada, ou não tem chave → **guardada mesmo
        assim**, com `uploadedAt: null` e `metaStatus` `UNKNOWN`/`NOT_SET`. Esse
        null É o sinal de "não verificada" e você tem de lê-lo: um 200 sozinho
        não distingue os dois casos.


        Um PEM protegido por passphrase é aceito; a chave é aberta uma vez,
        aqui, e guardada normalizada. O PEM tem de ser RSA de 2048 bits ou mais
        — a Meta cifra o `data_exchange` com RSA/OAEP.


        ⛔ **`confirm` NÃO É SEMPRE OBRIGATÓRIO. Ele é exigido exatamente quando
        a chamada SUBSTITUI UMA CHAVE VIVA — e essa regra é a mesma para OS DOIS
        verbos.** Uma única checagem de estado decide: já existe uma chave nossa
        viva na Meta (`uploadedAt` diferente de `null`). A PRIMEIRA configuração
        nunca pergunta, seja qual for o verbo, e repetir um par que a Meta nunca
        aceitou (`uploadedAt: null`) também não — essa chamada reenvia a MESMA
        metade pública guardada e converge em vez de substituir, então não há o
        que destruir. Quando ele É exigido, a checagem é `=== true`, então
        `"true"`, `1` e `{}` são todos recusados.


        ⚠️ **Importar também tem portão, e o que ele protege é o NOSSO lado, não
        o da Meta.** Uma importação não registra nada na Meta, mas sobrescreve a
        metade privada guardada aqui — a chave com que NÓS decifamos. Se o
        número já tinha uma chave que funcionava e a Meta não conseguir
        confirmar a importada (indisponível, por exemplo), a importada é
        guardada assim mesmo e todo `data_exchange` daquele número deixa de
        decifrar, sem nada ter mudado na Meta para apontar a causa. Por isso os
        dois verbos partilham o campo e respondem com códigos DIFERENTES:
        `FLOW_ENDPOINT_KEY_REQUIRES_CONFIRMATION` ao gerar (o que está em jogo é
        o registro na Meta) e `FLOW_ENDPOINT_KEY_IMPORT_REQUIRES_CONFIRMATION`
        ao importar (o que está em jogo é a metade privada guardada aqui).


        ⚠️ `replaced` está no payload porque um 200 sozinho não diz qual das
        duas coisas aconteceu. `replaced: false` é "agora existe uma chave onde
        não havia nenhuma viva"; `replaced: true` é "a chave que funcionava
        acabou, e todo Flow que respondia com o par antigo passa a responder com
        o novo".


        **O corpo aceita três campos — `confirm`, `privateKey` e `passphrase` —
        e qualquer outro dá 400 `FLOW_UNKNOWN_FIELDS`**. `passphrase` sozinha é
        RECUSADA, 400 `FLOW_ENDPOINT_KEY_PASSPHRASE_ORPHAN`, e nunca ignorada:
        um `privateKey` digitado errado cairia senão no GERAR, que registra uma
        chave nova na Meta e substitui o que lá estava — o resultado mais
        destrutivo desta rota, alcançado por um erro de digitação e reportado
        como sucesso. Um `privateKey` que não seja string não vazia, ou um
        `passphrase` que não seja string, dá 400
        `FLOW_ENDPOINT_KEY_IMPORT_INVALID`, respondido antes de qualquer
        criptografia rodar. Um PEM que não dá para usar é um 400 cujo código
        nomeia o conserto: `FLOW_ENDPOINT_KEY_PASSPHRASE_REQUIRED`,
        `FLOW_ENDPOINT_KEY_PASSPHRASE_WRONG` ou `FLOW_ENDPOINT_KEY_PEM_INVALID`
        (ilegível, não-RSA, ou com menos de 2048 bits).


        Corpo truncado não é lido como corpo vazio — o payload é parseado do
        texto cru, então `{"confirm": true` (uma chave faltando) dá 400
        `FLOW_BODY_INVALID` em vez de um confuso "confirmação necessária".
        Nenhum corpo continua sendo legítimo, e significa GERAR. Nomear o número
        no corpo — `whatsappNumberId`, `numberId` ou `wabaId` — tem recusa
        própria, 400 `FLOW_NUMBER_FROM_KEY`, porque o número vem da credencial.
        Permissão `flows:manage`.


        **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`.
      operationId: post_numbers_id_flow_endpoint_key
      parameters:
        - name: id
          in: path
          required: true
          description: >-
            O id do número ao qual a chave está vinculada — o `id` (ou o id da
            instância) que `GET /v1/numbers` devolve. Ele é CONFERIDO contra o
            número da própria credencial, nunca usado para procurar um.
          schema:
            type: string
          example: num_01HZX...
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                confirm:
                  type: boolean
                  enum:
                    - true
                  description: >-
                    Tem de ser o booleano `true`, exatamente. ⛔ NÃO é sempre
                    obrigatório: é exigido exatamente quando a chamada SUBSTITUI
                    UMA CHAVE VIVA — ou seja, quando já existe uma chave nossa
                    viva na Meta (`uploadedAt` diferente de `null`) — e essa
                    regra vale para OS DOIS verbos, gerar e importar. A primeira
                    configuração não pergunta, e repetir um par que a Meta nunca
                    aceitou também não. O que ele reconhece muda com o verbo: ao
                    gerar, que a chave registrada na Meta é SUBSTITUÍDA e todos
                    os Flows `data_exchange` deste número deixam de decifrar; ao
                    importar, que a metade privada guardada aqui é SUBSTITUÍDA,
                    o que quebra a decifragem do nosso lado se a Meta não
                    conseguir confirmar a chave importada.
                  example: true
                privateKey:
                  type: string
                  minLength: 1
                  description: >-
                    O PEM de uma chave privada que você JÁ tem, cuja metade
                    pública a Meta tem registrada para este número. ⛔ A PRESENÇA
                    dele é o que transforma este POST de GERAR em IMPORTAR:
                    enviado, nada é registrado na Meta e só a metade privada
                    guardada muda; omitido, um par novo é criado e a metade
                    pública dele REGISTRADA na Meta. Tem de ser string não vazia
                    — `privateKey: 42` dá 400 `FLOW_ENDPOINT_KEY_IMPORT_INVALID`
                    e nunca é convertido. Envie o conteúdo do arquivo `.pem`
                    inteiro, incluindo as linhas `-----BEGIN …-----` e `-----END
                    …-----`. RSA, 2048 bits ou mais; um PEM protegido por
                    passphrase é aceito junto de `passphrase`. Se a metade
                    pública dele não for a que a Meta tem, a resposta é 400
                    `FLOW_ENDPOINT_KEY_IMPORT_MISMATCH` e nada é escrito.
                  example: |
                    -----BEGIN PRIVATE KEY-----
                    MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQ...
                    -----END PRIVATE KEY-----
                passphrase:
                  type: string
                  description: >-
                    A passphrase que abre `privateKey`, quando o PEM está
                    cifrado. Opcional, e só faz sentido junto de `privateKey`: ⛔
                    enviada sozinha é RECUSADA com 400
                    `FLOW_ENDPOINT_KEY_PASSPHRASE_ORPHAN` em vez de ignorada,
                    porque um `privateKey` digitado errado cairia senão no GERAR
                    e substituiria o registro na Meta. Tem de ser string. Um PEM
                    cifrado sem passphrase dá 400
                    `FLOW_ENDPOINT_KEY_PASSPHRASE_REQUIRED`; uma passphrase que
                    não o abre dá 400 `FLOW_ENDPOINT_KEY_PASSPHRASE_WRONG` —
                    dois códigos, porque são dois consertos diferentes.
                  example: a-passphrase-que-abre-o-pem
            examples:
              generateFirstTime:
                summary: >-
                  GERAR, primeira configuração — sem corpo, não há nada vivo
                  para substituir
                value: {}
              generateReplacingLiveKey:
                summary: GERAR sobre uma chave viva — `confirm` obrigatório
                value:
                  confirm: true
              importFirstTime:
                summary: IMPORTAR uma chave que já é sua — nada é registrado na Meta
                value:
                  privateKey: |
                    -----BEGIN PRIVATE KEY-----
                    MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQ...
                    -----END PRIVATE KEY-----
              importPassphraseProtected:
                summary: IMPORTAR um PEM protegido por passphrase sobre uma chave viva
                value:
                  privateKey: |
                    -----BEGIN PRIVATE KEY-----
                    MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQ...
                    -----END PRIVATE KEY-----
                  passphrase: a-passphrase-que-abre-o-pem
                  confirm: true
      responses:
        '200':
          description: >-
            Agora existe um par de chaves no número. GERAR também registrou a
            metade pública na Meta; IMPORTAR não registrou NADA — nesse caso,
            `uploadedAt: null` com `metaStatus` `UNKNOWN`/`NOT_SET` significa
            que a chave foi GUARDADA e a Meta não a confirmou, que é a única
            coisa que um 200 sozinho não conta. `replaced` diz se uma chave que
            estava VIVA acabou de ser deslocada — um 200 sozinho não diz
          content:
            application/json:
              examples:
                generated:
                  summary: >-
                    GERAR — par novo, registrado na Meta, substituindo uma chave
                    viva
                  value:
                    configured: true
                    publicKey: |
                      -----BEGIN PUBLIC KEY-----
                      MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
                      -----END PUBLIC KEY-----
                    uploadedAt: '2026-09-02T10:00:00.000Z'
                    endpointUrl: https://pilotstatus.com.br/api/flows/endpoint/AbC123...
                    metaStatus: VALID
                    replaced: true
                importedVerified:
                  summary: IMPORTAR — a Meta confirmou que a chave é a que ela tem
                  value:
                    configured: true
                    publicKey: |
                      -----BEGIN PUBLIC KEY-----
                      MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
                      -----END PUBLIC KEY-----
                    uploadedAt: '2026-09-02T10:00:00.000Z'
                    endpointUrl: https://pilotstatus.com.br/api/flows/endpoint/AbC123...
                    metaStatus: VALID
                    replaced: false
                importedUnverified:
                  summary: >-
                    IMPORTAR — guardada, mas a Meta NÃO confirmou (uploadedAt é
                    null)
                  value:
                    configured: true
                    publicKey: |
                      -----BEGIN PUBLIC KEY-----
                      MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
                      -----END PUBLIC KEY-----
                    uploadedAt: null
                    endpointUrl: https://pilotstatus.com.br/api/flows/endpoint/AbC123...
                    metaStatus: UNKNOWN
                    replaced: false
        '400':
          description: >-
            `FLOW_ENDPOINT_KEY_REQUIRES_CONFIRMATION` (gerar substituiria uma
            chave viva na Meta e `confirm: true` não foi enviado),
            `FLOW_ENDPOINT_KEY_IMPORT_REQUIRES_CONFIRMATION` (o mesmo portão no
            verbo de importar — o que seria substituído é a metade privada
            guardada aqui), `FLOW_ENDPOINT_KEY_IMPORT_MISMATCH` (a chave enviada
            não é a que a Meta tem; NADA foi escrito),
            `FLOW_ENDPOINT_KEY_IMPORT_INVALID`,
            `FLOW_ENDPOINT_KEY_PASSPHRASE_ORPHAN`,
            `FLOW_ENDPOINT_KEY_PASSPHRASE_REQUIRED`,
            `FLOW_ENDPOINT_KEY_PASSPHRASE_WRONG`,
            `FLOW_ENDPOINT_KEY_PEM_INVALID`, `FLOW_BODY_INVALID`,
            `FLOW_UNKNOWN_FIELDS`, `FLOW_NUMBER_FROM_KEY`, ou uma recusa da Meta
            repassada com a mensagem e o código dela
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    description: Portuguese half
                  errorEN:
                    type: string
                    description: English half
                  code:
                    type: string
              examples:
                requiresConfirmation:
                  summary: FLOW_ENDPOINT_KEY_REQUIRES_CONFIRMATION
                  value:
                    error: >-
                      Este número já tem uma chave registrada na Meta. Registrar
                      uma nova SUBSTITUI a atual e quebra todos os Flows
                      `data_exchange` deste número no instante em que a Meta
                      aceitar — envie `"confirm": true` (booleano, exatamente)
                      para prosseguir.
                    errorEN: >-
                      This number already has a key registered with Meta.
                      Registering a new one REPLACES it and breaks every
                      `data_exchange` Flow of this number the moment Meta
                      accepts it — send `"confirm": true` (a boolean, exactly)
                      to proceed.
                    code: FLOW_ENDPOINT_KEY_REQUIRES_CONFIRMATION
                importRequiresConfirmation:
                  summary: FLOW_ENDPOINT_KEY_IMPORT_REQUIRES_CONFIRMATION
                  value:
                    error: >-
                      Este número já tem uma chave em uso. Importar outra
                      SUBSTITUI a chave privada guardada aqui — e se a Meta não
                      confirmar a importada (indisponível, por exemplo), o
                      número fica com uma chave que pode não decifrar nada. Nada
                      é registrado na Meta por esta operação. Envie `"confirm":
                      true` (booleano, exatamente) para prosseguir.
                    errorEN: >-
                      This number already has a key in use. Importing another
                      REPLACES the private key stored here — and if Meta cannot
                      confirm the imported one (it being unreachable, say), the
                      number is left holding a key that may decrypt nothing.
                      Nothing is registered with Meta by this operation. Send
                      `"confirm": true` (a boolean, exactly) to proceed.
                    code: FLOW_ENDPOINT_KEY_IMPORT_REQUIRES_CONFIRMATION
                importMismatch:
                  summary: FLOW_ENDPOINT_KEY_IMPORT_MISMATCH
                  value:
                    error: >-
                      A chave privada enviada não corresponde à chave pública
                      que a Meta tem registrada para este número — guardá-la
                      deixaria o número sem conseguir decifrar nada, e a falha
                      só apareceria como um formulário que não avança. Importe a
                      chave correspondente à registrada, ou faça um POST sem
                      `privateKey` para gerar um par novo (isso SUBSTITUI o
                      registro na Meta).
                    errorEN: >-
                      The private key you sent does not match the public key
                      Meta has registered for this number — storing it would
                      leave the number unable to decrypt anything, and the
                      failure would only show up as a form that never advances.
                      Import the key matching the registered one, or POST
                      without `privateKey` to generate a fresh pair (which
                      REPLACES the registration at Meta).
                    code: FLOW_ENDPOINT_KEY_IMPORT_MISMATCH
                importInvalidField:
                  summary: FLOW_ENDPOINT_KEY_IMPORT_INVALID
                  value:
                    error: >-
                      `privateKey` deve ser a chave privada em PEM (string não
                      vazia) e `passphrase`, quando enviada, uma string.
                    errorEN: >-
                      `privateKey` must be the private key in PEM (a non-empty
                      string), and `passphrase`, when sent, a string.
                    code: FLOW_ENDPOINT_KEY_IMPORT_INVALID
                passphraseOrphan:
                  summary: FLOW_ENDPOINT_KEY_PASSPHRASE_ORPHAN
                  value:
                    error: >-
                      `passphrase` só faz sentido junto de `privateKey`. Sem
                      `privateKey` esta rota GERA um par novo e o registra na
                      Meta, substituindo o atual — não é o que uma passphrase
                      indica querer. Envie a chave, ou remova a passphrase.
                    errorEN: >-
                      `passphrase` only means something alongside `privateKey`.
                      Without `privateKey` this route GENERATES a new pair and
                      registers it with Meta, replacing the current one — which
                      is not what sending a passphrase suggests you meant. Send
                      the key, or drop the passphrase.
                    code: FLOW_ENDPOINT_KEY_PASSPHRASE_ORPHAN
                passphraseRequired:
                  summary: FLOW_ENDPOINT_KEY_PASSPHRASE_REQUIRED
                  value:
                    error: >-
                      A chave privada enviada está protegida por passphrase e
                      nenhuma foi informada. Envie `passphrase` junto de
                      `privateKey`.
                    errorEN: >-
                      The private key you sent is passphrase-protected and none
                      was given. Send `passphrase` alongside `privateKey`.
                    code: FLOW_ENDPOINT_KEY_PASSPHRASE_REQUIRED
                passphraseWrong:
                  summary: FLOW_ENDPOINT_KEY_PASSPHRASE_WRONG
                  value:
                    error: >-
                      A passphrase não abre a chave privada enviada. Confira a
                      passphrase — a chave em si não foi rejeitada, ela apenas
                      não foi aberta.
                    errorEN: >-
                      The passphrase does not open the private key you sent.
                      Check the passphrase — the key itself was not rejected, it
                      simply was not opened.
                    code: FLOW_ENDPOINT_KEY_PASSPHRASE_WRONG
                pemUnreadable:
                  summary: FLOW_ENDPOINT_KEY_PEM_INVALID (unreadable PEM)
                  value:
                    error: >-
                      Não foi possível ler `privateKey` como uma chave privada
                      PEM. Envie o conteúdo do arquivo `.pem` inteiro, incluindo
                      as linhas `-----BEGIN …-----` e `-----END …-----`.
                    errorEN: >-
                      `privateKey` could not be read as a PEM private key. Send
                      the whole `.pem` file contents, including the `-----BEGIN
                      …-----` and `-----END …-----` lines.
                    code: FLOW_ENDPOINT_KEY_PEM_INVALID
                pemNotRsa:
                  summary: FLOW_ENDPOINT_KEY_PEM_INVALID (not an RSA key)
                  value:
                    error: >-
                      A chave enviada não é RSA. A Meta cifra o `data_exchange`
                      com RSA/OAEP, e uma chave EC ou Ed25519 não decifra nada —
                      envie a chave RSA-2048 do número.
                    errorEN: >-
                      The key you sent is not RSA. Meta encrypts `data_exchange`
                      with RSA/OAEP, and an EC or Ed25519 key decrypts nothing —
                      send the number's RSA-2048 key.
                    code: FLOW_ENDPOINT_KEY_PEM_INVALID
                pemTooWeak:
                  summary: FLOW_ENDPOINT_KEY_PEM_INVALID (RSA under 2048 bits)
                  value:
                    error: >-
                      A chave RSA enviada é menor que 2048 bits. A Meta
                      especifica RSA-2048 e recusaria a chave — envie uma de
                      2048 bits ou mais.
                    errorEN: >-
                      The RSA key you sent is smaller than 2048 bits. Meta
                      specifies RSA-2048 and would refuse it — send one of 2048
                      bits or more.
                    code: FLOW_ENDPOINT_KEY_PEM_INVALID
        '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 `flows:manage`
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  code:
                    type: string
              example:
                error: >-
                  This endpoint acts on a single WhatsApp number: send the
                  x-whatsapp-number-id header naming the number to act on (its
                  id or instance id from GET /v1/numbers) | Este endpoint atua
                  sobre um único número de WhatsApp: envie o header
                  x-whatsapp-number-id indicando o número desejado (o id dele ou
                  o id da instância, obtidos em GET /v1/numbers)
                code: TENANT_SCOPE_NOT_ALLOWED
        '404':
          description: >-
            O `{id}` do caminho não é o número ao qual esta credencial está
            vinculada. Nunca 403: o número de outro tenant e outro número seu
            respondem o mesmo corpo, byte a byte, para que um id adivinhado
            nunca seja confirmado
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    description: Portuguese half
                  errorEN:
                    type: string
                    description: English half
                  code:
                    type: string
              example:
                error: >-
                  Número não encontrado para esta chave. Esta rota atua sobre o
                  número ao qual a chave está vinculada — use a chave do número
                  em questão, ou o header x-whatsapp-number-id se a chave for de
                  conta.
                errorEN: >-
                  Number not found for this key. This route acts on the number
                  the key is bound to — use that number's key, or the
                  x-whatsapp-number-id header if the key is an account-wide one.
                code: FLOW_NUMBER_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: Portuguese half
                  errorEN:
                    type: string
                    description: English half
                  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: >-
            `FLOW_ENDPOINT_KEY_UNAVAILABLE` (a cifra em repouso não está
            configurada, então o serviço se recusa a guardar a metade privada em
            claro — nos DOIS verbos, gerar e importar, ainda que a mensagem fale
            em gerar; uma falha de deploy sobre a qual quem chama não pode fazer
            nada) ou `INTERNAL_ERROR`
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    description: Portuguese half
                  errorEN:
                    type: string
                    description: English half
                  code:
                    type: string
              example:
                error: >-
                  Não foi possível gerar a chave do endpoint: o serviço não está
                  configurado para guardar a chave privada com segurança. Fale
                  com o suporte.
                errorEN: >-
                  Could not generate the endpoint key: the service is not
                  configured to store the private key safely. Contact support.
                code: FLOW_ENDPOINT_KEY_UNAVAILABLE
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)

````