API Keys & Products¶
API keys and products are managed by the identity service and enforced by the gateway.
API Keys¶
API keys provide machine-to-machine authentication and a way for users and external systems to call the gateway without an OAuth session.
Key Format¶
mk_live_<64 hex characters>
The mk_live_ prefix makes keys easy to identify in logs and scrubbing tools. The raw key value is returned once at creation and is never stored — only its SHA-256 hash is kept.
Creating an API Key¶
POST /api-keys
Authorization: Bearer <user-jwt>
Content-Type: application/json
{
"name": "My CI pipeline key",
"scopes": ["workflows:invoke", "workflows:read"],
"expires_at": "2026-12-31T23:59:59Z"
}
Response (raw key shown once):
{
"id": "ak_abc123",
"name": "My CI pipeline key",
"key": "mk_live_a1b2c3d4...",
"key_prefix": "mk_live_a",
"scopes": ["workflows:invoke", "workflows:read"],
"expires_at": "2026-12-31T23:59:59Z",
"created_at": "2025-01-15T10:00:00Z"
}
Scope Inheritance¶
- If
scopesis empty ([]), the key inherits all of the owner's current scopes at request time - If
scopesis set, the effective scopes are the intersection of the key's declared scopes and the owner's permissions
This means reducing a user's permissions also automatically reduces the key's effective scope — even without regenerating the key.
Key Endpoints¶
| Method | Path | Auth | Description |
|---|---|---|---|
POST |
/api-keys |
User JWT | Create new key |
GET |
/api-keys |
User JWT | List own keys (no raw values) |
DELETE |
/api-keys/{id} |
User JWT | Revoke key |
POST |
/api-keys/validate |
Internal | Validate raw key (gateway use only) |
GET |
/admin/api-keys |
Admin | List all keys |
DELETE |
/admin/api-keys/{id} |
Admin | Revoke any key |
Revoking Keys¶
A revoked key is immediately rejected by the identity service. The gateway's 60-second validation cache means a revoked key may still work for up to 60 seconds after revocation.
Products¶
A product bundles API access rights with a rate-limit quota. Users and groups are assigned products to control how much and what they can call.
Product Model¶
{
"id": "pro-tier",
"name": "Pro Tier",
"description": "10,000 requests per hour",
"rate_limit_max_requests": 10000,
"rate_limit_window_seconds": 3600,
"allowed_route_ids": "*"
}
allowed_route_ids is either "*" (all routes) or a comma-separated list of route IDs.
Product Endpoints¶
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/products |
User JWT | Own assigned products |
POST |
/products |
Admin | Create product |
PUT |
/products/{id} |
Admin | Update product |
DELETE |
/products/{id} |
Admin | Delete product |
PUT |
/products/{id}/users/{username} |
Admin | Assign to user |
DELETE |
/products/{id}/users/{username} |
Admin | Remove from user |
PUT |
/products/{id}/groups/{group} |
Admin | Assign to group |
DELETE |
/products/{id}/groups/{group} |
Admin | Remove from group |
Assignment Priority¶
When a caller has multiple products (via user + group assignments), the first matching product is used (user direct assignments before group assignments). Configure a fallback_product in the rate_limit_product policy to handle callers with no product assigned.
Product-Based Rate Limiting in Policies¶
The rate_limit_product policy type applies per-caller quotas using the product system:
type: rate_limit_product
apply_to: ["*"]
apply_to_triggers: ["http"]
strategy: sliding_window
fallback_product: free-tier
on_violation: reject
See Policies Reference for the full policy YAML reference (Forgejo mirror: Policies Reference).
Related Pages¶
- Identity & Authentication
- Gateway Hardening
- Policies Reference (Forgejo mirror: Policies Reference)