Documenta arquitectura, mapeamento de IDs e contratos API para ponte bidireccional entre portal wizard, Desk ops e FOSSBilling Support. Co-authored-by: Cursor <cursoragent@cursor.com>
4.4 KiB
Contrato — API Sincronização Tickets Desk ↔ FOSS
Spec: 044
VM122: Desk API · VM123: FOSSBilling Admin API
Status: 📋 Especificado — implementação pendente
1. Desk → FOSS — criar espelho
Quando: ticket Desk criado ou escalado e external_customer_id disponível.
foss_client.create_support_ticket() (novo módulo VM122)
POST https://financeiro.ligbox.com.br/api/admin/support/ticket_create
Auth: Basic admin@ligbox.com.br:{FOSS_ADMIN_API_KEY}
Content-Type: application/x-www-form-urlencoded
| Campo FOSS | Origem Desk |
|---|---|
client_id |
billing_accounts.external_customer_id |
subject |
tickets.subject |
content |
Primeira nota + link Desk + OB- se existir |
helpdesk |
Ligbox Ops (departamento default) |
priority |
mapa Desk priority → FOSS |
Resposta esperada: { "result": { "id": 42 } } → gravar foss_ticket_id=42.
Idempotência: antes de criar, GET ticket by desk_ticket_id em cache local ou custom field FOSS desk_ticket_id.
2. FOSS → Desk — webhook inbound
POST /api/v1/webhooks/foss/support
Auth: header X-Foss-Webhook-Secret: {FOSS_WEBHOOK_SECRET}
Content-Type: application/json
Payload
{
"event": "ticket.reply",
"foss_ticket_id": 42,
"client_id": 17,
"domain": "empresa.com.br",
"subject": "Problema DNS",
"status": "open",
"message": "Cliente respondeu: ainda não resolveu",
"author": "client",
"created_at": "2026-07-01T18:05:00Z"
}
event |
Acção Desk |
|---|---|
ticket.opened |
Criar ticket Desk se não existir (cliente abriu no FOSS) |
ticket.reply |
Append nota interna + notificar assignee |
ticket.closed |
UPDATE tickets SET status='closed' |
ticket.reopened |
status='open' |
Response 200
{
"ok": true,
"desk_ticket_id": 45,
"handled": true,
"duplicate": false
}
Erros
| HTTP | Condição |
|---|---|
| 401 | Secret inválido |
| 404 | foss_ticket_id sem correlação e client_id desconhecido |
| 409 | Evento duplicado (idempotência) |
3. Desk — API staff (fase E)
POST /api/v1/support/tickets
Auth: JWT Desk · roles: technician+, sales_support+
{
"domain": "empresa.com.br",
"subject": "Webmail inacessível",
"body": "Cliente reporta erro 502",
"mirror_foss": true,
"wizard_ticket_id": null
}
Fluxo:
- Resolve
billing_accountspordomain - INSERT
tickets - Se
mirror_foss=trueeexternal_customer_id→foss_client.create_support_ticket() - Return
{ desk_ticket_id, foss_ticket_id, tracking_url }
GET /api/v1/support/tickets/{id}/sync-status
Retorna estado sync FOSS + links.
4. Portal VM112 — sem alteração v1
Endpoints existentes mantidos:
| Método | Path | Notas |
|---|---|---|
POST |
/api/onboarding/support/ticket |
Cria OB- + webhook Desk |
GET |
/api/onboarding/support/ticket/{OB-}/public |
Portal cliente Spec 026 |
Extensão fase E: resposta inclui desk_ticket_id quando sync completo (opcional, não bloqueia cliente).
5. FOSS — configuração webhook (VM123)
Opções (escolher uma na implementação):
| Opção | Prós | Contras |
|---|---|---|
| A Hook PHP FOSS custom | Tempo real | Requer patch container |
B Cron Desk poll support/ticket_get_list |
Sem patch FOSS | Latência 1–5 min |
| C Traefik + sidecar notifier | Desacoplado | Mais infra |
Recomendação v1: Opção B (poll) + Opção A quando estável.
6. Variáveis ambiente (VM122)
| Variável | Descrição |
|---|---|
FOSSBILLING_URL |
https://financeiro.ligbox.com.br |
FOSS_ADMIN_EMAIL |
Conta M2M admin |
FOSS_ADMIN_API_KEY |
API key FOSS (Spec 027) |
FOSS_WEBHOOK_SECRET |
Validação inbound FOSS→Desk |
FOSS_TICKET_SYNC_ENABLED |
true / false feature flag |
7. Testes curl
# Webhook simulado FOSS → Desk
curl -s -X POST https://desk.ligbox.com.br/api/v1/webhooks/foss/support \
-H "X-Foss-Webhook-Secret: $FOSS_WEBHOOK_SECRET" \
-H "Content-Type: application/json" \
-d '{
"event": "ticket.reply",
"foss_ticket_id": 42,
"client_id": 17,
"domain": "empresa.com.br",
"message": "Teste sync Spec 044"
}'
Histórico
| Versão | Data | Notas |
|---|---|---|
| 1.0 | 2026-07-01 | Contrato inicial Spec 044 |