Key Validation
The validation endpoint is how Hokusai services verify incoming API keys. It checks that a key is active, not expired, authorized for the requested service, and optionally validates scopes and IP restrictions.
POST /api/v1/keys/validate
The validation endpoint is public — it does not require an admin token. This allows any Hokusai microservice to validate keys independently.
Sending API Keys
There are three ways to send an API key for validation, listed in priority order:
Method 1: Authorization Header (Recommended)
curl -X POST https://auth.hokus.ai/api/v1/keys/validate \
-H "Authorization: Bearer hk_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"service_id": "prediction"}'
Method 2: X-API-Key Header
curl -X POST https://auth.hokus.ai/api/v1/keys/validate \
-H "X-API-Key: hk_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"service_id": "prediction"}'
Method 3: Request Body
curl -X POST https://auth.hokus.ai/api/v1/keys/validate \
-H "Content-Type: application/json" \
-d '{
"api_key": "hk_live_YOUR_API_KEY",
"service_id": "prediction"
}'
Use the Authorization header for production integrations. It follows the OAuth 2.0 Bearer Token standard and keeps keys out of request bodies and server logs.
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
service_id | string | No | Verify the key is authorized for this service |
required_scope | string | No | Verify the key has this specific scope |
client_ip | string | No | Check IP against the key's allowlist (auto-detected if omitted) |
api_key | string | No | API key (only needed if not sent via header) |
Validation Flow
Response
Successful Validation
{
"is_valid": true,
"key_id": "550e8400-e29b-41d4-a716-446655440000",
"user_id": "admin",
"service_id": "prediction",
"scopes": ["predict", "read"],
"rate_limit_per_hour": 5000,
"billing_plan": "free",
"monthly_prediction_limit": null
}
Failed Validation
{
"is_valid": false,
"key_id": null,
"user_id": null,
"service_id": null,
"scopes": null,
"rate_limit_per_hour": null,
"billing_plan": null,
"monthly_prediction_limit": null,
"error": "API key is inactive or has been revoked"
}
Caching Behavior
Validation results are cached in Redis for 5 minutes (configurable via CACHE_TTL). This means:
- First validation of a key queries the database and caches the result
- Subsequent validations within 5 minutes are served from cache (under 5ms response time)
- Key revocation invalidates the cache immediately
- Key rotation invalidates the old key's cache entry
- If Redis is unavailable, every validation falls back to a database query
After revoking a key, there may be up to a 5-minute window where cached validation results still return is_valid: true from other service instances. For immediate revocation, consider reducing the CACHE_TTL or triggering a cache flush.
Integration Examples
Python Service Integration
import requests
from functools import wraps
from flask import request, jsonify
AUTH_SERVICE_URL = "https://auth.hokus.ai"
def require_api_key(service_id: str, required_scope: str = None):
"""Decorator to validate API keys on incoming requests."""
def decorator(f):
@wraps(f)
def wrapper(*args, **kwargs):
api_key = request.headers.get("Authorization", "").replace("Bearer ", "")
if not api_key:
api_key = request.headers.get("X-API-Key", "")
if not api_key:
return jsonify({"error": "API key required"}), 401
validation = requests.post(
f"{AUTH_SERVICE_URL}/api/v1/keys/validate",
headers={"Authorization": f"Bearer {api_key}"},
json={
"service_id": service_id,
"required_scope": required_scope,
"client_ip": request.remote_addr,
},
).json()
if not validation.get("is_valid"):
return jsonify({"error": validation.get("error", "Invalid API key")}), 401
request.key_info = validation
return f(*args, **kwargs)
return wrapper
return decorator
@app.route("/predict")
@require_api_key(service_id="prediction", required_scope="predict")
def predict():
# request.key_info contains validation result
rate_limit = request.key_info["rate_limit_per_hour"]
# ... handle prediction
JavaScript / Node.js Integration
const AUTH_SERVICE_URL = "https://auth.hokus.ai";
async function validateApiKey(req) {
const apiKey =
req.headers.authorization?.replace("Bearer ", "") ||
req.headers["x-api-key"];
if (!apiKey) {
throw new Error("API key required");
}
const response = await fetch(`${AUTH_SERVICE_URL}/api/v1/keys/validate`, {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
service_id: "prediction",
client_ip: req.ip,
}),
});
const result = await response.json();
if (!result.is_valid) {
throw new Error(result.error || "Invalid API key");
}
return result;
}
Status Codes
| Status | Meaning |
|---|---|
200 | Key is valid |
400 | No API key provided in request |
401 | Key is invalid, expired, revoked, or fails scope/IP checks |
500 | Internal server error |
Next Steps
- Usage & Billing — Track API usage per key
- Security — IP allowlisting and scope management
- Troubleshooting — Debug validation failures