Authentication¶
Credentials¶
Every request to https://dev.aeliam.ai/api/v1/public/* must carry an API key, via either header:
Keys are created in the cabinet console (/cabinet/api-keys) and shown once. Format:
aelm_<env>_<random> (aelm_dev_…, aelm_sandbox_…, aelm_prod_…). Aeliam stores only a hash,
never the clear key.
Introspect the current key with GET /me:
{
"key_id": "…",
"cabinet_id": "…",
"scopes": ["crm:read", "devis:read"],
"environment": "dev",
"rate_limit": { "limit": 1000, "remaining": 999, "reset_at_ts": 1779993600 }
}
Scopes¶
A key carries a subset of scopes, chosen at creation. Endpoints enforce the scope they need.
| Scope | Grants |
|---|---|
crm:read |
Read opportunities |
crm:write |
Create / update opportunities and clients |
devis:read |
Read quotes and clients |
devis:draft |
Create draft quotes (no tarification) |
automation:read |
Read job status + PingID devices |
automation:enqueue |
Trigger RPA tarifications |
webhooks:manage |
Manage webhook subscriptions |
A 403 insufficient_scope response includes the required_scope; issue a new key with that scope.
Rate limits¶
Per-key limits are enforced and surfaced on each response:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 994
X-RateLimit-Reset: 1779993600
Retry-After: 12 # present on 429 responses
On 429 rate_limit_exceeded, wait for Retry-After (or retry_after_seconds in the body) before
retrying. Use exponential backoff.
Errors¶
All errors share a stable JSON shape:
| Status | Typical error |
Meaning / action |
|---|---|---|
| 400 | bad_request |
Malformed request or cursor |
| 401 | missing_api_key |
No key header — add X-API-Key or Authorization |
| 401 | invalid_api_key |
Unknown / expired / revoked key (same message for all, anti-enumeration) |
| 403 | insufficient_scope |
Key lacks the required scope |
| 403 | cabinet_required |
The principal has no cabinet attached |
| 404 | not_found |
Missing resource — or another tenant's (same response, anti-enumeration) |
| 409 | idempotency_conflict |
A concurrent request reused the same Idempotency-Key |
| 422 | validation_error |
Payload validation failed (details lists the fields) |
| 429 | rate_limit_exceeded |
Per-key limit hit — back off |
| 503 | upstream_error |
Transient upstream issue — retry with backoff |
RPA-specific error codes (rpa_quota_exceeded, rpa_replay_detected, …) are documented in
Idempotency & quotas.
Hardening notes¶
- Timing-equalised 401s: all authentication failures take a constant minimum time and return the same message, to defeat enumeration and timing attacks.
- IP throttling: repeated failed auth from one IP is throttled (
429) before any expensive lookup. - IP allowlist (optional): pin a key to specific CIDRs at creation.
- Expiry (optional): set an expiration for rotating CI/CD keys.