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

# Portal e acesso do cliente

> Painel web em /painel/, link de acesso por tenant e a fatia da API admin que o cliente pode usar.

O ZapMeow serve um painel em `/painel/` (a raiz `/` redireciona para ele; o `/dashboard/` antigo, da chave de API, continua). Ele tem duas entradas:

* **Admin Glow**: entra com `ZAPMEOW_ADMIN_KEY`. Vê todos os tenants, cria clientes, gera links de acesso, gere sessões, canal do Backoffice, papéis, grupos e, com **Cliente GHL**, abre qualquer tenant para ver o que o cliente vê.
* **Cliente**: entra com um **link de acesso** do próprio tenant. Conecta o GoHighLevel e o WhatsApp, ajusta a IA e o áudio, escolhe o modo das ações no CRM, monta o fluxo por estágio e aprova pedidos.

O painel é HTML e módulos JS embutidos (sem build), com dois temas: Notion para o cliente e tokens da Glow para o admin.

## Link de acesso

| Método e rota (chave admin) | O que faz |
| - | - |
| `POST /admin/tenants/{id}/portal-token` | gera um token novo (`zmp_…`) e invalida o anterior. Responde `{token, path}`; **o valor aparece só nesta resposta** (o banco guarda o SHA-256) |
| `DELETE /admin/tenants/{id}/portal-token` | revoga (`204`) |

O link é `https://<servidor>/painel/#t=<token>`: o token vai no fragmento, que o navegador não envia ao servidor, e o painel o tira da barra de endereço ao abrir. `GET /admin/tenants` passa a trazer `portalAccess` (tem link ativo). `GET /admin/sessions` lista todas as sessões com o `tenantId` de cada uma.

## `/portal`: a fatia do cliente

`/portal/{rota}` com `X-Portal-Token` (ou `Authorization: Bearer`) vira `/admin/tenants/{tenant do token}/{rota}`, depois de passar por uma **lista fechada**. O token só enxerga o próprio tenant; o caminho nunca carrega o id.

| Libera | Rotas | |
| - | - | - |
| Identidade | `GET /portal/me` | |
| Config | `GET /config`, `GET /config/{seção}`, `PUT /config/{voice, humanizer, roles, tools}` | |
| Sessões | `GET /sessions`, `POST /sessions` (nome começa por `{tenant}-`, nunca move sessão alheia, sem webhook próprio) | |
| Uma sessão do tenant | `/s/{sessão}/…`: `start`, `restart`, `stop`, `logout`, `auth/qr`, `auth/request-code`, `groups/…`, `outbox/…`, `status`. Sessão de outro tenant responde `404` | |
| GoHighLevel | `GET/DELETE /ghl`, `GET /ghl/install-url`, `PUT /ghl/pit`, `POST /ghl/sync`, `GET /ghl/{pipelines, fields, opportunities, tools, pending}`, `POST /ghl/tools/{tool}`, \`POST /ghl/pending/{id}/approve | reject\` |
| Fluxo | `/flows` e tudo abaixo (desenho, estado, sombra, eventos, conversas, simulação) | |
| Log | `GET /toollog` | |

**Fica só com a chave admin** (`403` no portal): cofre de segredos, criar/alterar/apagar tenant, o **decisor** do fluxo (`PUT /config/flow`: a URL dele é chamada pelo servidor; o cliente só lê), o token de portal e as rotas de mensagem (`sendText`…).

Os mesmos caminhos `/s/{sessão}/…` existem na API admin, em `/admin/tenants/{id}/s/{sessão}/…`: o painel usa as duas com o mesmo código.

## Instalação do GHL

Para o botão **Conectar com GoHighLevel** voltar ao painel, defina `GHL_POST_INSTALL_URL=https://<servidor>/painel/`. Sem `GHL_CLIENT_ID`/`GHL_CLIENT_SECRET` o painel oferece o token de integração privada (PIT) no lugar do OAuth.

## O que o painel não faz (ainda)

* A calibragem de risco do passo 3 de **Conectar** é só orientação: o teto de envios é aplicado por quem envia (Backoffice ou fluxo), não pelo ZapMeow.
* Não há botão de ligação de teste: `POST /api/{sessão}/call` pede a chave de API, que o painel não guarda.
* O segredo e a URL do webhook do Convex são variáveis de ambiente e não aparecem no painel.


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