# Customer authentication

If your support portal uses **general login** (your own username/password store), the platform calls *your* endpoint to authenticate a portal customer:

```json
{ "event": "customer.authenticate", "mode": "credentials", "username": "ada@example.com",
  "credentials": "<AES-256-GCM ciphertext>", "timestamp": 1765449600000 }
```

- The request is HMAC-signed like every signed webhook **and** the credential fields are end-to-end encrypted with AES-256-GCM, keyed by HKDF of the same shared secret, so the password never appears in plaintext.
- Timeout is 5 s and the flow **fails closed**: no reply, or a non-2xx, means sign-in is denied.
- Respond `200` with your customer's identity to approve. Full request/response contract and the decrypt snippet live in the support-portal integration docs (`docs/support-portal/customer-authentication.md` in your onboarding pack).

Alternatives that avoid implementing this endpoint: **link mode** (your backend mints single-use sign-in links via [Support Tickets → Mint customer sign-in link](/support-tickets)) or hosted SSO.
