# WHMCS reconciliation (Phase E)

HexaHost GameCloud compares WHMCS service links with server state and reports drift.

## API endpoints

| Method | Path | Purpose |
|--------|------|---------|
| `GET` | `/integrations/whmcs/accounts` | ListAccounts sync payload |
| `POST` | `/integrations/whmcs/services/import` | Link an existing GameCloud server |
| `POST` | `/integrations/whmcs/reconcile` | Full installation reconciliation |
| `POST` | `/integrations/whmcs/services/:id/reconcile` | Single-service reconciliation |
| `GET` | `/integrations/whmcs/events` | Cursor-based event poll |
| `POST` | `/integrations/whmcs/events/ack` | Acknowledge or dead-letter events |

## Reconciliation checks

- Suspended link without billing suspension
- Active link with billing suspension
- Terminated link with non-deleted server
- Running server while suspended
- Plan / RAM mismatch (when expected values provided)
- Orphan servers (WHMCS client without service link)
- Missing join slug (info)

## Severity

`INFO`, `WARNING`, `BLOCKING`, `DESTRUCTIVE`, `SECURITY`

Automatic repair (`autoRepair: true`, `dryRun: false`) only applies safe fixes:

- Apply billing suspension when link is suspended
- Clear billing suspension when WHMCS reports Active
- Block running servers that should be suspended

## Events

GameCloud emits:

- `reconciliation_required` — blocking/security issues found
- `usage_period_ready` — previous UTC month closed (worker)

WHMCS should poll `GET /events`, process payloads, then `POST /events/ack`. Failed events can be dead-lettered.

## PHP module

- `hexagamecloud_ListAccounts()` — server sync
- `ApiClient::reconcileService()` / `reconcileAll()`
- `ApiClient::importService()` for controlled imports

## Worker

Daily at 03:00 UTC the worker runs a lightweight reconciliation pass for all active installations.
