Viresso has two separate authentication flows:
- API keys are created in Viresso and are used to call the API from websites, apps, and servers.
- Hosted authentication access tokens are created by the hosted auth endpoints and identify an authenticated app user.
Do not use hosted auth access tokens as API keys.
API keys
API keys are workspace-scoped credentials. Create them from Settings → API Keys in Viresso.
Sending the API key
Pass the key via the Authorization header:
Authorization: Bearer {api_key}
API keys are not accepted in query parameters.
Each key can have full access or a limited set of abilities. Its effective access is also capped by the workspace permissions of the member who created it. See API Access for the complete ability list.
Origin restrictions
API keys can restrict allowed origins (e.g. example.com, *.example.com, localhost:5173). Origin restrictions are enforced against the Origin request header.
- For browser-based clients, create keys with origin restrictions matching your application domain.
- For server-side integrations, create keys without origin restrictions. A restricted key rejects requests without an
Originheader.
Reading file details and refreshing temporary URLs require files:read; file uploads require files:write; file deletions require files:delete. Each is also limited by the key creator's workspace permissions. Tokenized and signed temporary file downloads do not use API keys. Use temporary_url for an expiring link (10 minutes by default; file-details requests accept expires_in=30 through 600), or download_url for the existing permanent link. See Files API.
An origin mismatch returns 403 Forbidden:
{
"message": "Forbidden"
}
Hosted authentication
Hosted authentication adds passwordless app login on top of your Viresso content. It works with a configured content type in your workspace that contains an email field. When a visitor signs in, Viresso finds the matching entry and returns an access token for that app user.
These access tokens are strictly for hosted app authentication. They are not API keys and should not be used for server-to-server API access.
The hosted auth endpoints are available under POST /api/v1/{workspace}/auth. Each operation has its own rate-limit bucket so login attempts cannot consume the capacity used by real-time session validation:
| Operation | Limit and scope |
|---|---|
| Request a code | 10 requests per minute per email and 60 per IP |
| Verify a code | 10 requests per minute per OTP and 120 per IP |
| Exchange an auth code | 60 requests per minute per IP |
| Authenticate an access token | 600 requests per minute per access token |
If an allowed origin is configured for hosted login, hosted-auth requests that include an Origin header must normalize to that origin (host casing and default ports are treated equivalently). Server-side requests without an Origin header are not blocked by this browser-origin check.
Request a verification code
POST /api/v1/{workspace}/auth
Request body:
| Field | Type | Description |
|---|---|---|
email |
string (email) | The user's email address |
locale |
string | Locale for the verification email (optional, default en-US) |
Response (always 200, even if the email is not found — prevents enumeration):
{
"message": "If the email matches an account, a verification code has been sent.",
"otp_id": "uuid-string"
}
The otp_id is always returned so callers can follow the same flow without learning whether the email matched an entry. A verification email is only sent when the email matches a published entry.
Verify the code
POST /api/v1/{workspace}/auth/verify
Request body:
| Field | Type | Description |
|---|---|---|
otp_id |
string (UUID) | The OTP ID from the login response |
secret |
string (6 digits) | The verification code sent via email |
locale |
string | Locale for the response (optional, default en-US) |
Response:
{
"access_token": "random-80-char-string",
"expires_at": "2026-06-24T09:30:00.000000Z",
"user_data": { }
}
Each OTP can be attempted up to 3 times. After that, a new verification code must be requested.
Authenticate with an existing token
POST /api/v1/{workspace}/auth/authenticate
Request body:
| Field | Type | Description |
|---|---|---|
access_token |
string | An existing hosted auth access token |
locale |
string | Locale for the response (optional, default en-US) |
Response: Same shape as verify. Returns the same token (touches it, extends TTL).
Exchange an authorization code
POST /api/v1/{workspace}/auth/exchange
Request body:
| Field | Type | Description |
|---|---|---|
code |
string | An authorization code (generated server-side, 2-minute TTL) |
Response: Same shape as verify. Issues a new token.
Hosted auth token response
{
"access_token": "gH7sK...80-chars...9mQ2",
"expires_at": "2026-06-24T09:30:00.000000Z",
"user_data": {
"id": "01HY8M7M7D4RT5N6P2Q3R4S5T6",
"name": "Jane Doe",
"status": "published",
"fields": {
"full_name": "Jane Doe",
"email": "jane@example.com"
}
}
}
The user_data object is the rendered entry for the authenticated app user.
Token expiration
Hosted auth access tokens expire after 30 days. The authenticate endpoint resets the expiration. If a token expires, request a new verification code.
Related pages
- API Overview — Base URL, headers, and error handling.
- API Entries — Entry CRUD reference.
- API Access — API-key abilities, origin restrictions, and rotation.