Invites
6 Invites routes on the FLAM API: Look up an invitation token before signing in; Accept an invitation as the signed-in user; Read what her links say.
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/toolkit/invite/accept
Look up an invitation token before signing in
Answers the invited email so the sign-up screen can pre-fill it. No session needed.
Parameters
| In | Name | Type | Required | Notes |
|---|---|---|---|---|
| query | token | string | yes | — |
Responses
| Status | Meaning |
|---|---|
200 | The invited address |
400 | Token required |
404 | Invalid token |
410 | Already accepted |
200 returns:
{
"email": "string"
}Call it
curl -X GET "https://api-staging.flam.fashion/api/toolkit/invite/accept?token=<token>" \
-H "Authorization: Bearer $FLAM_API_KEY"POST /api/toolkit/invite/accept
Accept an invitation as the signed-in user
The email on the invite must match the session's, otherwise 403 — an invite is not transferable. Accepting attaches the pre-created email-keyed grants to the caller's HOUSE and repairs a missing personal org (ensurePersonalOrg is idempotent). Replaying an accepted token is a no-op, not an error.
Request body — application/json (required)
| Field | Type | Required | Notes |
|---|---|---|---|
token | string | yes | — |
{
"token": "string"
}Responses
| Status | Meaning |
|---|---|
200 | Accepted (or already was) |
400 | Token required |
401 | No valid session |
403 | This invite is for a different email |
404 | Invalid token |
200 returns:
{
"ok": true,
"alreadyAccepted": true
}Call it
curl -X POST "https://api-staging.flam.fashion/api/toolkit/invite/accept" \
-H "Authorization: Bearer $FLAM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"token":"string"}'POST /api/toolkit/invite/preview
Read what her links say about her
Public, unauthenticated, rate-limited per IP. Reads the OpenGraph tags and site icon of up to 6 public pages so the invitation wizard can ask 'is this you?'. A link that cannot be read comes back with ok: false rather than failing the call — one bad row must never cost her the others.
Request body — application/json
| Field | Type | Required | Notes |
|---|---|---|---|
links | string[] | yes | — |
{
"links": [
"https://atelier-berger.com",
"https://instagram.com/atelierberger"
]
}Responses
| Status | Meaning |
|---|---|
200 | One card per link, in the order they were sent. |
400 | No links, or more than six. |
429 | Too many fresh reads from this address. |
200 returns:
{
"cards": [
{
"link": "string",
"ok": true,
"host": "string",
"title": "string",
"description": "string",
"imageUrl": "string",
"iconUrl": "string"
}
]
}Call it
curl -X POST "https://api-staging.flam.fashion/api/toolkit/invite/preview" \
-H "Authorization: Bearer $FLAM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"links":["https://atelier-berger.com","https://instagram.com/atelierberger"]}'POST /api/toolkit/invite/redeem
Redeem an invitation code
Public, unauthenticated, rate-limited per IP. Opens the platform door for ONE address by writing its invitation — it does not create an account and does not sign anybody in. The caller signs up normally afterwards, through the unchanged invite-only gate. Redeeming for an address that is already invited consumes no use of the code.
Request body — application/json
| Field | Type | Required | Notes |
|---|---|---|---|
code | string | yes | — |
email | string (email) | yes | — |
{
"code": "FLAM-INNER-7QK4M2",
"email": "[email protected]"
}Responses
| Status | Meaning |
|---|---|
200 | The door is open for this address. |
400 | Not a code, a throwaway address, or the code is spent / expired / revoked. |
404 | No such code |
429 | Too many attempts from this address. |
200 returns:
{
"status": "opened",
"label": "string",
"grantTokens": 0,
"frames": 153,
"looks": 30,
"days": 7
}Call it
curl -X POST "https://api-staging.flam.fashion/api/toolkit/invite/redeem" \
-H "Authorization: Bearer $FLAM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"code":"FLAM-INNER-7QK4M2","email":"[email protected]"}'POST /api/toolkit/invite/request
Request an invitation to the house
Public, unauthenticated. Rate-limited per IP. A duplicate address answers 200 with status already_requested rather than an error — asking twice is not a fault.
Request body — application/json
| Field | Type | Required | Notes |
|---|---|---|---|
name | string | yes | — |
house | string | no | — |
email | string (email) | yes | — |
collection | string | no | — |
intake | IntakeAnswers | no | — |
link | string | no | — |
links | string[] | no | — |
logoUrl | string (uri) | no | — |
website | string | no | — |
{
"name": "Noa Berger",
"house": "Atelier Berger",
"email": "[email protected]",
"collection": "Resort 26 — 40 pieces of knitwear, shooting the week of the 12th.",
"intake": {
"audience": [
"label"
],
"volume": [
"under-20"
],
"draws": [
"packshots"
],
"aiToday": [
"packshots"
],
"pain": [
"details"
],
"painText": "string",
"cost": [
"reshoots"
]
},
"link": "string",
"links": [
"string"
],
"logoUrl": "https://…",
"website": "string"
}Responses
| Status | Meaning |
|---|---|
200 | The request was recorded (or already was). |
400 | Invalid body, or a disposable email domain. |
429 | Too many requests from this address. |
200 returns:
{
"status": "received"
}Call it
curl -X POST "https://api-staging.flam.fashion/api/toolkit/invite/request" \
-H "Authorization: Bearer $FLAM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Noa Berger","house":"Atelier Berger","email":"[email protected]","collection":"Resort 26 — 40 pieces of knitwear, shooting the week of the 12th.","intake":{"audience":["label"],"volume":["under-20"],"draws":["packshots"],"aiToday":["packshots"],"pain":["details"],"painText":"string","cost":["reshoots"]},"link":"string","links":["string"],"logoUrl":"https://…","website":"string"}'GET /api/toolkit/invites/mine
This house's invitation link and who has used it
The promotion panel: one shareable link, how many invites are left, and every address the link has let in with whether they signed up and whether they subscribed. Scoped to the acting HOUSE. Self-healing — a house that predates the promotion (or whose signup hook did not run) gets its code minted on the first read, so nobody has to be backfilled twice.
Responses
| Status | Meaning |
|---|---|
200 | The link, the remaining invites, and the guest list. |
401 | Signed out |
503 | The code could not be minted. Try again in a moment. |
200 returns:
{
"code": "ATELIER-BERGER-7QK4M2",
"url": "https://flam.fashion/i/ATELIER-BERGER-7QK4M2",
"maxUses": 0,
"baseMaxUses": 10,
"usedCount": 0,
"invitesLeft": 0,
"guestLooks": 7,
"guestTokens": 500,
"hostTokens": 250,
"guestValueUsd": "$20",
"guestArrivalUsd": "$10",
"guestBonusTokens": 250,
"hostValueUsd": "$20",
"holdDays": 14,
"invitees": [
{
"email": "[email protected]",
"invitedAt": "string",
"signedUp": true,
"subscribed": true,
"subscribedAt": "string"
}
]
}Call it
curl -X GET "https://api-staging.flam.fashion/api/toolkit/invites/mine" \
-H "Authorization: Bearer $FLAM_API_KEY"