API Keys
API keys provide stateless authentication for server-to-server communication, automated scripts, and environments where browser-based sessions are not practical. Keys are scoped to a user and can optionally restrict which resources and actions are permitted.
Creating a Key
Send a POST request to the /token endpoint with the user's credentials and
optional permissions:
{
"email": "user@example.com",
"password": "your-password",
"permissions": {
"posts": { "read": ["id", "title", "body"], "create": ["title", "body"] },
"comments": { "read": ["id", "text"] }
}
}
The response includes the full API key (prefixed with sna_). This is the only
time the key is returned in plain text — Snaapi stores a hashed version
internally.
Key Properties
Each API key has the following properties:
| Property | Type | Description |
|---|---|---|
id |
uuid | Unique identifier |
name |
string | Human-readable label |
prefix |
string | First characters of the key (for identification) |
start |
string | First 6–10 characters for secret scanning |
userId |
string | Owner of the key |
enabled |
boolean | Whether the key is active |
permissions |
JSON | Scoped resource/action/field permissions |
metadata |
JSON | Custom metadata |
expiresAt |
datetime | Optional expiration timestamp |
rateLimitEnabled |
boolean | Whether rate limiting is active |
rateLimitMax |
number | Maximum requests per time window |
rateLimitTimeWindow |
number | Time window duration (milliseconds) |
refillInterval |
number | How often the request bucket refills |
refillAmount |
number | Number of requests restored per refill |
requestCount |
number | Total requests made with this key |
remaining |
number | Requests remaining in the current window |
lastRequest |
datetime | Timestamp of the most recent request |
Permissions Structure
The KeyPermissionsSchema maps resource names to actions and their allowed
fields:
// { resourceName: { action: [field1, field2, ...] } }
{
"posts": {
"read": ["id", "title", "body"],
"create": ["title", "body"]
},
"users": {
"read": ["id", "email"]
}
}
When a key has scoped permissions, they are intersected with the user's role permissions at request time. The effective permission is the narrower of the two — the key can never grant more access than the role allows.
If no permissions are specified, the key inherits the full permissions of the
user's role.
Rate Limiting
Rate limiting is enabled by default for API keys. The global default can be configured with:
SNAAPI_RATE_LIMIT_PER_MIN=200
Per-key overrides are set via the key's rateLimitMax, rateLimitTimeWindow,
refillInterval, and refillAmount properties.
When a key exceeds its rate limit, subsequent requests receive a
429 Too Many Requests response until the window resets or refills.
When to Use Keys vs Sessions
| Scenario | Recommended |
|---|---|
| Browser-based applications | Session |
| Server-to-server integrations | API key |
| Automated scripts and CI/CD | API key |
| Mobile apps with user login | Session |
| Third-party webhook consumers | API key |
| Short-lived interactive actions | Session |
Sessions are tied to a browser cookie and require no manual token management. API keys are long-lived, portable, and suited for non-interactive environments where cookies are impractical.