MVOWHATSAPP API · PHP

UMA API. VÁRIAS CONEXÕES.

Conecte seus clientes.
O PHP mantém a conversa.

Conexões persistentes, mensagens e eventos usando a biblioteca MVO PHP. Cada instância tem identidade, credenciais, fila e chave de acesso próprias.

01 / PREPARE

Inicie a API

Execute composer serve. O supervisor administra os workers e retoma as instâncias marcadas para execução.

02 / IDENTIFIQUE

Crie uma instância

Use o token administrativo para criar um cliente em POST /v1/instances. Guarde a chave devolvida.

03 / CONECTE

Vincule o WhatsApp

Solicite um QR ou código. A mesma instância restaura um vínculo válido depois de reiniciar.

Entregue uma API para cada cliente

Uma instalação atende vários clientes. Crie uma instância por WhatsApp: cada uma recebe seu ID, token, credenciais e fila. A biblioteca é compartilhada; você não precisa copiar o projeto para cada cliente.

O administrador cria a instância

POST /v1/instances
Authorization: Bearer TOKEN_ADMINISTRATIVO
Content-Type: application/json

{"id":"cliente-01","name":"Cliente 01"}

A resposta HTTP 201 devolve instance, token e links, incluindo swagger, openapi, connect e messages. Guarde o token exibido na criação. Entregue ao cliente a URL base, seu ID, seu token e o link do Swagger. O token administrativo permanece com você.

O cliente testa e integra

Abra o Swagger de exemplo do cliente-01, substituindo o ID pelo cadastrado. Clique em Authorize e cole somente o token da instância, sem escrever Bearer. Depois abra uma operação, clique em Try it out, ajuste os dados e use Execute. O Swagger monta a autenticação e mostra a resposta e o cURL para integração.

Comece por GET /v1/instances/cliente-01, conecte o WhatsApp e então envie mensagens. O Swagger do cliente fixa seu ID, usa token no header e não inclui criação ou listagem global de instâncias. Seu token não autoriza operações de outro cliente. Ao recarregar a aba, autorize novamente; a chave não é persistida.

O Swagger geral inclui os contratos administrativos e legados. O OpenAPI da instância permite importar os mesmos contratos em outras ferramentas. Esses links levam somente documentação, sem credenciais ou dados da conta. Abrir a documentação não conecta o WhatsApp; clicar em Execute executa uma requisição real.

Qual endereço entregar?

http://127.0.0.1:8877 é o ambiente local deste computador. Para o cliente acessar de outro computador, publique a API no seu domínio HTTPS e entregue, por exemplo, https://api.sua-empresa.example/swagger/cliente-01, junto do token privado da instância.

Use o método de cada operação

O Swagger segue o mesmo contrato do servidor: GET consulta, POST cria, envia ou executa ações, PATCH altera campos, PUT define um valor e DELETE remove recursos. Nas consultas, preencha os parâmetros da query; não envie corpo JSON.

GET /v1/instances/cliente-01/operations/service.number?numero=5511999999999
GET /v1/instances/cliente-01/operations/product.list?limit=25

PATCH /v1/instances/cliente-01/operations/settings.messages.set
Content-Type: application/json
Authorization: Bearer TOKEN_DA_INSTANCIA

{"readMsgAuto":true}

Os exemplos de escrita mostram os identificadores em _params quando necessários; em consultas, use a query correspondente. Pedidos com token, consultas em lote e download de mídia continuam em POST para receber dados no corpo. Áudio/vídeo recebidos também usam POST, pois removem os quadros do buffer; HEAD não consome esses dados.

As chamadas anteriores com POST /operations/... e os métodos originais dos caminhos legados permanecem aceitos. O Swagger apresenta os métodos preferidos. Um método inválido retorna 405 method_not_allowed e o header Allow.

Conectar por QR Code

Autentique com a chave da instância. Atualize a imagem quando qr_version mudar; quando qrcode for nulo, remova a imagem expirada. O SVG vem pronto para usar em uma tag de imagem.

POST /v1/instances/cliente-01/connect
Authorization: Bearer TOKEN_DA_INSTANCIA
Content-Type: application/json

{"tipo":"qrcode"}

Para código, envie {"tipo":"codigo","numero":"5511999999999"}. Mantenha o polling conforme refresh_after_ms. A retomada também trata a atualização da versão Web após erro 405.

Enviar pela conexão existente

POST /v1/instances/cliente-01/messages
Authorization: Bearer TOKEN_DA_INSTANCIA
Content-Type: application/json
Idempotency-Key: pedido-123-confirmacao
Prefer: respond-async

{"type":"text","payload":{"messageData":{"numero":"5511999999999","text":"Olá pela MVO PHP!"}}}

O worker executa o comando. HTTP 202 devolve um job_id e status_url para acompanhar o resultado com o mesmo token; repita a mesma Idempotency-Key somente para o mesmo pedido e conteúdo. Confirmação do servidor, entrega e leitura são estados distintos.

Receber mensagens na sua aplicação

Cadastre destinos em PUT /v1/instances/cliente-01/webhooks. Configure um segredo para validar X-MVO-Signature por HMAC-SHA256.

{
  "tipo": "RECEBIDO",
  "instance_key": "cliente-01",
  "event": "message",
  "event_id": 42,
  "retorno": {
    "key": {"id":"ID_DA_MENSAGEM","remoteJid":"5511999999999@s.whatsapp.net","fromMe":false},
    "messageType": "conversation",
    "message": {"conversation":"Olá"}
  }
}

Há também GET /v1/instances/cliente-01/events?after=42, em JSON ou SSE. Webhooks usam HTTPS público por padrão; redes internas exigem configuração explícita.

Formulários sem cadastro Meta

Use message.form, POST /v1/instances/{id}/messages/form ou /messages com type: "form". O formulário nativo usa a sessão PHP existente e não exige flow_id, token de Flow, publicação na Meta ou endpoint externo. Escolhas foram abertas e concluídas no Web e Android; campos de texto foram abertos e enviados no Android. Os exemplos estão no grupo Mensagens do Swagger.

A rota tipada /messages/form foi testada de ponta a ponta, de maik para default, com duas etapas no Android: Nome e confirmação. O usuário confirmou o envio das duas; a API recebeu uma resposta autenticada versão 3, com citação e IDs correspondentes, nome preenchido e confirmação da segunda etapa.

Campo Nome no Android

POST /v1/instances/cliente-01/messages/form
Authorization: Bearer TOKEN_DA_INSTANCIA
Content-Type: application/json
Prefer: respond-async

{
  "messageData": {
    "numero": "5511999999999",
    "texto": "Informe seu nome.",
    "cta": "Abrir cadastro",
    "platform": "android",
    "steps": [{
      "id": "cadastro", "label": "Cadastro MVO", "kind": "input", "button": "Enviar",
      "fields": [{"id": "name", "label": "Nome", "type": "text", "required": true, "default": ""}]
    }]
  }
}

platform: "android" habilita campos de texto; a API recebeu uma resposta autenticada name: "Maik" citando a mensagem original no teste Android. Não há suporte Web confirmado para InputFields. Para escolhas, use o padrão platform: "portable", com selection: "single" ou "multiple" e options: [{"id":"suporte","title":"Suporte"}]. São permitidas até três etapas, com até cinco opções ou campos por etapa. IDs devem ser únicos; o CTA permite até 30 caracteres.

As respostas chegam no evento message como parsedFormResponse, com name: "form_message", version e params por ID de campo ou etapa. Webhooks trazem formResponse com os mesmos metadados e respostas em data. Correlacione pelo ID citado quando disponível; no Web versão 1, use IDs únicos de campo ou etapa se a citação estiver ausente. HTTP 202 informa que o comando foi enfileirado: acompanhe o job e os eventos.

Galaxy Flow inline

As operações message.flow e message.flow.navigate continuam disponíveis com flow_json. Esse formato foi concluído no Web e ainda apresentou erro no Android. Não há conversão silenciosa entre Galaxy Flow e formulário nativo.

No APK Android examinado, a ação do botão não encaminha flow_json para o modal; a navegação normal resolve metadados e a definição pelo ID. O APK oficial mais novo mantém a mesma seleção de campos. Um ensaio com o motor público e host Android simulado processou a definição gerada pelo PHP, mas não executou o APK. Ainda não há correção PHP verificada para o Galaxy inline no Android ou data_exchange sem registro remoto.

POST /v1/instances/cliente-01/operations/message.flow.navigate
Authorization: Bearer TOKEN_DA_INSTANCIA
Content-Type: application/json
Prefer: respond-async

{
  "messageData": {
    "numero": "5511999999999",
    "texto": "Preencha seu cadastro.",
    "cta": "Abrir cadastro",
    "flow_token": "cadastro-cliente-42",
    "flow_json": {
      "version": "7.3",
      "screens": [{
        "id": "INICIO", "title": "Cadastro MVO",
        "terminal": true, "success": true, "data": {},
        "layout": {"type": "SingleColumnLayout", "children": [{
          "type": "Form", "name": "form", "children": [
            {"type": "TextInput", "name": "name", "label": "Nome", "required": true},
            {"type": "Footer", "label": "Enviar", "on-click-action": {
              "name": "complete", "payload": {"name": "${form.name}"}
            }}
          ]
        }]}
      }]
    }
  }
}

Substitua o destinatário e use um flow_token para correlacionar o atendimento à resposta. Em POST /v1/instances/{id}/messages, use type: "flow.navigate" e esse corpo em payload. Para escolher outra tela inline, informe screen com um ID existente na definição; dados iniciais opcionais vão em data. Objetos {} são preservados após reiniciar a fila.

A definição inline pode ocupar até 256 KiB. O CTA permite até 30 caracteres; a versão da mensagem é 3 e a versão do JSON deste formulário é 7.3. A identidade local gerada não registra nem publica um Flow na Meta. Também aceitamos navigate por um flow_id publicado, com a tela correspondente.

message.flow.exchange exige o ID real de um Flow registrado com endpoint, metadados e chaves de troca de dados configurados. A biblioteca inclui internamente flow_metadata.data_api_version: "3.0" para solicitar a consulta e verificação da chave e assinatura do endpoint pelo cliente. O campo opcional data_api_version aceita somente "3.0" e também pode ser usado em navigate com endpoint registrado; é rejeitado em Flow inline. Exchange não aceita flow_json, screen, data ou flow_action_payload. A operação envia a referência, sem criar ou hospedar o endpoint; a troca de dados real ainda precisa de homologação.

O evento message inclui parsedFlowResponse quando recebe uma resposta válida, mantendo o JSON original. Webhooks compatíveis também oferecem flowResponse. HTTP 202 informa que o comando foi enfileirado: acompanhe o job e os eventos antes de repetir um envio incerto.

Galaxy inline verificado em 15/10/2026: o formulário enviado de maik para default abriu e concluiu no WhatsApp Web; a sessão recebeu a resposta autenticada name: "Teste MVO" com o token correspondente. O debug USB confirmou a interface nativa “Ocorreu um erro.” no Android 16 com WhatsApp 2.26.40.76. A análise do APK instalado confirmou que a ação Galaxy não encaminha flow_json ao modal e que o caminho analisado resolve a definição pelo ID. A pesquisa anterior nos APKs 2.26.40.77 e 2.26.39.79, com assinaturas verificadas, encontrou o carregamento por cache ou /json/{flow_id}. Isso pode explicar a diferença em relação ao Web: a identidade inline não é um registro remoto. Os valores de configuração e as respostas de rede do aparelho continuam desconhecidos. O logcat não expôs o código inicial. O stack de clearHistory foi localizado na limpeza da WebView; o aviso de URI about é compatível com about:blank nesse caminho, sem identificar a causa inicial. Ainda não há correção PHP confirmada para esse Galaxy inline no Android; a confirmação do transporte não comprova a abertura em todos os clientes.

O formulário nativo message.form tem contrato próprio e não é uma implementação de Galaxy data_exchange.

Gerencie os canais pela sua instância

Crie e configure canais públicos, consulte o diretório, gerencie seguidores, administradores e convites, publique texto, mídia e enquetes e acompanhe perguntas, reações, votos, fixação e atualizações. O grupo Canais do Swagger apresenta os contratos e o método HTTP de cada ação; o cliente utiliza /swagger/{id} e seu próprio token.

POST /v1/instances/cliente-01/channels
Authorization: Bearer TOKEN_DA_INSTANCIA
Content-Type: application/json
Prefer: respond-async
Idempotency-Key: meu-canal-criar-1

{"name":"Novidades MVO","description":"Avisos e novidades"}

POST /v1/instances/cliente-01/channels/120363000000000000@newsletter/posts/text
Authorization: Bearer TOKEN_DA_INSTANCIA
Content-Type: application/json
Prefer: respond-async

{"text":"Novidades da MVO!"}

Consulte o job_id retornado pelo HTTP 202. Use o JID @newsletter confirmado pelo WhatsApp; o ID acima é ilustrativo. A mesma sessão PHP executa todas as ações. Publicações usam mídia pública própria dos canais, com URL HTTPS ou base64 até 32 MiB; a foto do canal aceita até 8 MiB. Reações, votos, fixação e visualizações recebem o serverId numérico da publicação.

GET /channels/{channel_id}/posts consulta o histórico remoto; /posts/local lista o histórico observado e persistido na sessão. As rotas locais permitem consultar a publicação e baixar sua mídia sem receber URL arbitrária ou caminho interno. newsletter_message, newsletter_update e channel_update chegam pelos eventos, SSE e webhooks existentes. A assinatura POST /channels/{channel_id}/live informa seu prazo e precisa de renovação após expirar ou reconectar.

As permissões e os recursos disponíveis são decididos pelo WhatsApp. server_ack confirma o ACK correspondente; sent em reações, votos ou recibos indica somente o transporte. Os testes usam dados sintéticos e transportes locais, sem alterações em canais reais. O contrato interno das métricas avançadas insights depende da conta e não tem exemplo inventado nem homologação de servidor. As publicações temporárias /channels/{channel_id}/statuses pertencem ao canal; /statuses abaixo gerencia os Status pessoais.

Gerencie os Status do WhatsApp

Publique texto, imagem, vídeo e voz com destinatários explícitos. Consulte publicações próprias e recebidas, revogue seus Status, ajuste privacidade e silenciamento, envie respostas e reações e acompanhe os recibos de visualização observados. O grupo Status do Swagger traz 19 operações com exemplos.

POST /v1/instances/cliente-01/statuses/text
Authorization: Bearer TOKEN_DA_INSTANCIA
Content-Type: application/json
Prefer: respond-async

{"text":"Novidades da MVO!","recipients":["123456789@lid"],"statusSetting":"allowlist","style":{"backgroundColor":"#009BF5","textColor":"#FFFFFF"}}

Use GET /statuses/own e GET /statuses/received a partir da base da instância. As consultas mostram apenas os Status recebidos, sincronizados ou publicados por essa sessão; expirados e revogados são omitidos por padrão. A audiência utilizada fica salva para revogar uma publicação própria depois de reiniciar.

HTTP 202 fornece um job para acompanhar. O evento status chega pelos eventos e webhooks. Recibos de entrega não são visualizações, e a leitura automática de conversas não visualiza Status. Privacidade usa app-state autenticado; abrir a documentação não publica nem visualiza nada.

Gerencie suas comunidades

A conexão da instância administra comunidades, membros, administradores, convites, configurações, foto, subgrupos e solicitações. O Swagger oferece 39 operações no grupo Comunidades, com contratos específicos e exemplos de cada ação.

Crie e consulte pela mesma sessão

POST /v1/instances/cliente-01/communities
Authorization: Bearer TOKEN_DA_INSTANCIA
Content-Type: application/json
Idempotency-Key: comunidade-clientes-criar-1
Prefer: respond-async

{"subject":"Clientes MVO","options":{"description":"Avisos e atendimento","membershipApprovalMode":"request_required","createGeneralChat":true}}

GET /v1/instances/cliente-01/communities
Authorization: Bearer TOKEN_DA_INSTANCIA

Use o jid retornado pelo WhatsApp nas demais rotas, como 120363000000000000@g.us. Nome e descrição aceitam até 100 e 2.048 caracteres. Um HTTP 202 retorna o job a acompanhar; confira a conclusão e os resultados individuais antes de repetir alterações.

Organize membros e subgrupos

POST /v1/instances/cliente-01/communities/120363000000000000@g.us/members
Authorization: Bearer TOKEN_DA_INSTANCIA
Content-Type: application/json

{"participants":["123456789@lid"]}

POST /v1/instances/cliente-01/communities/120363000000000000@g.us/subgroups
Authorization: Bearer TOKEN_DA_INSTANCIA
Content-Type: application/json

{"subject":"Suporte MVO","participants":["123456789@lid"],"options":{"description":"Atendimento"}}

Liste membros e administradores com GET; promova ou rebaixe com PATCH; remova membros com DELETE. A criação de subgrupo vincula o pai no mesmo pedido. Vincule grupos existentes em POST .../subgroups/link com {"subgroup_ids":["120363000000000001@g.us"]}. Para solicitar vínculo oculto, use um item {"jid":"120363000000000001@g.us","hidden":true}. Desvincule em DELETE no mesmo caminho, usando IDs em string.

Consulte subgrupos em GET .../subgroups, participantes em GET .../subgroups/participants e sugestões em GET .../subgroups/suggestions. O parâmetro opcional source=mex na consulta de subgrupos preserva o envelope MEX original. Solicitações de entrada ficam em .../requests, com ações de aprovar, rejeitar e cancelar.

Convites e ações administrativas

GET .../invite consulta o convite, e POST .../invite/revoke renova o código. Para consultar um convite ou entrar, use POST /communities/invites/inspect ou POST /communities/join dentro da instância, com {"code":"CODIGO_DO_CONVITE"} no corpo. Solicitação pendente não é uma entrada aprovada.

Nome, descrição, foto e configurações usam PUT. Há transferência de propriedade, recurso de suspensão, saída e desativação. Essas ações seguem as permissões reais da conta; uma recusa do WhatsApp permanece um erro. No explorador, pesquise community. ou communities para ver os contratos.

Validação das comunidades.

Os testes locais cobrem protocolo IQ/MEX, contratos, isolamento por instância e falhas parciais. Esta entrega não criou comunidades nem alterou membros em contas reais. A disponibilidade no serviço atual e as permissões devem ser homologadas com uma conta autorizada.

Administre o WhatsApp Business

Produtos, coleções, carrinho, pedidos, perfil comercial, categorias, capa, etiquetas, respostas rápidas e listas de transmissão usam a conexão da própria instância. As operações comerciais são executadas pela biblioteca PHP e dependem das permissões da conta no WhatsApp.

Crie e atualize seus produtos

O CRUD HTTP recebe o preço na unidade principal da moeda: 19.99 vira 19990 no protocolo. A biblioteca, as consultas de catálogo e o envio legado de produto trabalham diretamente em milésimos. Imagens aceitam URL HTTPS pública ou base64.

POST /cliente-01/rest/produto/TOKEN_DA_INSTANCIA
Content-Type: application/json
Idempotency-Key: produto-plano-mvo-criar-1
Prefer: respond-async

{
  "name": "Plano MVO",
  "description": "Hospedagem para sua empresa",
  "images": [{"base64":"BASE64_DA_IMAGEM"}],
  "price": 19.99,
  "currency": "BRL",
  "isHidden": false,
  "originCountryCode": "BR"
}

Liste em GET /produto/TOKEN_DA_INSTANCIA. Para editar, use PATCH /produto/TOKEN_DA_INSTANCIA/PRODUCT_ID; campos não enviados são preservados, inclusive as imagens. Remova com DELETE /produto/TOKEN_DA_INSTANCIA/PRODUCT_ID. O campo isHidden controla a visibilidade.

Organize as coleções e o carrinho

POST /cliente-01/rest/produto/TOKEN_DA_INSTANCIA/catalogo/colecoes
Content-Type: application/json
Idempotency-Key: colecao-hospedagem-criar-1

{"name":"Hospedagem","products":["PRODUCT_ID"]}

PATCH /cliente-01/rest/produto/TOKEN_DA_INSTANCIA/catalogo/colecoes/COLLECTION_ID
Content-Type: application/json
Idempotency-Key: colecao-hospedagem-alterar-2

{"productsToAdd":["NOVO_PRODUCT_ID"],"productsToRemove":["PRODUCT_ID"]}

Consulte, exclua, solicite revisão e reordene coleções pelas rotas abaixo. Exclusões em lote preservam o resultado de cada ID; uma falha parcial retorna error=true. Ative o carrinho com PUT /produto/TOKEN_DA_INSTANCIA/catalogo/carrinho e {"enabled":true}; a resposta informa o estado observado no servidor.

Use etiquetas e respostas rápidas

POST /cliente-01/rest/business/TOKEN_DA_INSTANCIA/etiquetas
Content-Type: application/json
Idempotency-Key: etiqueta-interessados-criar-1

{"name":"Interessados","color":3}

PUT /cliente-01/rest/business/TOKEN_DA_INSTANCIA/etiquetas/ETIQUETA_ID/chat
Content-Type: application/json
Idempotency-Key: contato-etiqueta-associar-1

{"numero":"5511999999999","added":true}

Etiquetas, respostas rápidas e listas comerciais são sincronizadas por patches criptográficos com confirmação. As leituras retornam source=session_app_state, indicando os dados já sincronizados naquela sessão. Use added:false para remover uma associação. As listas comerciais podem receber telefones; a API exige seus LIDs confirmados antes de gravar.

Acompanhe cada alteração

HTTP 202
{"error":false,"status":"pending","job_id":"JOB_ID",
 "status_url":"/v1/instances/cliente-01/jobs/JOB_ID"}

GET /v1/instances/cliente-01/jobs/JOB_ID
Authorization: Bearer TOKEN_DA_INSTANCIA

Aguarde completed ou failed e confira result ou failure. Repetir a mesma Idempotency-Key com o mesmo comando e payload consulta o mesmo job. Se o resultado ficar outcome_unknown, confira o estado antes de reenviar. Webhooks devem ser validados por HMAC e deduplicados pelo event_id.

O perfil comercial aceita várias janelas de atendimento no mesmo dia, incluindo fechamento às 24:00. Busque categorias em GET /business/TOKEN_DA_INSTANCIA/categorias?query=internet&locale=pt_BR&version=V_2. No explorador, pesquise business, produto, colecoes ou etiquetas para encontrar os contratos.

Validação das operações Business.

Catálogo, coleções, carrinho e ferramentas comerciais têm testes locais de protocolo e confirmação. Parte das escritas de coleções e configuração de carrinho foi reconstruída de artefatos públicos do WhatsApp Web de 2024. A homologação no serviço atual e em contas Business reais permanece pendente; esta entrega não alterou contas comerciais reais.

Compatibilidade com limites claros.

Rotas anteriores disponíveis em /{instancia}/rest/.... Áudio e vídeo usam WebSocket na mesma porta pública, com tickets de uso único. Geração de links de chamada e cadastro mobile por SMS/ligação continuam retornando 501. Chamadas/mídia nativas exigem dependências opcionais; os testes de chamadas foram locais, sem uma chamada real. Abrir esta documentação não conecta uma conta.

Explore os contratos

Carregando OpenAPI…