<!-- section: Auth API · status: building · source: docs/auth-api/14-settings.md -->

> What 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](/docs/auth-api/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](/docs/auth-api/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.

## GET /v1/auth/settings

**Secret key.**

```bash Request
curl "$BASE/v1/auth/settings" -H "authorization: Bearer $SK"
```

```json Response
{
  "disableSignUp": false,
  "invitationUrl": null,
  "ssoOrigins": [],
  "scimRoleMap": {}
}
```

| Setting | Default | What it does |
|---|---|---|
| `disableSignUp` | `false` | Stop new account creation; existing users still sign in |
| `invitationUrl` | unset | Where [invitations](/docs/auth-api/organizations) land in your app |
| `ssoOrigins` | `[]` | Hosts trusted for [SSO discovery](/docs/auth-api/enterprise-sso) |
| `scimRoleMap` | `{}` | Directory groups that [grant roles](/docs/auth-api/directory-sync) |

## PATCH /v1/auth/settings

Changes only what you send, so one setting can move without restating the rest.

```bash Request
curl -X PATCH "$BASE/v1/auth/settings" \
  -H "authorization: Bearer $SK" \
  -H "content-type: application/json" \
  -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:

```json
{ "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:

```json
{ "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 |
