API Keys
FORGE includes a complete API key management system for granting third-party applications and services secure access to your API. Keys support granular permissions, rate limiting, expiration, and revocation.
Overview
API keys provide an alternative authentication mechanism to user sessions. They are designed for server-to-server integrations, mobile applications, and any external system that needs to call your API programmatically. Each key has its own permission set and rate limit.
Database Schema
The api_keys table stores all issued keys:
| Column | Type | Description |
|---|---|---|
id | UUID | Primary key |
name | VARCHAR(255) | Human-readable label (e.g., "Mobile App") |
key_hash | VARCHAR(64) | SHA-256 hash of the full key |
key_prefix | VARCHAR(8) | First 8 characters for identification |
permissions | JSONB | Array of permitted actions |
rate_limit | INTEGER | Maximum requests per minute |
last_used_at | TIMESTAMP | Last time the key was used |
last_used_ip | VARCHAR(45) | IP address of the last request |
request_count | BIGINT | Total number of requests made with this key |
expires_at | TIMESTAMP | Key expiration date (nullable for no expiration) |
revoked_at | TIMESTAMP | When the key was revoked (nullable) |
revoked_by | UUID | User who revoked the key (nullable) |
revoked_reason | TEXT | Reason for revocation (nullable) |
created_by | UUID | User who created the key |
created_at | TIMESTAMP | Record creation timestamp |
updated_at | TIMESTAMP | Last update timestamp |
Security Model
API keys follow a write-once security model:
Key Creation Flow
─────────────────
1. Admin creates a key → Full key returned ONCE
2. Key is hashed (SHA-256) → Only the hash is stored
3. Key prefix saved → First 8 chars for display
4. Admin copies the key → Key is never shown again
Key Validation Flow
───────────────────
1. Client sends X-API-Key header
2. Server hashes the received key
3. Hash is compared against stored key_hash
4. Permissions and expiration are checkedWARNING
The full API key is displayed only once at creation time. It cannot be retrieved later. If a key is lost, it must be revoked and a new one created.
Permissions Array
The permissions JSONB column stores an array of allowed actions:
["contents:read", "contents:write", "menus:read", "lookups:read"]Common permission patterns:
| Permission | Description |
|---|---|
contents:read | Read content pages |
contents:write | Create and update content |
users:read | Read user data |
users:write | Create and update users |
menus:read | Read menu structure |
lookups:read | Read lookup values |
* | Full access (all permissions) |
Authentication
API keys are sent via the X-API-Key HTTP header:
curl -X GET /api/contents \
-H "X-API-Key: fk_a1b2c3d4e5f6g7h8i9j0..."The middleware validates the key on every request:
- Extract the key from the
X-API-Keyheader - Compute the SHA-256 hash
- Look up the hash in the
api_keystable - Verify the key is not expired (
expires_at) - Verify the key is not revoked (
revoked_at) - Check that the requested action is in the
permissionsarray - Enforce the
rate_limit - Update
last_used_at,last_used_ip, andrequest_count
TIP
API key authentication and user session authentication are mutually exclusive on a single request. If both are provided, the API key takes precedence.
Rate Limiting
Each API key has its own rate_limit (requests per minute). When the limit is exceeded, the API returns:
HTTP/1.1 429 Too Many Requests
Retry-After: 30
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705312800Admin Interface
The admin panel provides full API key lifecycle management:
- Create Key -- Set name, permissions, rate limit, and optional expiration. The full key is displayed once in a copy-friendly dialog.
- View Keys -- List all keys showing name, prefix, status, last used date, and request count.
- Revoke Key -- Immediately disable a key with an optional reason. Revoked keys cannot be reactivated.
Key States
| State | Condition | Can be used? |
|---|---|---|
| Active | Not expired, not revoked | Yes |
| Expired | expires_at is in the past | No |
| Revoked | revoked_at is set | No |
WARNING
Revoking a key is permanent and takes effect immediately. Any integrations using the revoked key will begin receiving 401 Unauthorized responses. Coordinate with third-party consumers before revoking.
Audit Trail
All API key actions are recorded in the audit log. When a request is made with an API key, the api_key_id field in the audit record is populated, providing full traceability of third-party actions.