API Keys Module
Manage programmatic access tokens for external integrations and developer tools.
Description
The API Keys module allows users to generate long-lived access tokens for programmatic interaction with the VeriWorkly API.
Unlike session-based authentication which is designed for browser use, API Keys are intended for CLI tools, CI/CD pipelines, and personal automation scripts.
Security Model
To protect your account, VeriWorkly implements a strict visibility policy for keys:
- One-Time Secret: The raw API key is only returned once — in the response to the
POSTthat created (or rotated) it. It is stored solely as an HMAC-SHA256 hash and can never be read back. - No masked secret: List operations return no form of the secret at all, not even a masked
one. Each entry carries
keyPrefix— the first 8 characters, e.g.vw_a1b2c— which is enough to tell keys apart. If you lose a secret, rotate the key. - Format:
vw_followed by 64 hexadecimal characters. - Expiry: Every key expires. When you don't supply
expiresAt, it defaults to 365 days out. - Rate Limiting: Each key has its own limit (default 20 requests / 15 minutes, capped at 20).
Responses carry
X-RateLimit-Limit,X-RateLimit-Remaining, andX-RateLimit-Reset.
Managing keys requires a session
Every endpoint in this module is session-only — you cannot use an API key to list, create, rotate, revoke, or delete API keys.
Scopes
Keys are scope-gated. A request whose key lacks the scope a route requires is rejected with 403.
Session callers are never scope-gated. Scopes default to ["user:read"] when you don't specify
any, and requesting a value outside this set fails with 400.
| Scope | Grants |
|---|---|
user:read | GET /users/me |
user:write | PUT /users/me/name, /users/me/username, /users/me/sync |
resume:read | Reading documents, the master profile, and share links |
resume:write | Creating/updating/deleting documents and share links |
roadmap:read | Roadmap endpoints |
changelog:read | Changelog endpoints |
github:read | GitHub stats and issues |
ai:write | POST /ai/generate, /ats/analyze, /ats/convert-resume |
Key Lifecycle
| Action | Description |
|---|---|
| Creation | Generate a key with a custom name, scopes, and rate limit. Store the secret immediately — it is shown once. |
| Usage | Send the key as X-API-Key: vw_... or Authorization: Bearer vw_.... Both headers are accepted. |
| Rotation | Issue a replacement and revoke the old key in one transaction. Send an empty body to carry all settings over. |
| Soft revoke | Disable a key without removing its record. Takes effect immediately; a revoked key cannot be reactivated. |
| Deletion | Permanently remove a key and its record. |
Available Endpoints
GET /api-keys— List API KeysGET /api-keys/{id}— Get API KeyPOST /api-keys— Create API KeyPOST /api-keys/{id}/rotate— Rotate API KeyPOST /api-keys/{id}/revoke— Revoke API KeyDELETE /api-keys/{id}— Delete API Key
Sign OutPOST
Revokes the current session and clears the session cookie. Also flushes the server-side session cache for that cookie. This endpoint returns Better Auth's payload, not the `{ success, message, data }` envelope.
List API KeysGET
Lists the caller's API keys, newest first. **No form of the secret is returned here — not even a masked one.** Each entry carries only `keyPrefix`, the first 8 characters of the key, which is enough to tell keys apart in a list. If you lose a secret, rotate the key. Session-authenticated only — an API key cannot be used to manage API keys.