FLAM

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-staging.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

InNameTypeRequiredNotes
querydays7 | 30 | 90noSpend window — 7, 30 or 90. Anything else falls back to 30.

Responses

StatusMeaning
200The account
401No 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-staging.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

StatusMeaning
200Removed.
401No valid session

200 returns:

{
  "image": "string"
}

Call it

curl -X DELETE "https://api-staging.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 bodymultipart/form-data (required)

FieldTypeRequiredNotes
filefileyes

Responses

StatusMeaning
200Stored. image is the URL now on your user row.
400No file, an empty file, or an unsupported type.
401No valid session
413Larger than 512KB.

200 returns:

{
  "image": "string"
}

Call it

curl -X POST "https://api-staging.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

InNameTypeRequiredNotes
pathuserIdstringyes

Responses

StatusMeaning
200The image bytes.
401No valid session
404That user has no picture.

Call it

curl -X GET "https://api-staging.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 bodyapplication/json (required)

FieldTypeRequiredNotes
emailstring (email)yes
{
  "email": "string"
}

Responses

StatusMeaning
200Invoice email saved
400Invalid email
401No valid session
403Session email not in the admin allowlist
502Payment provider update failed

Call it

curl -X PATCH "https://api-staging.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

StatusMeaning
200The caller's scoped living-memory record
401No 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-staging.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 bodyapplication/json (required)

FieldTypeRequiredNotes
statementstringyes
scope"house" | "person"yes
memoryClass"fact" | "preference" | "lesson" | "playbook" | "outcome_pattern" | "image_reading"yes
replacesMemoryIdstringno
{
  "statement": "string",
  "scope": "house",
  "memoryClass": "fact",
  "replacesMemoryId": "string"
}

Responses

StatusMeaning
200A correction was appended
201A new memory was appended
400Invalid input
401No valid session
403Session email not in the admin allowlist
404The predecessor is not active in the caller's scope

Call it

curl -X POST "https://api-staging.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

InNameTypeRequiredNotes
pathidstringyes

Responses

StatusMeaning
200The memory was retired
401No valid session
403Session email not in the admin allowlist
404No active memory is available in this scope

Call it

curl -X DELETE "https://api-staging.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

StatusMeaning
200The plan will not renew
401No valid session
404NO_ACTIVE_PLAN — nothing is renewing
502CANCEL_FAILED — the provider refused; nothing was changed here
503BILLING_NOT_CONFIGURED — no provider credentials

200 returns:

{
  "status": "canceled",
  "endsAt": "2026-07-27T09:00:00.000Z"
}

Call it

curl -X POST "https://api-staging.flam.fashion/api/account/plan/cancel" \
  -H "Authorization: Bearer $FLAM_API_KEY"