Admin
23 Admin routes on the FLAM API: Grant / revoke toolkit or tool access (admin); Token/cost usage summary from the ledger (admin); Develop runs across the.
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.
POST /api/toolkit/admin/access
Grant / revoke toolkit or tool access (admin)
Request body — application/json (required)
| Field | Type | Required | Notes |
|---|---|---|---|
action | "grant_toolkit" | "revoke_toolkit" | "grant_tool" | "revoke_tool" | yes | — |
userId | string | no | — |
email | string | no | — |
toolkitId | string | no | — |
toolId | string | no | — |
{
"action": "grant_toolkit",
"userId": "string",
"email": "string",
"toolkitId": "string",
"toolId": "string"
}Responses
| Status | Meaning |
|---|---|
200 | { ok, count } |
400 | Missing action / item id / target |
403 | Session email not in the admin allowlist |
Call it
curl -X POST "https://api.flam.fashion/api/toolkit/admin/access" \
-H "Authorization: Bearer $FLAM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"action":"grant_toolkit","userId":"string","email":"string","toolkitId":"string","toolId":"string"}'GET /api/toolkit/admin/ai-costs
Token/cost usage summary from the ledger (admin)
Responses
| Status | Meaning |
|---|---|
200 | Settled tokens + real USD per tool, per day, and totals |
403 | Session email not in the admin allowlist |
200 returns:
{
"byTool": [
{
"tool": "string",
"tokens": 0,
"cost_usd": 0,
"n": 0
}
],
"daily": [
{
"day": "string",
"tokens": 0,
"cost_usd": 0
}
],
"totalTokensSettled": 0,
"totalCostUsd": 0
}Call it
curl -X GET "https://api.flam.fashion/api/toolkit/admin/ai-costs" \
-H "Authorization: Bearer $FLAM_API_KEY"GET /api/toolkit/admin/develops
Develop runs across the house, newest first
Responses
| Status | Meaning |
|---|---|
200 | Runs |
403 | Session email not in the admin allowlist |
Call it
curl -X GET "https://api.flam.fashion/api/toolkit/admin/develops" \
-H "Authorization: Bearer $FLAM_API_KEY"POST /api/toolkit/admin/develops/action
Retry or cancel a develop
Cancel carries the Darkroom's honest semantics — queued frames release their hold, a frame already rendering finishes and still costs.
Responses
| Status | Meaning |
|---|---|
200 | The action's honest tally |
403 | Session email not in the admin allowlist |
Call it
curl -X POST "https://api.flam.fashion/api/toolkit/admin/develops/action" \
-H "Authorization: Bearer $FLAM_API_KEY"GET /api/toolkit/admin/emails
Every letter the house sent (email_log)
The list omits html on purpose — a hundred rendered emails is megabytes of body for a table that shows none of it. Pass ?id= for ONE row WITH its byte-exact archived HTML, exactly as the recipient received it. skipped is the dev-safe lane, not a fault.
Responses
| Status | Meaning |
|---|---|
200 | Letters, or one letter with its archive |
403 | Session email not in the admin allowlist |
404 | No such letter |
Call it
curl -X GET "https://api.flam.fashion/api/toolkit/admin/emails" \
-H "Authorization: Bearer $FLAM_API_KEY"GET /api/toolkit/admin/entitlements
Real-money purchases across the house
Responses
| Status | Meaning |
|---|---|
200 | Entitlements |
403 | Session email not in the admin allowlist |
Call it
curl -X GET "https://api.flam.fashion/api/toolkit/admin/entitlements" \
-H "Authorization: Bearer $FLAM_API_KEY"POST /api/toolkit/admin/entitlements/revoke
Revoke a granted entitlement (a refund's other half)
Responses
| Status | Meaning |
|---|---|
200 | Revoked |
403 | Session email not in the admin allowlist |
Call it
curl -X POST "https://api.flam.fashion/api/toolkit/admin/entitlements/revoke" \
-H "Authorization: Bearer $FLAM_API_KEY"GET /api/toolkit/admin/failures
Failures grouped by what the provider actually said
Twelve rows of "the provider returned no frame" is one problem wearing twelve uuids, so failures group on the error text with ids and digits knocked out. Each group carries how many HOUSES it reached — one house is probably their input, several is ours — and the whole real message from the most recent occurrence. Refused emails ride along.
Responses
| Status | Meaning |
|---|---|
200 | Grouped failures, plus refused emails |
403 | Session email not in the admin allowlist |
Call it
curl -X GET "https://api.flam.fashion/api/toolkit/admin/failures" \
-H "Authorization: Bearer $FLAM_API_KEY"GET /api/toolkit/admin/frames
Every house's outputs, browsable
What is actually being MADE on FLAM. Narrows server-side by house (organization id), tool (source_tool), age in days, and origin — made is anything the house developed, brought is what a director uploaded. The filter lists ride along in the same answer so the panel never needs a second round trip.
Responses
| Status | Meaning |
|---|---|
200 | Frames, plus the houses and tools that exist |
400 | Invalid input |
403 | Session email not in the admin allowlist |
Call it
curl -X GET "https://api.flam.fashion/api/toolkit/admin/frames" \
-H "Authorization: Bearer $FLAM_API_KEY"GET /api/toolkit/admin/frames/{id}/file
The bytes of any house's frame (admin only)
assets.ts's streamAsset owner-gates on organization_id and answers 404 to everyone else — correct for a director, and fatal for an admin who has to look at the frame a customer is complaining about. Widening that route would put "or an admin" inside the DIRECTOR path, where a bug in the allowlist becomes a cross-house read for real users. This one is admin-only from its first line.
Responses
| Status | Meaning |
|---|---|
200 | The image bytes |
403 | Session email not in the admin allowlist |
404 | No such frame |
Call it
curl -X GET "https://api.flam.fashion/api/toolkit/admin/frames/{id}/file" \
-H "Authorization: Bearer $FLAM_API_KEY"POST /api/toolkit/admin/grant-tokens
Comp a token grant to a user (admin)
Request body — application/json (required)
| Field | Type | Required | Notes |
|---|---|---|---|
userId | string | yes | — |
tokens | integer | yes | — |
expiryDays | integer | null | no | — |
reason | string | no | — |
{
"userId": "string",
"tokens": 0,
"expiryDays": 0,
"reason": "string"
}Responses
| Status | Meaning |
|---|---|
200 | { ok, granted, tokens, expiresAt } |
400 | USER_REQUIRED | BAD_TOKENS (body includes max) |
403 | Session email not in the admin allowlist |
404 | USER_NOT_FOUND |
Call it
curl -X POST "https://api.flam.fashion/api/toolkit/admin/grant-tokens" \
-H "Authorization: Bearer $FLAM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"userId":"string","tokens":0,"expiryDays":0,"reason":"string"}'POST /api/toolkit/admin/invite
Open the door for one email (admin)
Issues the PLATFORM-gate invitation: an invitations row plus permanent email-keyed studio access, so the invitee lands usable on signup. Idempotent — re-issuing an open door returns the same token and opens nothing twice. This is NOT the seat invitation (/api/toolkit/org/seats/invite).
Request body — application/json
| Field | Type | Required | Notes |
|---|---|---|---|
email | string (email) | yes | — |
{
"email": "[email protected]"
}Responses
| Status | Meaning |
|---|---|
200 | The door is open for this address. |
400 | Bad address |
403 | Not an admin |
200 returns:
{
"email": "string",
"token": "string",
"url": "string",
"status": "issued",
"toolkitsOpened": 0
}Call it
curl -X POST "https://api.flam.fashion/api/toolkit/admin/invite" \
-H "Authorization: Bearer $FLAM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]"}'GET /api/toolkit/admin/invite-requests
List invitation requests (admin)
Responses
| Status | Meaning |
|---|---|
200 | Every request, newest first. |
403 | Not an admin |
200 returns:
{
"requests": [
{
"id": "string",
"name": "string",
"house": "string",
"email": "string",
"collection": "string",
"status": "string",
"createdAt": "string"
}
]
}Call it
curl -X GET "https://api.flam.fashion/api/toolkit/admin/invite-requests" \
-H "Authorization: Bearer $FLAM_API_KEY"GET /api/toolkit/admin/offerings
The catalogue, as the house sees it
Responses
| Status | Meaning |
|---|---|
200 | Offerings |
401 | No valid session |
403 | Session email not in the admin allowlist |
Call it
curl -X GET "https://api.flam.fashion/api/toolkit/admin/offerings" \
-H "Authorization: Bearer $FLAM_API_KEY"POST /api/toolkit/admin/offerings
Create or update an offering (price, tier, previews)
Responses
| Status | Meaning |
|---|---|
200 | The saved offering |
400 | Invalid input |
403 | Session email not in the admin allowlist |
Call it
curl -X POST "https://api.flam.fashion/api/toolkit/admin/offerings" \
-H "Authorization: Bearer $FLAM_API_KEY"POST /api/toolkit/admin/offerings/retire
Retire an offering from the board
Responses
| Status | Meaning |
|---|---|
200 | Retired |
403 | Session email not in the admin allowlist |
Call it
curl -X POST "https://api.flam.fashion/api/toolkit/admin/offerings/retire" \
-H "Authorization: Bearer $FLAM_API_KEY"GET /api/toolkit/admin/overview
The house at a glance — the first screen
Directors and houses, how many worked this week, the outstanding token float, what the engine is doing right now, what moved today against yesterday, and a fourteen-day strip. Money and tokens are separate fields and are never summed — there is deliberately no field holding the two added together.
Responses
| Status | Meaning |
|---|---|
200 | The house at a glance |
403 | Session email not in the admin allowlist |
Call it
curl -X GET "https://api.flam.fashion/api/toolkit/admin/overview" \
-H "Authorization: Bearer $FLAM_API_KEY"GET /api/toolkit/admin/payments
Real transactions — subscriptions, top-ups, offerings, comps
Money reaches FLAM through three doors and the Money book only showed one. Comps are included and read as zero: hiding them makes the token float unexplainable, pricing them at anything else makes them look like revenue. amountUsd is currency and tokens is what that payment minted — separate fields, no total, because a top-up is money that bought tokens, not money and tokens.
Responses
| Status | Meaning |
|---|---|
200 | Transactions and standing subscriptions |
403 | Session email not in the admin allowlist |
Call it
curl -X GET "https://api.flam.fashion/api/toolkit/admin/payments" \
-H "Authorization: Bearer $FLAM_API_KEY"GET /api/toolkit/admin/tokenomics
What a token costs against what we charge, and the funnel
Three layers, never blended — the price book per tool AND per quality (tokens charged against credit_price_book.loaded_cost_usd), what actually ran from the jobs spine, and the conversion funnel. While costUnmeasured is true the worker still settles with a measured cost of zero, so every margin is MODELLED from the price book and the panel says so rather than printing a 100% margin.
Responses
| Status | Meaning |
|---|---|
200 | Unit economics, actuals and the funnel |
403 | Session email not in the admin allowlist |
Call it
curl -X GET "https://api.flam.fashion/api/toolkit/admin/tokenomics" \
-H "Authorization: Bearer $FLAM_API_KEY"DELETE /api/toolkit/admin/tool-items
Delete a curated item by id (admin)
Parameters
| In | Name | Type | Required | Notes |
|---|---|---|---|---|
| query | id | string | yes | — |
Responses
| Status | Meaning |
|---|---|
200 | { ok, deleted } |
400 | id required |
403 | Session email not in the admin allowlist |
Call it
curl -X DELETE "https://api.flam.fashion/api/toolkit/admin/tool-items?id=<id>" \
-H "Authorization: Bearer $FLAM_API_KEY"GET /api/toolkit/admin/tool-items
Curated items for one tool (admin)
Parameters
| In | Name | Type | Required | Notes |
|---|---|---|---|---|
| query | toolId | string | yes | — |
Responses
| Status | Meaning |
|---|---|
200 | { items } |
400 | toolId required |
403 | Session email not in the admin allowlist |
Call it
curl -X GET "https://api.flam.fashion/api/toolkit/admin/tool-items?toolId=<toolId>" \
-H "Authorization: Bearer $FLAM_API_KEY"POST /api/toolkit/admin/tool-items
Append a curated item (admin)
Request body — application/json (required)
| Field | Type | Required | Notes |
|---|---|---|---|
toolId | string | yes | — |
category | string | yes | — |
contentEn | string | no | — |
titleHe | string | no | — |
labelHe | string | no | — |
imageUrl | string | no | — |
notesHe | string | no | — |
{
"toolId": "string",
"category": "string",
"contentEn": "string",
"titleHe": "string",
"labelHe": "string",
"imageUrl": "string",
"notesHe": "string"
}Responses
| Status | Meaning |
|---|---|
200 | { ok, id, sortOrder } |
400 | toolId and category required |
403 | Session email not in the admin allowlist |
Call it
curl -X POST "https://api.flam.fashion/api/toolkit/admin/tool-items" \
-H "Authorization: Bearer $FLAM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"toolId":"string","category":"string","contentEn":"string","titleHe":"string","labelHe":"string","imageUrl":"string","notesHe":"string"}'GET /api/toolkit/admin/users
All users with balance + access (admin)
Responses
| Status | Meaning |
|---|---|
200 | User list |
403 | Session email not in the admin allowlist |
200 returns:
{
"users": [
{}
]
}Call it
curl -X GET "https://api.flam.fashion/api/toolkit/admin/users" \
-H "Authorization: Bearer $FLAM_API_KEY"