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

# Disparar um flow do FlowBuilder para um número

> Dispara um flow (ativo e publicado) num ticket do contato — o disparador das ondas de reativação: consulte os cards perdidos em GET /v1/cards e dispare um flow por lead. Validações síncronas antes do 202: flow executável da conta (404/422), conexão da conta de canal whatsapp/waba (404/422) e guarda anti-atendimento: se o contato tem ticket aberto COM atendente humano na conexão, responde 409 com o ticketId — use force: true para sobrepor conscientemente. ATENÇÃO (janela 24h WABA): em conexão WABA, disparo frio fora da janela de 24h exige que o flow comece com nó de TEMPLATE — texto livre falha com erro Meta 131047 e o lead não recebe nada. Requer escopo `flows:trigger`.



## OpenAPI

````yaml /openapi/wapi-v1.pt.json post /v1/flows/trigger
openapi: 3.1.0
info:
  title: Whatix — API do Chat
  version: 1.0.0
  description: >-
    API pública do Whatix para integrar seus sistemas ao atendimento: enviar e
    ler mensagens, gerenciar contatos e tags, ler e mover cards de pipeline e
    disparar flows.


    ## Base URL

    Cada cliente tem a própria instância: `https://<sua-instancia>/wapi`. O
    playground usa a variável `instance`; o botão **Documentação** da tela *API
    do Chat* já a preenche.


    ## Autenticação

    `Authorization: Bearer wtx_live_…`. Tokens são criados por um admin em *API
    → Tokens*, com validade opcional e **escopos** no formato `recurso:ação`:


    | Recurso | Escopos | Endpoints |

    |---|---|---|

    | conversations | read | GET /v1/conversations |

    | messages | read, send | GET …/messages, GET /v1/messages/{id}/status ·
    POST /v1/messages/send, POST …/messages |

    | connections | read | GET /v1/connections |

    | contacts | read, write | GET/POST/PUT /v1/contacts…, GET /v1/tags |

    | cards | read, write | GET /v1/cards…, GET /v1/pipelines, GET
    /v1/lost-reasons · POST /v1/cards, PATCH …/stage |

    | flows | trigger | POST /v1/flows/trigger |


    Um escopo `write` inclui o `read` correspondente.


    ## Erros

    Sempre JSON: `{ "error": "<texto>", "code": "ERR_…" }`. Trate pelo `code`;
    `error` é texto pra humanos.


    | Código | HTTP | Quando acontece |

    |---|---|---|

    | `ERR_TOKEN_MISSING` | 401 | Header Authorization ausente. Envie
    `Authorization: Bearer wtx_live_…`. |

    | `ERR_TOKEN_INVALID` | 401 | O token não existe ou está mal formado. Gere
    um novo na tela API do Chat → Tokens. |

    | `ERR_TOKEN_REVOKED` | 401 | O token foi revogado no painel. Crie outro. |

    | `ERR_TOKEN_EXPIRED` | 401 | Passou da validade definida na criação. Crie
    outro ou rotacione antes de expirar. |

    | `ERR_SCOPE_MISSING` | 403 | O token é válido mas não tem o escopo exigido
    pelo endpoint. Um escopo `x:write` satisfaz `x:read`. |

    | `ERR_RATE_LIMITED` | 429 | Mais de 120 requisições por minuto com o mesmo
    token. Aguarde os segundos de `Retry-After`. |

    | `ERR_MISSING_CONTENT` | 400 | O envio precisa de pelo menos um entre
    `body`, `medias` (multipart) ou `templateData`. |

    | `ERR_NUMBER_REQUIRED` | 400 | O campo `number` é obrigatório. |

    | `ERR_NUMBER_INVALID` | 400 | O número não tem dígitos válidos após
    normalização. Use E.164 sem `+` (ex.: 5534999990000). |

    | `ERR_CONNECTION_NOT_FOUND` | 404 | `whatsappId`/`whatsappName` não
    corresponde a uma conexão desta conta. |

    | `ERR_NO_CONNECTION_AVAILABLE` | 404 | A conta não tem conexão padrão
    ativa. Informe `whatsappId` ou configure a conexão padrão no painel. |

    | `ERR_UNSUPPORTED_CHANNEL` | 422 | A conexão escolhida não é WhatsApp. Só
    canais `whatsapp` e `waba` enviam pela API. Em POST /v1/messages/send
    devolve 400; em POST /v1/flows/trigger, 422. |

    | `ERR_NO_TICKET_FOUND` | 404 | Conversa (ticket) inexistente ou de outra
    conta. |

    | `ERR_MISSING_NUMBER` | 400 | `number` é obrigatório no upsert de contato.
    |

    | `ERR_NUMBER_NOT_ON_WHATSAPP` | 422 | Com `validateNumber=true`, o número
    não existe no WhatsApp. |

    | `ERR_WHATSAPP_NOT_FOUND` | 404 | `whatsappId` informado não é uma conexão
    desta conta. |

    | `ERR_NO_CONTACT_FOUND` | 404 | Contato inexistente ou de outra conta. |

    | `ERR_NUMBER_IMMUTABLE` | 400 | `PUT /v1/contacts/{id}` não aceita
    `number`. Corrija o número pelo painel. |

    | `ERR_INVALID_TAG_IDS` | 400 | `tagIds` ausente ou não é array. Tags de
    outra conta são ignoradas em silêncio. |

    | `ERR_INVALID_TAGMODE` | 400 | A conta não usa etiquetas de contato (modo
    de tags configurado só para conversas). Ajuste o modo de tags no painel. |

    | `ERR_INVALID_DATE_FILTER` | 400 | Filtro de data sem offset de fuso (use
    `2026-09-01T00:00:00-03:00`). |

    | `ERR_NO_CARD_FOUND` | 404 | Card inexistente ou de outra conta. |

    | `ERR_CONTACT_IDENTIFIER_REQUIRED` | 400 | Informe exatamente um entre
    `contactId` e `phone` ao criar card. |

    | `ERR_PIPELINE_NOT_FOUND` | 404 | `pipelineId` inexistente ou de outra
    conta. |

    | `ERR_STAGE_REQUIRED` | 400 | `stageId` é obrigatório ao mover card. |

    | `ERR_STAGE_NOT_FOUND` | 404 | `stageId` inexistente ou de outra conta. |

    | `ERR_STAGE_NOT_IN_PIPELINE` | 422 | A etapa existe, mas pertence a outro
    pipeline. Mover entre pipelines não é permitido. |

    | `ERR_SOURCE_NOT_FOUND` | 404 | `sourceId` (origem do card) inexistente ou
    de outra conta. |

    | `ERR_SOURCE_REQUIRED_FOR_STAGE` | 400 | A etapa escolhida exige uma origem
    (`sourceId`). Informe-a ou use uma etapa que não exija. |

    | `ERR_FLOW_ID_AND_WHATSAPP_ID_REQUIRED` | 400 | `flowId` e `whatsappId` são
    obrigatórios. |

    | `ERR_VARIABLES_MUST_BE_OBJECT` | 400 | `variables` precisa ser um objeto
    JSON (chave → valor). |

    | `ERR_FLOW_NOT_FOUND` | 404 | Flow inexistente ou de outra conta. |

    | `ERR_FLOW_NOT_EXECUTABLE` | 422 | Flow inativo, despublicado ou sem nós.
    Publique-o no FlowBuilder. |

    | `ERR_TICKET_IN_HUMAN_SERVICE` | 409 | O contato está em atendimento humano
    ativo; o flow não é disparado pra não atropelar o atendente. |

    | `ERR_FEATURE_NOT_AVAILABLE` | 403 | Recurso não incluído no seu plano
    (middleware hasFeature). |

    | `ERR_STORAGE_LIMIT_REACHED` | 403 | Limite de armazenamento da instância
    atingido; envio de mídia bloqueado. |

    | `ERR_DUPLICATED_CONTACT` | 400 | Já existe outro contato com esse número.
    |

    | `ERR_CONTACT_NUMBER_IS_LID` | 400 | Número é um identificador @lid do
    WhatsApp, não um telefone. |


    Erros levantados pelos middlewares `hasFeature`/`checkStorage`
    (`ERR_FEATURE_NOT_AVAILABLE`, `ERR_STORAGE_LIMIT_REACHED`) vêm sem `code`
    hoje.


    ## Rate limit

    120 requisições por minuto por token. Toda resposta traz
    `X-RateLimit-Limit`, `X-RateLimit-Remaining` e `X-RateLimit-Reset` (epoch em
    segundos). Ao exceder: 429 com `Retry-After` em segundos.


    ## Paginação

    Listas aceitam `pageNumber` (1-based) e `pageSize` (default 40, máx. 100;
    mensagens: default 100, máx. 200) e devolvem `count` e `hasMore`. Valor de
    `pageSize` acima do máximo não dá erro — é limitado ao máximo em silêncio.
    Filtros de data (`createdAtAfter`/`createdAtBefore`,
    `closedAtAfter`/`closedAtBefore`) são inclusivos nos dois limites.


    ## Números

    E.164 **sem** `+`: DDI + DDD + número (`5534999990000`).


    ## Perguntas frequentes

    - **`wtx_test_` vs `wtx_live_`?** Só o prefixo do token muda — hoje não há
    diferença de comportamento entre os dois ambientes; os dois funcionam do
    mesmo jeito na API.

    - **Como listo as origens (`sourceId`)?** Não existe endpoint pra isso. Os
    nomes de origem vêm dentro de cada card (campo `source`) e são cadastrados
    no painel.

    - **Quais filtros aceitam múltiplos valores (CSV)?** Só `status`,
    `contactTagId` e `notContactTagId` de GET /v1/cards. `stageId`, `sourceId`,
    `pipelineId` e os demais IDs são sempre um único inteiro.

    - **Como contar cards por etapa sem paginar tudo?** Use `pageSize=1` com o
    filtro de `stageId` desejado e leia só o `count` da resposta.

    - **GET /v1/pipelines mostra todos os pipelines?** Sim — todos os pipelines
    da sua conta, sem filtro de visibilidade por usuário.

    - **O que a API devolve num erro interno (500)?** `{ "error": "Internal
    server error" }`, sem `code`. Trate como transitório e repita com backoff.

    - **O que é `stageEnteredAt`?** Quando o card entrou na etapa (`stage`)
    atual — é o que a plataforma usa pra medir estagnação.
servers:
  - url: https://{instance}/wapi
    description: Sua instância Whatix
    variables:
      instance:
        default: sua-instancia.whatix.cloud
        description: Domínio da sua instância (sem https://)
security:
  - bearerAuth: []
tags:
  - name: Conversas
    description: >-
      Conversas (tickets) da sua instância: listar, filtrar por status, fila,
      atendente.
  - name: Mensagens
    description: Enviar texto, mídia e templates; ler o histórico e o status de entrega.
  - name: Conexões
    description: Canais conectados (WhatsApp/WABA) e qual é o padrão de envio.
  - name: Contatos
    description: Cadastro por número, upsert idempotente, tags.
  - name: Cards
    description: >-
      Cards de pipeline (o que o painel chama de Pipelines): pipelines, etapas,
      motivos de perda.
  - name: Flows
    description: Disparar um flow publicado do FlowBuilder para um número.
paths:
  /v1/flows/trigger:
    post:
      tags:
        - Flows
      summary: Disparar um flow do FlowBuilder para um número
      description: >-
        Dispara um flow (ativo e publicado) num ticket do contato — o disparador
        das ondas de reativação: consulte os cards perdidos em GET /v1/cards e
        dispare um flow por lead. Validações síncronas antes do 202: flow
        executável da conta (404/422), conexão da conta de canal whatsapp/waba
        (404/422) e guarda anti-atendimento: se o contato tem ticket aberto COM
        atendente humano na conexão, responde 409 com o ticketId — use force:
        true para sobrepor conscientemente. ATENÇÃO (janela 24h WABA): em
        conexão WABA, disparo frio fora da janela de 24h exige que o flow comece
        com nó de TEMPLATE — texto livre falha com erro Meta 131047 e o lead não
        recebe nada. Requer escopo `flows:trigger`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - flowId
                - whatsappId
                - number
              properties:
                flowId:
                  type: integer
                whatsappId:
                  type: integer
                  description: Conexão (canal whatsapp/waba) da conta.
                number:
                  type: string
                  description: Telefone do contato (E.164 ou variantes BR).
                contactName:
                  type: string
                  description: Nome usado se o contato for criado.
                variables:
                  type: object
                  additionalProperties: true
                  description: >-
                    Reservado; hoje não chega ao flow. O valor é aceito e
                    registrado no evento de disparo, mas o executor do
                    FlowBuilder não lê `variables` — o flow só enxerga as
                    variáveis nativas do contato/conversa (`{{nome}}`,
                    `{{telefone}}`, `{{protocolo}}`, `{{data}}`, `{{hora}}`).
                    Para levar um dado seu ao flow, grave-o no contato via POST
                    /v1/contacts (`extraInfo`) antes de disparar.
                force:
                  type: boolean
                  default: false
                  description: Sobrepõe a guarda de atendimento humano ativo (409).
            example:
              flowId: 12
              whatsappId: 2
              number: '5534992341048'
      responses:
        '202':
          description: Flow validado e disparado em background no ticket devolvido.
          headers:
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
          content:
            application/json:
              schema:
                type: object
                properties:
                  requestId:
                    type: string
                  accepted:
                    type: boolean
                  ticketId:
                    type: integer
                  contactId:
                    type: integer
              example:
                requestId: req_8a41f0
                accepted: true
                ticketId: 4933
                contactId: 612
        '400':
          description: >-
            `ERR_FLOW_ID_AND_WHATSAPP_ID_REQUIRED`: `flowId` e `whatsappId` são
            obrigatórios. · `ERR_NUMBER_REQUIRED`: O campo `number` é
            obrigatório. · `ERR_VARIABLES_MUST_BE_OBJECT`: `variables` precisa
            ser um objeto JSON (chave → valor).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: ERR_FLOW_ID_AND_WHATSAPP_ID_REQUIRED
                code: ERR_FLOW_ID_AND_WHATSAPP_ID_REQUIRED
        '401':
          description: >-
            `ERR_TOKEN_MISSING`: Header Authorization ausente. Envie
            `Authorization: Bearer wtx_live_…`. · `ERR_TOKEN_INVALID`: O token
            não existe ou está mal formado. Gere um novo na tela API do Chat →
            Tokens. · `ERR_TOKEN_REVOKED`: O token foi revogado no painel. Crie
            outro. · `ERR_TOKEN_EXPIRED`: Passou da validade definida na
            criação. Crie outro ou rotacione antes de expirar.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Token não fornecido
                code: ERR_TOKEN_MISSING
        '403':
          description: >-
            `ERR_SCOPE_MISSING`: O token é válido mas não tem o escopo exigido
            pelo endpoint. Um escopo `x:write` satisfaz `x:read`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Token sem permissão para esta ação
                code: ERR_SCOPE_MISSING
        '404':
          description: >-
            `ERR_FLOW_NOT_FOUND`: Flow inexistente ou de outra conta. ·
            `ERR_CONNECTION_NOT_FOUND`: `whatsappId`/`whatsappName` não
            corresponde a uma conexão desta conta.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: ERR_FLOW_NOT_FOUND
                code: ERR_FLOW_NOT_FOUND
        '409':
          description: >-
            `ERR_TICKET_IN_HUMAN_SERVICE`: O contato está em atendimento humano
            ativo; o flow não é disparado pra não atropelar o atendente. · Corpo
            achatado `{ error, code, ticketId }`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: ERR_TICKET_IN_HUMAN_SERVICE
                code: ERR_TICKET_IN_HUMAN_SERVICE
        '422':
          description: >-
            `ERR_FLOW_NOT_EXECUTABLE`: Flow inativo, despublicado ou sem nós.
            Publique-o no FlowBuilder. · `ERR_UNSUPPORTED_CHANNEL`: A conexão
            escolhida não é WhatsApp. Só canais `whatsapp` e `waba` enviam pela
            API. Em POST /v1/messages/send devolve 400; em POST
            /v1/flows/trigger, 422.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: ERR_FLOW_NOT_EXECUTABLE
                code: ERR_FLOW_NOT_EXECUTABLE
        '429':
          description: >-
            `ERR_RATE_LIMITED`: Mais de 120 requisições por minuto com o mesmo
            token. Aguarde os segundos de `Retry-After`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: Limite de requisições excedido
                code: ERR_RATE_LIMITED
          headers:
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
            Retry-After:
              $ref: '#/components/headers/Retry-After'
      security:
        - bearerAuth: []
components:
  headers:
    X-RateLimit-Limit:
      schema:
        type: integer
      description: Quantas requisições o token pode fazer por minuto.
    X-RateLimit-Remaining:
      schema:
        type: integer
      description: Quantas requisições ainda restam na janela atual.
    X-RateLimit-Reset:
      schema:
        type: integer
      description: Epoch (segundos) em que a janela de rate limit atual reseta.
    Retry-After:
      schema:
        type: integer
      description: >-
        Só no 429: segundos até poder tentar de novo (igual ao campo
        `retryAfter` do corpo).
  schemas:
    Error:
      type: object
      required:
        - error
      additionalProperties: true
      description: >-
        Corpo plano `{ error, code, ...extras }`: extras aparecem na raiz —
        `retryAfter` (429), `requiredScope` (403), `ticketId` (409), `param`
        (filtro de data inválido). Não existe objeto `details`.
      properties:
        error:
          type: string
          description: >-
            Texto do erro (em ~22 códigos é o próprio código). Não faça match
            nele; use `code`.
        code:
          type: string
          enum:
            - ERR_TOKEN_MISSING
            - ERR_TOKEN_INVALID
            - ERR_TOKEN_REVOKED
            - ERR_TOKEN_EXPIRED
            - ERR_SCOPE_MISSING
            - ERR_RATE_LIMITED
            - ERR_MISSING_CONTENT
            - ERR_NUMBER_REQUIRED
            - ERR_NUMBER_INVALID
            - ERR_CONNECTION_NOT_FOUND
            - ERR_NO_CONNECTION_AVAILABLE
            - ERR_UNSUPPORTED_CHANNEL
            - ERR_NO_TICKET_FOUND
            - ERR_MISSING_NUMBER
            - ERR_NUMBER_NOT_ON_WHATSAPP
            - ERR_WHATSAPP_NOT_FOUND
            - ERR_NO_CONTACT_FOUND
            - ERR_NUMBER_IMMUTABLE
            - ERR_INVALID_TAG_IDS
            - ERR_INVALID_TAGMODE
            - ERR_INVALID_DATE_FILTER
            - ERR_NO_CARD_FOUND
            - ERR_CONTACT_IDENTIFIER_REQUIRED
            - ERR_PIPELINE_NOT_FOUND
            - ERR_STAGE_REQUIRED
            - ERR_STAGE_NOT_FOUND
            - ERR_STAGE_NOT_IN_PIPELINE
            - ERR_SOURCE_NOT_FOUND
            - ERR_SOURCE_REQUIRED_FOR_STAGE
            - ERR_FLOW_ID_AND_WHATSAPP_ID_REQUIRED
            - ERR_VARIABLES_MUST_BE_OBJECT
            - ERR_FLOW_NOT_FOUND
            - ERR_FLOW_NOT_EXECUTABLE
            - ERR_TICKET_IN_HUMAN_SERVICE
            - ERR_FEATURE_NOT_AVAILABLE
            - ERR_STORAGE_LIMIT_REACHED
            - ERR_DUPLICATED_CONTACT
            - ERR_CONTACT_NUMBER_IS_LID
          description: Código estável do erro.
        retryAfter:
          type: integer
          description: >-
            Só no 429: segundos até poder tentar de novo (igual ao header
            Retry-After).
        requiredScope:
          type: string
          description: 'Só no 403: escopo que o token não tem.'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Token criado em API → Tokens no painel. Prefixo `wtx_live_` (ou
        `wtx_test_`).

````