Skip to content

Send (or reuse) the email-verification code

POST
/api/me/send-verification/
curl --request POST \
--url http://localhost:8000/api/me/send-verification/ \
--header 'Authorization: Bearer <token>'

Generates a 6-digit code, emails it to the signed-in admin’s address, and returns the resend cooldown. If a still-valid pending code exists (within 60s of the last send), no new email is sent — the existing code’s metadata is returned instead so the UI can render a countdown.

Returns 400 no_email_on_account when the admin has no email on file (rare — Firebase identities always carry one but platform-admin rows can be created without). Returns 409 already_verified when the admin’s email is already verified (the UI should never reach this state). Verify with POST /api/me/verify-email/.

Media typeapplication/json

Response shape for POST /api/me/send-verification/.

object
sent_at
required

ISO-8601 UTC of when the most recent code was generated.

string format: date-time
expires_at
required

ISO-8601 UTC after which the code is rejected as code_expired.

string format: date-time
resend_available_at
required

ISO-8601 UTC after which a fresh send is allowed. Resends within the cooldown window reuse the existing code (no new email).

string format: date-time
cooldown_seconds
required

Seconds until resend_available_at. Render a countdown from this.

integer
Examples

Code sent (fresh)

{
"sent_at": "2026-05-28T15:00:00Z",
"expires_at": "2026-05-28T15:15:00Z",
"resend_available_at": "2026-05-28T15:01:00Z",
"cooldown_seconds": 60
}
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
Example400—AdminHasNoEmailOnFile

400 — Admin has no email on file

{
"detail": "no_email_on_account"
}
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
Examplegenerated
{
"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
Examplegenerated
{
"detail": "example"
}
Media typeapplication/json
object
detail
required

409 — the request conflicts with current state. detail is a stable code (e.g. reanalyze_in_flight, already_on_plan, email_in_use). Some 409s carry extra context fields alongside detail; those are documented on the specific endpoint that emits them.

string
Examples
Example409—EmailIsAlreadyVerified

409 — Email is already verified

{
"detail": "already_verified"
}