Nazeel API
The contract is openapi.yaml. Base path /api/v1.
Authentication
- Browser:
GET /api/v1/auth/oidc/loginor/auth/saml/loginredirects to the IdP; the callback sets thenazeel_sessioncookie. - CLI:
nazeel loginopens the dashboard, which callsPOST /auth/cli/tokenand hands a 30-day token to the CLI's localhost callback. Send it asAuthorization: Bearer. - First run:
NAZEEL_BOOTSTRAP_TOKENacts as an admin until SSO is configured. - Local accounts:
POST /auth/password/loginwith email and password, answeringok,mfa_requiredormfa_enrol_required. Ten failed attempts on one account in fifteen minutes locks it for fifteen; sixty from one address blocks the address.
Things a client has to get right
CSRF. A cookie-authenticated request that changes anything must carry an Origin or
Referer the API recognises. Bearer-token clients are unaffected.
Side-effecting GETs refuse the cookie entirely (terminal, audit export, logs,
recordings). A browser will issue those cross-origin, so a cookie there would be exploitable
from any page. Use a bearer token, or mint a single-use 60-second ticket with
POST /auth/ticket and pass it as a query parameter.
Sessions are revocable. Every token carries a jti that is checked against the sessions
table on each request, so revocation takes effect immediately rather than at expiry.
GET /me/sessions, DELETE /me/sessions/{jti}, POST /me/sessions/revoke-all (which
spares the calling session).
Empty lists are [], never null. If you find one that is not, it is a bug.
Errors
{"code": "nazeel.env.quota.perUser", "params": {"owner": "amr", "current": "3", "max": "3"}}
Admission failures carry causes[], one per rule, each with field, code, params.
Render texts from api/pkg/i18n (Render(lang, code, params)), English and Arabic.
Licence
PUT /licence {"key": "NZL2...."}, and NZL1. keys are still accepted. States: valid,
grace, expired, invalid, missing. Issue keys with nazeel-licence issue (vendor
only).
Expired or missing refuses creating, extending and syncing environments, and nothing else:
waking, previews, sign-in and the audit log all keep working. A licensed feature that is
absent answers 402 with the feature name in params, which a client should render as
"not in your plan" rather than as an error. GET /licence/usage-report returns a signed
report of monthly active seats.
Audit
GET /audit (admin), GET /audit/verify, GET /audit/export (signed evidence package),
PUT /settings/siem for syslog or HTTP forwarding. Entries are hash-chained and can never
be altered or deleted.