Quikko authenticates API requests with short-lived JWT access tokens and long-lived refresh tokens. Access tokens expire after 15 minutes by default; refresh tokens are valid for 7 days by default. Obtain a token pair fromDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/Andr21Da16/Quikko/llms.txt
Use this file to discover all available pages before exploring further.
POST /api/v1/auth/register or POST /api/v1/auth/login, then include the access token in the Authorization header on every protected request.
Passing the Token
All protected endpoints require the access token as a Bearer credential in theAuthorization header:
Bearer , and contains a valid HS256-signed JWT. Any deviation results in a 401 AUTH_TOKEN_INVALID response.
Registering and Getting a Token Pair
New users register with an email and a password (minimum 8 characters). The server creates the account with thefree plan and immediately returns a token pair alongside the user object — no separate login step is needed.
POST /api/v1/auth/login with the same body shape. The response is identical in structure. Both register and login are rate-limited per IP to protect against brute-force attacks, with independent counters configurable via AUTH_RATE_LIMIT_PER_MIN and RATE_LIMIT_LOGIN_PER_MIN.
Refreshing the Access Token
When the access token expires, exchange the refresh token for a new access token without requiring the user to log in again:The refresh response contains only
accessToken. There is no refreshToken or user object in the refresh response. Store the original refresh token and reuse it until it itself expires.refresh-type JWT (not an access token), and confirms the user still exists in the database before issuing a new access token.
Token Lifetimes
Both TTLs are configurable through environment variables:| Environment Variable | Default | Description |
|---|---|---|
JWT_ACCESS_TOKEN_TTL | 15m | Lifetime of the access token |
JWT_REFRESH_TOKEN_TTL | 7d | Lifetime of the refresh token |
What the JWT Contains
All tokens are signed with HMAC-SHA256 using theJWT_SECRET environment variable. The JWT payload carries:
| Claim | Description |
|---|---|
userID | MongoDB ObjectID of the authenticated user |
type | "access" or "refresh" |
iat | Issued-at timestamp (standard) |
exp | Expiry timestamp (standard) |
free/pro) is not embedded in the JWT. It is looked up from MongoDB on each request that enforces a plan restriction. This ensures plan changes take effect immediately without requiring users to re-authenticate.
401 Error Responses
Protected endpoints return401 in two distinct situations:
| Error Code | Cause |
|---|---|
AUTH_TOKEN_INVALID | Authorization header is missing, malformed, or contains an invalid signature |
AUTH_TOKEN_EXPIRED | The token has a valid signature but its exp claim has passed |
AUTH_TOKEN_EXPIRED should trigger a refresh attempt.
Silent Refresh Pattern (Frontend)
The Next.js frontend uses a silent refresh pattern so users are never interrupted by token expiry:- A protected API call returns
401 AUTH_TOKEN_EXPIRED. - The client calls
POST /api/v1/auth/refreshwith the stored refresh token. - On success, the new access token is saved and the original request is retried transparently.
- If the refresh call also fails (e.g. the refresh token has itself expired), the user is redirected to the login page.
localStorage or sessionStorage.
Never store JWTs in
localStorage in production. Browser storage is accessible to any JavaScript running on the page, making tokens vulnerable to XSS attacks. Keep access tokens in memory and refresh tokens in a secure, HttpOnly cookie or in-memory store.WebSocket Authentication
Browsers cannot set custom headers during a WebSocket handshake, so the access token is passed as a query parameter instead:401 response before the WebSocket connection is established.