Authentication
Every request carries a bearer token:
Authorization: Bearer aik_S3cr3tT0k3nValueShownOnceDoNotShare1234Any Bearer token beginning with aik_ is handled by the API-key
authenticator and never falls through to Firebase — so a mistyped key fails as
a key, with a key-shaped error, rather than as “invalid Firebase token”.
flowchart TB
T["Authorization: Bearer …"] --> P{"starts with<br/>aik_ ?"}
P -->|yes| K["API-key auth"]
P -->|no| F["Firebase auth"]
K --> V{"key live, and<br/>plan entitled?"}
V -->|yes| OK["team-scoped access"]
V -->|"revoked or typo'd"| E1["401 Invalid API key"]
V -->|"plan downgraded"| E2["401 requires Organization"]
OK --> H{"human-only<br/>endpoint?"}
H -->|yes| E3["403 not available<br/>to API-key callers"]
H -->|no| Y["200"]
Getting a key
Section titled “Getting a key”Minting is owner-only and requires the Organization plan or above. The team owner does it in the app under Settings → API keys, or over HTTP from a signed-in session:
curl -X POST https://api.ai.aikynetix.app/api/api-keys/ \ -H 'Authorization: Bearer <firebase-id-token>' \ -H 'Content-Type: application/json' \ -d '{"label":"production webhook"}'{ "id": "9b1c7e2a-4d3f-4a8b-9c0d-1e2f3a4b5c6d", "label": "production webhook", "token": "aik_S3cr3tT0k3nValueShownOnceDoNotShare1234", "created_at": "2026-04-30T08:00:00Z"}Two things can refuse that call, both owner-facing rather than
integration-facing: {"detail": "Only the team owner can manage API keys"} if
you are a member rather than the owner, and
{"detail": "api_keys_require_upgraded_plan"} if the team’s tier does not
carry API access. Listing and revoking stay available on every tier, so an
owner who downgraded can still audit and clean up.
Rotating
Section titled “Rotating”Mint the new key, deploy it, then revoke the old one with
DELETE /api/api-keys/{id}/. Revocation takes effect on the next request.
Managing keys is a human-session surface: an aik_… token cannot list, mint or
revoke keys — not even its own.
What a key can reach
Section titled “What a key can reach”Everything team-scoped that a coach can reach: sessions, athletes, client groups, the exercise catalogue, Solutions, and billing as read-only.
What it cannot reach are the human-shaped surfaces, which answer 403 with
{"detail": "This endpoint is not available to API-key callers."}:
- the signed-in user’s own profile, onboarding and branding
- team membership, invites and ownership transfer
- billing actions — checkout, portal, cancel, reactivate
- the dashboard aggregates and per-session trends
- the coaching agents, the in-app assistant, and AI artifacts
- custom metric thresholds
- API-key management itself
Two consequences worth designing around:
Sessions created by a key have uploaded_by: null. A key is not a person.
If you need attribution, keep it on your side.
Aggregation is yours. With the dashboard endpoints closed, trends across sessions are something you compute — the per-session data is all there.
If the plan changes
Section titled “If the plan changes”A downgrade stops the key working immediately, on the next request:
{ "detail": "API keys require the Organization plan or higher" }That is a 401, and it is deliberately worded differently from
{"detail": "Invalid API key"} so you can tell a billing problem from a bad
credential. The keys are not deleted — they authenticate again the moment the
plan is restored, with no re-minting.
Handle these two differently: an invalid key is a code or config problem and retrying never helps; a plan problem needs a human at the customer to act.