Refresh tokens (rotation)
Auth
Refresh tokens (rotation)
Rotate the refresh token. Returns a fresh access + refresh pair.
POST
Refresh tokens (rotation)
Overview
Exchanges a valid refresh token for a new access + refresh pair and invalidates the presented token in the same transaction. Refresh tokens are single-use rotating — the server marks the old row asusedAt = now and links it to the new row via replacedBy. Re-presenting an already-used refresh token is treated as theft: the entire session chain (every refresh token sharing the same sessionId) is revoked and the API returns 401 TOKEN_REVOKED.
The access token returned is a fresh RS256 JWT with a 15-minute TTL. The refresh token is a new 256-bit opaque base64url string with a 30-day TTL.
Authentication
None required at the HTTP layer — the refresh token itself is the credential. Do not sendAuthorization: Bearer ... on this call.
Path parameters
None.Query parameters
None.Request body
| Field | Type | Required | Allowed values / Constraints | Example |
|---|---|---|---|---|
refreshToken | string | yes | 1..2048 chars; the opaque base64url token returned by /auth/login, /auth/verify-email, or a prior /auth/refresh. | v8q3xZ0p6rW7sT4uV1nB2cX9yY8mK5jL6hG7fD3eA0c |
Example payload
Response — 200 OK
| Field | Type | Notes / Allowed values | Example |
|---|---|---|---|
accessToken | string | RS256 JWT, 15-min TTL. Pass in Authorization: Bearer <accessToken>. | eyJhbGciOiJSUzI1NiIs... |
refreshToken | string | New 256-bit opaque base64url token, 30-day TTL. Replaces the token sent in the request body. | qK9wM2lP8oU5tV1nB2cX9yY8mK5jL6hG7fD3eA0c-aR4 |
Example response
Error responses
| Status | Code | Meaning |
|---|---|---|
| 400 | VALIDATION_FAILED | Body malformed or refreshToken missing / outside the 1..2048 char range. |
| 401 | UNAUTHENTICATED | Refresh token does not match any row, is expired, or fails the shape check (length < 32 or > 256). |
| 401 | TOKEN_REVOKED | Refresh-token reuse detected (the row was already marked usedAt) — the entire session chain has been revoked. The client must redirect the user to login. |
Example error — 401
Side effects
- Marks the presented
refresh_tokensrow withusedAt = nowandreplacedByTokenId = <new id>. - Inserts a new
refresh_tokensrow sharing the samesessionIdanddeviceFingerprint. - On reuse detection, calls
revokeAllForSession(sessionId)— every refresh token for that session is revoked.
See also
- Authentication — full token lifecycle.
- Login — issues the initial token pair.
- Logout — revoke the current session’s refresh token.
- Errors — stable error code catalog.