Send (or reuse) the email-verification code
const url = 'http://localhost:8000/api/me/send-verification/';const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}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/.
Authorizations
Section titled “Authorizations”Responses
Section titled “Responses”Response shape for POST /api/me/send-verification/.
object
ISO-8601 UTC of when the most recent code was generated.
ISO-8601 UTC after which the code is rejected as code_expired.
ISO-8601 UTC after which a fresh send is allowed. Resends within the cooldown window reuse the existing code (no new email).
Seconds until resend_available_at. Render a countdown from this.
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}Within 60s of the last send; no new email sent
{ "sent_at": "2026-05-28T15:00:00Z", "expires_at": "2026-05-28T15:15:00Z", "resend_available_at": "2026-05-28T15:01:00Z", "cooldown_seconds": 18}object
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).
Examples
400 — Admin has no email on file
{ "detail": "no_email_on_account"}object
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).
Examplegenerated
{ "detail": "example"}object
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).
Examplegenerated
{ "detail": "example"}object
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.
Examples
409 — Email is already verified
{ "detail": "already_verified"}