Apps
Apps sao as aplicacoes consumidoras (seu CRM, atendimento, chatbot). Cada app tem api_key e webhook_secret. Todos endpoints aqui exigem admin key.
POST /v1/apps
Cria app + gera credenciais.
POST /v1/appsAuthorization: Bearer ADMIN_KEYContent-Type: application/json
{ "name": "MeuZap CRM", "webhook_url": "https://meuzap.com/wpphub-webhook"}201 Created:
{ "id": "01HZTQAPP01...", "name": "MeuZap CRM", "api_key_prefix": "ak_live", "api_key": "ak_live_4f2a8b9c123...", // ⚠️ MOSTRADA UNICA VEZ "webhook_secret": "whsec_xyz...", // ⚠️ MOSTRADO UNICA VEZ "webhook_url": "https://meuzap.com/wpphub-webhook", "is_active": true, "created_at": "...", "updated_at": "..."}api_key e webhook_secret so aparecem agora. Hub guarda apenas hash SHA-256. Se perder, recrie a app.
GET /v1/apps
Lista (sem paginacao).
{ "data": [ { "id": "...", "name": "MeuZap CRM", "api_key_prefix": "ak_live_4f2a", "webhook_url": "https://meuzap.com/...", "is_active": true, "created_at": "...", "updated_at": "..." } ]}api_key_prefix e os 12 primeiros chars — pra identificar em log sem expor a key inteira.
GET /v1/apps/:id
Mesmo schema do item.
PATCH /v1/apps/:id
Atualiza webhook_url. Audita em audit_events (campo before/after).
PATCH /v1/apps/01HZTQ...Authorization: Bearer ADMIN_KEYContent-Type: application/json
{ "webhook_url": "https://novo.endpoint.com/whk" }DELETE /v1/apps/:id
Soft delete (is_active=false). Webhooks param de ser entregues; deliveries pendentes sao canceladas.
204 No Content.
POST /v1/apps/:id/rotate-api-key
Gera nova api_key e invalida a anterior imediatamente. Retorna a chave plain uma unica vez — apos resposta, so o hash fica no DB.
POST /v1/apps/01HZTQAPP.../rotate-api-keyAuthorization: Bearer ADMIN_KEY{ "id": "01HZTQAPP...", "name": "MeuZap", "api_key_prefix": "ak_live_9xY", "api_key": "ak_live_9xY3...full-secret-AQUI...", "webhook_url": "https://meuzap.example.com/webhook", "is_active": true, "created_at": "...", "updated_at": "..."}Quando usar: comprometimento conhecido da key (vazou em log, repo, screenshot), quarterly rotation, offboarding de devs com acesso ao secret. Apos chamada, qualquer request com a key antiga retorna 401. Audit app.rotate_api_key registra a operacao.
POST /v1/apps/:id/rotate-webhook-secret
Gera novo webhook_secret (HMAC) e invalida o anterior. Retorna o secret plain uma unica vez.
POST /v1/apps/01HZTQAPP.../rotate-webhook-secretAuthorization: Bearer ADMIN_KEY{ "id": "01HZTQAPP...", "name": "MeuZap", "webhook_secret": "whsec_a1b2c3d4...full-secret-AQUI...", "webhook_url": "https://meuzap.example.com/webhook", "is_active": true, "created_at": "...", "updated_at": "..."}Importante: propagar o novo secret pro receptor antes que o proximo delivery saia. Deliveries enviados apos a rotacao sao assinados com o secret novo — receptor com secret antigo retorna signature mismatch e o delivery vai pra retry exponencial. Audit app.rotate_webhook_secret registra a operacao.
GET /v1/apps/:id/accesses
Lista vinculos com chips (app_chip_access).
{ "data": [ { "app_id": "...", "chip_id": "...", "can_send": true, "can_receive": true, "receive_self_chat": false, "transcribe_audio_mode": "off", "transcribe_audio_jids": [], "priority": 100, "created_at": "..." } ]}POST /v1/app-chip-access
Cria vinculo (upsert).
POST /v1/app-chip-accessAuthorization: Bearer ADMIN_KEYContent-Type: application/json
{ "app_id": "01HZTQAPP...", "chip_id": "01HZTQCHIP...", "can_send": true, "can_receive": true, "receive_self_chat": false, "transcribe_audio_mode": "off", // 'off' | 'all' | 'whitelist' "transcribe_audio_jids": [] // JIDs pra transcricao parcial (so quando mode='whitelist')}DELETE /v1/app-chip-access/:appId/:chipId
Revoga vinculo. App perde acesso ao chip imediatamente.