Start signup — send a verification code to the email
const url = 'https://api.flotera.com/api/v1/auth/signup/start';const options = { method: 'POST', headers: {'Content-Type': 'application/json'}, body: '{"email":"hello@example.com","tenant_name":"example","turnstile_token":"example"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.flotera.com/api/v1/auth/signup/start \ --header 'Content-Type: application/json' \ --data '{ "email": "hello@example.com", "tenant_name": "example", "turnstile_token": "example" }'First step of the email-verification signup flow (05 §4.3). Protected by distributed rate limits (IP prefix + hashed email) and, when configured, by a Cloudflare Turnstile challenge.
Stores a pending signup (name + email, no account yet) and emails a
6-digit code valid for 10 minutes with 5 entry attempts. Re-requesting
a code for the same email is allowed once per 60 seconds; inside the
cooldown the operation answers 429 with Retry-After.
Anti-enumeration (05 §8.3): the response is 202 regardless of
whether the email already has an account. A taken email receives a
“you already have an account” email instead of a code; the stored
pending row behaves identically from the outside (including the
resend cooldown), so a taken and a free email are indistinguishable
to the caller. The email itself is dispatched after the response —
response timing does not depend on the SMTP path either.
Operator-disabled operation. Public signup is off by default and
is enabled per deployment with ERMEON_SIGNUP_ENABLED. While it is
off, all three signup operations answer 404 not_found for every
request, before the body is parsed and before any storage is touched.
Clients must read GET /auth/config (signup_enabled) instead of
probing this path.
Request Bodyrequired
Section titled “Request Bodyrequired”object
Display name of the tenant that will be created at the complete step; stored with the pending signup.
Cloudflare Turnstile response token from the widget. Optional in the schema because the challenge is deployment-configurable, but required in practice whenever GET /auth/config reports turnstile.enabled; omitting it then returns 403. Single-use.
Examplegenerated
{ "email": "hello@example.com", "tenant_name": "example", "turnstile_token": "example"}Responses
Section titled “Responses”Code dispatch accepted (identical for any email). The body reports the resend cooldown for the UI countdown.
object
Seconds until another code may be requested for the same email — drives the UI resend countdown.
Examplegenerated
{ "resend_cooldown_seconds": 1}Turnstile challenge missing, rejected by Cloudflare, or impossible to verify (fail closed). code=forbidden, detail="captcha verification failed". The body never depends on the submitted credentials; the token is single-use, so the widget must be reset before retrying.
RFC 9457 problem document with a stable machine code.
object
Stable machine-readable error code (03 §2.4).
UUID (v7 for new entities; v4 accepted during migration).
object
JSON Pointer to the offending field.
Example
{ "type": "https://ermeon.com/problems/validation", "code": "unauthorized"}Public signup is disabled on this deployment (code=not_found). Identical for every payload.
RFC 9457 problem document with a stable machine code.
object
Stable machine-readable error code (03 §2.4).
UUID (v7 for new entities; v4 accepted during migration).
object
JSON Pointer to the offending field.
Example
{ "type": "https://ermeon.com/problems/validation", "code": "unauthorized"}Request failed validation (code=validation_failed), with per-field errors.
RFC 9457 problem document with a stable machine code.
object
Stable machine-readable error code (03 §2.4).
UUID (v7 for new entities; v4 accepted during migration).
object
JSON Pointer to the offending field.
Example
{ "type": "https://ermeon.com/problems/validation", "code": "unauthorized"}Rate limit exceeded (code=rate_limited).
RFC 9457 problem document with a stable machine code.
object
Stable machine-readable error code (03 §2.4).
UUID (v7 for new entities; v4 accepted during migration).
object
JSON Pointer to the offending field.
Example
{ "type": "https://ermeon.com/problems/validation", "code": "unauthorized"}Headers
Section titled “Headers”Seconds to wait before retrying.
A dependency the endpoint needs is not configured or is temporarily unavailable (code=unavailable). The rest of the API keeps working — an absent external integration must not take the service down.
RFC 9457 problem document with a stable machine code.
object
Stable machine-readable error code (03 §2.4).
UUID (v7 for new entities; v4 accepted during migration).
object
JSON Pointer to the offending field.
Example
{ "type": "https://ermeon.com/problems/validation", "code": "unauthorized"}