Auth API
buildingWhat is fixed by convention, what you still decide per project, and how to change it.
Settings
Most of how auth behaves is decided for you, on purpose.
The rule is convention over configuration: if there is an answer we would defend in a security review, that is the answer, and it is not a switch. A knob whose only correct position is the default is a way for somebody to get it wrong.
What is left is what we cannot guess — facts about your product and your customers' systems, which have no sensible default because they are not opinions.
Fixed for every project
| Behaviour | What it is | Why it is not yours to set |
|---|---|---|
| Account creation | A six-digit code, emailed | An account that exists before the address is proved can be created for somebody, with a password they never chose. See sign up |
| Email verification | Always required | The account was made by proving the address, so there is nothing to relax |
| Password length | At least 12 characters | Length is the only password rule that survives contact with evidence. No character classes, no rotation |
| Password | Optional | Codes are a complete way in; a password is a second one |
| Code lifetime | 10 minutes, 3 attempts | Long enough to find the mail, short enough to be useless later |
| Session | 7 days, refreshed daily | |
| Access tokens | 15 minutes, EdDSA, per-project keys | See tokens |
If you need one of these to be different, tell us what you are building — that is a conversation about the convention, not a setting we forgot to expose.
Secret key.
1curl "$BASE/v1/auth/settings" -H "authorization: Bearer $SK"1{2 "disableSignUp": false,3 "invitationUrl": null,4 "ssoOrigins": [],5 "scimRoleMap": {}6}| Setting | Default | What it does |
|---|---|---|
disableSignUp | false | Stop new account creation; existing users still sign in |
invitationUrl | unset | Where invitations land in your app |
ssoOrigins | [] | Hosts trusted for SSO discovery |
scimRoleMap | {} | Directory groups that grant roles |
Changes only what you send, so one setting can move without restating the rest.
1curl -X PATCH "$BASE/v1/auth/settings" \2 -H "authorization: Bearer $SK" \3 -H "content-type: application/json" \4 -d '{"disableSignUp":true}'Changes take effect on the next request, not after a cache expires.
A misspelled setting is refused, not ignored — a setting that reads as saved and does nothing is worse than an error:
{ "error": "Unknown setting: disableSignUps. Known settings are disableSignUp, invitationUrl, ssoOrigins, scimRoleMap." }A setting that used to exist gets a straight answer rather than "unknown", so you are told what happened rather than left thinking you made a typo:
{ "error": "Email verification is always required and is no longer configurable." }disableSignUp is not a suspension
Sign-in, sessions and tokens keep working; only account creation stops — for an app that provisions its users elsewhere, or one you are closing to new signups. It covers both doors: a code for an unknown address will not create an account either.
Errors
| Status | Code | Means |
|---|---|---|
400 | — | Unknown setting name, quoted back to you |
400 | — | A retired setting, with what replaced it |
401 | — | Missing key, or a publishable key |