Account
9 Account routes on the FLAM API: The director's own account, in one read; Remove your picture; Set your own picture (multipart).
Base URL https://api.flam.fashion. Send Authorization: Bearer flam_sk_… on every call; a handful of routes are session-only and say so. How keys and roles work.
GET /api/account
The director's own account, in one read
Profile, current plan, token balance WITH where those tokens went by workflow, and the book of money that actually landed. Deliberately does NOT re-serve what already has a door: name/avatar, password, social linking and sessions are Better Auth (/api/auth/*); plan and pack prices are /api/toolkit/ai/billing/catalog; upgrades and top-ups are the checkout routes; export/erase are /me/export and /me/delete.
Parameters
| In | Name | Type | Required | Notes |
|---|---|---|---|---|
| query | days | 7 | 30 | 90 | no | Spend window — 7, 30 or 90. Anything else falls back to 30. |
Responses
| Status | Meaning |
|---|---|
200 | The account |
401 | No valid session |
200 returns:
{
"profile": {
"id": "string",
"name": "string",
"email": "string",
"emailVerified": true,
"image": "string",
"joinedAt": "2026-07-27T09:00:00.000Z"
},
"plan": {
"tier": "string",
"name": "string",
"status": "trialing",
"priceUsd": 0,
"monthlyTokens": 0,
"rolloverMultiple": 0,
"renewsAt": "2026-07-27T09:00:00.000Z"
},
"tokens": {
"balance": 0,
"grant": 0,
"topup": 0,
"held": 0,
"days": 7,
"byWorkflow": [
{
"workflow": "string",
"tokens": 0,
"runs": 0,
"lastAt": "2026-07-27T09:00:00.000Z"
}
]
},
"invoices": [
{
"id": "string",
"at": "2026-07-27T09:00:00.000Z",
"kind": "subscription_grant",
"item": "string",
"tokens": 0,
"amountUsd": 0,
"reference": "string"
}
],
"billing": {
"cardOnFile": true,
"email": "string",
"canManage": true
}
}Call it
curl -X GET "https://api.flam.fashion/api/account" \
-H "Authorization: Bearer $FLAM_API_KEY"DELETE /api/account/avatar
Remove your picture
Back to your initial. The bytes go too — 'remove my picture' means remove it, not hide it. Answers { image: null }.
Responses
| Status | Meaning |
|---|---|
200 | Removed. |
401 | No valid session |
200 returns:
{
"image": "string"
}Call it
curl -X DELETE "https://api.flam.fashion/api/account/avatar" \
-H "Authorization: Bearer $FLAM_API_KEY"POST /api/account/avatar
Set your own picture (multipart)
The bytes arrive ALREADY SQUARE, downscaled and webp-encoded: ImageCropper (@flam/ui) does the crop and the encode in the browser, because the API is a Cloudflare Worker and workerd has no image library. So this validates rather than transforms.
Accepts image/webp, image/png, image/jpeg up to 512KB — roughly 17x what an honest client sends, and the bound on a hostile one.
Answers the URL now on your row, so a caller can render it immediately instead of re-reading the account. That URL carries a ?v= stamp: the serving route sends immutable, max-age=1y, which is only safe because each replacement is a new URL.
Request body — multipart/form-data (required)
| Field | Type | Required | Notes |
|---|---|---|---|
file | file | yes | — |
Responses
| Status | Meaning |
|---|---|
200 | Stored. image is the URL now on your user row. |
400 | No file, an empty file, or an unsupported type. |
401 | No valid session |
413 | Larger than 512KB. |
200 returns:
{
"image": "string"
}Call it
curl -X POST "https://api.flam.fashion/api/account/avatar" \
-H "Authorization: Bearer $FLAM_API_KEY" \
-F "[email protected]"GET /api/account/avatar/{userId}
A user's picture (bytes)
A SESSION IS REQUIRED and that is the whole access rule: a colleague's face is directory-level information inside a house, and gating it further would mean a membership query on every <img> on every screen. It is NOT public — an unauthenticated request gets 401, so a portrait never leaks to a stranger who guesses a user id.
Parameters
| In | Name | Type | Required | Notes |
|---|---|---|---|---|
| path | userId | string | yes | — |
Responses
| Status | Meaning |
|---|---|
200 | The image bytes. |
401 | No valid session |
404 | That user has no picture. |
Call it
curl -X GET "https://api.flam.fashion/api/account/avatar/{userId}" \
-H "Authorization: Bearer $FLAM_API_KEY"PATCH /api/account/billing-email
Set the house's invoice email
Owner-only. Keeps the house-scoped invoice recipient separate from sign-in identity and updates the payment provider when a customer already exists.
Request body — application/json (required)
| Field | Type | Required | Notes |
|---|---|---|---|
email | string (email) | yes | — |
{
"email": "string"
}Responses
| Status | Meaning |
|---|---|
200 | Invoice email saved |
400 | Invalid email |
401 | No valid session |
403 | Session email not in the admin allowlist |
502 | Payment provider update failed |
Call it
curl -X PATCH "https://api.flam.fashion/api/account/billing-email" \
-H "Authorization: Bearer $FLAM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"email":"string"}'GET /api/account/memory
Read the current house and actor-scoped memory book
Returns shared memories for the active organization plus only the current actor's personal memories inside that organization. Corrected and retired history remains visible for provenance but is never injected into chat.
Responses
| Status | Meaning |
|---|---|
200 | The caller's scoped living-memory record |
401 | No valid session |
200 returns:
{
"memories": [
{
"id": "string",
"scope": "house",
"memoryClass": "fact",
"kind": "told",
"statement": "string",
"confidence": 0,
"status": "candidate",
"evidenceCount": 0,
"supersedesId": "string",
"projected": true,
"createdAt": "2026-07-27T09:00:00.000Z",
"updatedAt": "2026-07-27T09:00:00.000Z"
}
]
}Call it
curl -X GET "https://api.flam.fashion/api/account/memory" \
-H "Authorization: Bearer $FLAM_API_KEY"POST /api/account/memory
Add or append a correction to a scoped memory
A correction creates a successor and preserves its predecessor. The canonical Neon write and Core projection event are committed in one transaction.
Request body — application/json (required)
| Field | Type | Required | Notes |
|---|---|---|---|
statement | string | yes | — |
scope | "house" | "person" | yes | — |
memoryClass | "fact" | "preference" | "lesson" | "playbook" | "outcome_pattern" | "image_reading" | yes | — |
replacesMemoryId | string | no | — |
{
"statement": "string",
"scope": "house",
"memoryClass": "fact",
"replacesMemoryId": "string"
}Responses
| Status | Meaning |
|---|---|
200 | A correction was appended |
201 | A new memory was appended |
400 | Invalid input |
401 | No valid session |
403 | Session email not in the admin allowlist |
404 | The predecessor is not active in the caller's scope |
Call it
curl -X POST "https://api.flam.fashion/api/account/memory" \
-H "Authorization: Bearer $FLAM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"statement":"string","scope":"house","memoryClass":"fact","replacesMemoryId":"string"}'DELETE /api/account/memory/{id}
Retire a scoped active memory
Stops future retrieval without deleting evidence or history. The current organization is always the outer boundary and personal memories must belong to the current actor.
Parameters
| In | Name | Type | Required | Notes |
|---|---|---|---|---|
| path | id | string | yes | — |
Responses
| Status | Meaning |
|---|---|
200 | The memory was retired |
401 | No valid session |
403 | Session email not in the admin allowlist |
404 | No active memory is available in this scope |
Call it
curl -X DELETE "https://api.flam.fashion/api/account/memory/{id}" \
-H "Authorization: Bearer $FLAM_API_KEY"POST /api/account/plan/cancel
Stop the renewal (cancel at period end)
Cancel means "do not renew", never "take it back now" — every token already granted stays, and the plan runs to the end of the period it is paid for. The provider is told first and our row is mirrored only on its yes, so a failed vendor call can never leave a director believing they cancelled while the card is still charged. Grants nothing; the webhook remains the only thing that grants.
Responses
| Status | Meaning |
|---|---|
200 | The plan will not renew |
401 | No valid session |
404 | NO_ACTIVE_PLAN — nothing is renewing |
502 | CANCEL_FAILED — the provider refused; nothing was changed here |
503 | BILLING_NOT_CONFIGURED — no provider credentials |
200 returns:
{
"status": "canceled",
"endsAt": "2026-07-27T09:00:00.000Z"
}Call it
curl -X POST "https://api.flam.fashion/api/account/plan/cancel" \
-H "Authorization: Bearer $FLAM_API_KEY"Billing
10 Billing routes on the FLAM API: The house's auto top-up rule, ceiling, card and audit trail; Arm, retune or disarm the auto top-up rule (OWNER ONLY).
Me
3 Me routes on the FLAM API: The signed-in user; GDPR erasure — delete the caller's account; GDPR access — export the caller's own user row.