# Contrato — API Sincronização Tickets Desk ↔ FOSS

**Spec:** [044](../spec.md)  
**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

```json
{
  "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

```json
{
  "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+`

```json
{
  "domain": "empresa.com.br",
  "subject": "Webmail inacessível",
  "body": "Cliente reporta erro 502",
  "mirror_foss": true,
  "wizard_ticket_id": null
}
```

**Fluxo:**
1. Resolve `billing_accounts` por `domain`
2. INSERT `tickets`
3. Se `mirror_foss=true` e `external_customer_id` → `foss_client.create_support_ticket()`
4. 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

```bash
# 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 |
