Skip to content

Preview a client invite

POST
/api/client-invites/preview/
curl --request POST \
--url http://localhost:8000/api/client-invites/preview/ \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "token": "Gu7Qk2n0bVw1sXyZ-4hRt9pLmA3cE6dF8jK0oPqS5uW" }'

What the invite page shows before anyone signs in: the team, the coach, the athlete’s card, the relation and level, the invited address masked, and the consent version the accept must carry. Open to anyone holding the token — it rides in the body, never in a path. email_matches is null on an anonymous request and says, for a signed-in one, whether the accept would go through. Rate-limited (429). Answers 404 while client access is switched off on the environment.

lang
string

en · ru · es: the page’s language, for the coach’s fallback name. Default: the invite’s language.

POST /api/client-invites/preview/ body. The token travels in the body, never in a path (D4).

object
token
required

The t from the invite link’s fragment.

string
>= 1 characters <= 128 characters

Examples

ExampleAToken

A token

{
"token": "Gu7Qk2n0bVw1sXyZ-4hRt9pLmA3cE6dF8jK0oPqS5uW"
}
Media typeapplication/json

What the invite page shows before anyone signs in (ClientInvitePreview).

object
team_name
required
string
invited_by_name
required

The coach’s name, never an e-mail address; when they gave none, “Your coach” in ?lang, else the invite’s language.

string
client_name
required

The athlete’s card the invite opens.

string
relation
required
  • athlete - Athlete
  • guardian - Parent or guardian
string
Allowed values: athlete guardian
level
required
  • view - View
  • contribute - Contribute
string
Allowed values: view contribute
email_hint
required

The invited address, masked: o***@example.com.

string
expires_at
required
string format: date-time
nullable
email_matches
required

Whether the signed-in account’s address is the invited one; null on an anonymous request. False stops the page before consent: the accept would answer 409 invite_email_mismatch.

boolean
nullable
consent_version
required

The consent version the accept must carry for this invite’s relation.

string

Examples

ExampleAGuardian'sInvite,SignedInWithTheInvitedAddress

A guardian's invite, signed in with the invited address

{
"team_name": "North Track Academy",
"invited_by_name": "Kim Larsen",
"client_name": "Sofia Lebedeva",
"relation": "guardian",
"level": "view",
"email_hint": "o***@example.com",
"expires_at": "2026-11-12T09:00:00Z",
"email_matches": true,
"consent_version": "2026-10-29-draft"
}
Media typeapplication/json
object
detail
required

Human-readable message, or a stable machine code for the cases a client branches on. The standard envelope for 400 (validation — a field-keyed object may appear instead), 401 (missing / invalid credentials), 403 (authenticated but not permitted), and 404 (absent — cross-team records are collapsed to 404 so the API never leaks the existence of another team’s data).

string

Example generated

{
"detail": "example"
}
Media typeapplication/json
object
detail
required

Human-readable message, or a stable machine code for the cases a client branches on. The standard envelope for 400 (validation — a field-keyed object may appear instead), 401 (missing / invalid credentials), 403 (authenticated but not permitted), and 404 (absent — cross-team records are collapsed to 404 so the API never leaks the existence of another team’s data).

string

Examples

Example404—NoSuchInvite

404 — no such invite

{
"detail": "invite_not_found"
}
Media typeapplication/json
object
detail
required

Human-readable message, or a stable machine code for the cases a client branches on. The standard envelope for 400 (validation — a field-keyed object may appear instead), 401 (missing / invalid credentials), 403 (authenticated but not permitted), and 404 (absent — cross-team records are collapsed to 404 so the API never leaks the existence of another team’s data).

string

Examples

410 — expired

The 14-day link lapsed: ask the coach to resend it.

{
"detail": "invite_expired"
}
Media typeapplication/json
object
detail
required

429 — throttled: this account’s (or address’s) rate for the route is used up; try again after wait seconds, which Retry-After repeats. A route with a limit of its own answers its own code instead, documented there.

string
wait

With throttled: whole seconds until the next request can pass.

integer
nullable

Example generated

{
"detail": "example",
"wait": 1
}