Authentication
A request to the API is made either by a person, signed in through your own identity provider, or by a machine, with an API key. Both are checked on every request, at your tenant’s own host.
People: your identity provider, with a second factor
Section titled “People: your identity provider, with a second factor”A person signs in at platform.atlanticagenticlabs.com with your tenant ID, then through your identity provider (Microsoft Entra ID, Google, Okta, GitHub, GitLab, or any SAML or OIDC provider). Cloudflare Access verifies the sign-in and sends LightHouse a signed assertion with each request (Cf-Access-Jwt-Assertion, or the CF_Authorization cookie).
LightHouse then:
- requires proof of a second factor, from the provider or from the sign-in policy’s own audit, or refuses with
403 mfa_required; - requires the provider to be one your tenant allows, and the person to match a grant in your access rules, or refuses with
403 not_authorised; - gives the person the highest role their grants allow.
Sign-ins and refusals go to your audit log. People’s requests from scripts are not the intended path: use a machine key.
Machine keys
Section titled “Machine keys”A machine key lets your own tools read the API and MCP.
| Property | Rule |
|---|---|
| Format | aalcp-<8 hex>-<43 characters>, sent as Authorization: Bearer aalcp-... |
| Role | viewer or content_viewer. Never handler or client_admin, so a leaked key cannot change who gets in |
| Expiry | Required, at most 365 days |
| Scope | One tenant. At any other tenant’s address the key does not exist (401) |
| Storage | Shown once. LightHouse keeps only its SHA-256, so a copy of the database grants nothing |
Creating a key
Section titled “Creating a key”Settings → API keys (a client_admin, signed in): a label, the role, and an expiry of 30, 90 or 180 days or a year. Copy it at once; it is never shown again. By API, as a person: POST /api/v1/keys with {"label": "bi-export", "role": "viewer", "expires_at": "2027-01-31T00:00:00Z"}. See Issue Key.
Rotating and revoking
Section titled “Rotating and revoking”Issue the new key, move your tool to it, then revoke the old one: Settings → API keys → Revoke, or DELETE /api/v1/keys/{key_id}. A revocation is recorded, not deleted, so the audit trail keeps who revoked it and when. The page also shows each key’s last use.
The Access service token at the edge
Section titled “The Access service token at the edge”Your tenant’s host sits behind Cloudflare Access. A machine passes it with your tenant’s machine access token, a Cloudflare Access service token Atlantic issues with your tenant, sent as two headers beside the key:
CF-Access-Client-Id: <client id>CF-Access-Client-Secret: <client secret>Settings → API keys shows the token’s expiry and when it was last renewed. Atlantic renews it before it expires; if it has lapsed, ask Atlantic.
curl -s "https://$AAL_TENANT.atlanticagenticlabs.com/api/v1/me" \ -H "Authorization: Bearer $AAL_KEY" \ -H "CF-Access-Client-Id: $CF_ACCESS_CLIENT_ID" \ -H "CF-Access-Client-Secret: $CF_ACCESS_CLIENT_SECRET"import os
import httpx
headers = { "Authorization": f"Bearer {os.environ['AAL_KEY']}", "CF-Access-Client-Id": os.environ["CF_ACCESS_CLIENT_ID"], "CF-Access-Client-Secret": os.environ["CF_ACCESS_CLIENT_SECRET"],}r = httpx.get(f"https://{os.environ['AAL_TENANT']}.atlanticagenticlabs.com/api/v1/me", headers=headers)print(r.status_code, r.json()["viewer"]["role"])const res = await fetch(`https://${process.env.AAL_TENANT}.atlanticagenticlabs.com/api/v1/me`, { headers: { Authorization: `Bearer ${process.env.AAL_KEY}`, "CF-Access-Client-Id": process.env.CF_ACCESS_CLIENT_ID!, "CF-Access-Client-Secret": process.env.CF_ACCESS_CLIENT_SECRET!, },});console.log(res.status, (await res.json()).viewer.role);What a machine key may never do
Section titled “What a machine key may never do”A key is refused on every route that does any of the following: with 403 person_required where the route acts only for a signed-in person, or 403 role_required where it needs handler or client_admin, which no key can hold.
- approves or decides: approvals and every handler command;
- pays: payment methods, checkout, top-ups, invoices marked paid;
- raises or changes a limit: spending limits, caps, pre-approvals;
- administers: access rules, keys, connectors, branding, where agents run, the library’s Add to deployment.
This is what stops an AI agent holding a key from approving its own work, spending, or loosening its own limits. See API security.
Delegated sign-in for tools
Section titled “Delegated sign-in for tools”A short-lived token a person approves in their own portal (a device code for a command line, OAuth for an MCP client) is Coming.