Authentication
Register
/api/auth/signinCreate a new user account and send a verification email. The account is created even if the email can't be sent; the user can ask for another one with Resend Verification Email.
JSON Body
| Field | Type | Description |
|---|---|---|
username | string | Unique username |
email | string | Valid email address |
password | string | Password (min 8 characters) |
alias ? | string? | Display name |
Returns: 201 Created, with no body. Log in with POST /api/auth/login to get tokens.
Errors: 409 with email is already in use or that username is taken.
Log In
/api/auth/loginAuthenticate with email and password. Returns an access token and sets a session cookie.
JSON Body
| Field | Type | Description |
|---|---|---|
email | string | Email address |
password | string | Account password |
device ? | string | Device name for session tracking |
browser ? | string | Browser name for session tracking |
os ? | string | Operating system for session tracking |
Response
| Field | Type | Description |
|---|---|---|
token | string | Access token (Bearer) |
session_token | string | Session refresh token |
Returns: AuthTokenResponse (access + refresh tokens).
Errors: 400 with {"error": "invalid email or password"} when the email or the password is wrong (the same message for both, so it doesn't reveal which accounts exist). After 10 attempts for an address within 15 minutes without a successful one, 429 with {"error": "too many failed login attempts, try again later"}, even with the right password, until 15 minutes have passed since the first failure (see Rate Limiting).
Refresh Session
/api/auth/refreshRefresh the current session. Reads the session token from the X-Session-Token header, or from the duvet_session_token cookie when there's no header. Returns a new access token and rotates the session token. Refreshes of one session that overlap all get the same new tokens: for 30 seconds after a rotation, the previous session token refreshes to the current tokens. After that, or once the session is logged out, it answers 401. The new tokens last 24 hours, but a session ends 30 days after its login: from then on, refreshing it answers 401 and the user has to log in again.
Response
| Field | Type | Description |
|---|---|---|
token | string | New access token (Bearer) |
session_token | string | Rotated session refresh token |
Returns: AuthTokenResponse (access + refresh tokens).
Log Out
/api/auth/logoutRevoke the current session token (from the X-Session-Token header, or else the cookie) and clear the session cookie.
Returns: 204 No Content
Verify Email
/api/auth/verifyVerify a user's email address using a one-time token sent via email.
JSON Body
| Field | Type | Description |
|---|---|---|
token | string | Email verification token |
Returns: 204 No Content
Resend Verification Email
/api/auth/verify/sendSend a new email verification token to the authenticated user. Requires authentication. At most 3 per hour per account.
Returns: 204 No Content
Errors: 409 when the email is already verified, 400 for an account without an email, and 502 when the email couldn't be sent.
Reset Password
/api/auth/reset-passwordReset a password using a password reset token.
JSON Body
| Field | Type | Description |
|---|---|---|
token | string | Password reset token |
password | string | New password (min 8 characters) |
Every session of the account ends: its tokens stop working, and its gateway connections are closed with code 4004.
Returns: 204 No Content
Send Reset Password Email
/api/auth/reset-password/sendSend a password reset email to the authenticated user. Requires authentication. At most 3 per hour per account.
Returns: 204 No Content
Errors: 400 for an account without an email, and 502 when the email couldn't be sent.
Forgot Password
/api/auth/forgot-passwordRequest a password reset email by providing an email address. Always returns success to avoid revealing whether the email exists. Sends at most 3 emails per address per hour; requests past that still succeed but send nothing.
JSON Body
| Field | Type | Description |
|---|---|---|
email | string | Account email address |
Returns: 204 No Content
Change Email
/api/auth/change-emailUpdate the user's email address using a verification token and the new email.
JSON Body
| Field | Type | Description |
|---|---|---|
token | string | Email change verification token |
email | string | New email address |
Returns: 204 No Content
Send Change Email Verification
/api/auth/change-email/sendSend a verification email to initiate an email address change. Requires authentication. At most 3 per hour per account.
JSON Body
| Field | Type | Description |
|---|---|---|
email | string | New email address to verify |
Returns: 204 No Content
Errors: 409 when the address is already yours or belongs to a verified account, and 502 when the email couldn't be sent.