Overview
The High IQ API uses a tiered authentication model. Most strain data endpoints are publicly accessible with no authentication required. Protected endpoints use either an X-Admin-Key header (for administrative operations) or Authorization: Bearer tokens (for internal cron jobs and pipeline triggers).
Authentication Tiers
| Tier | Header | Use Case | Example Endpoints |
|---|
| Public | None | Strain data, search, catalog | GET /strains, GET /strains/search |
| Admin | X-Admin-Key: <key> | Administrative operations | POST /blog/generate-image |
| Internal | Authorization: Bearer <api_key> | Cron jobs, pipelines | GET /cron/*, POST /admin/trigger |
Public Endpoints
The majority of API endpoints are public and require no authentication. These include all strain data retrieval, search, filtering, and catalog operations.
# No authentication needed
curl "https://tiwih-api.vercel.app/api/v1/strains/slug/blue-dream/complete"
curl "https://tiwih-api.vercel.app/api/v1/strains/search?q=sour+diesel"
curl "https://tiwih-api.vercel.app/api/v1/strains/popular"
User Authentication
User authentication in High IQ is handled through Clerk + Convex, not through the Hono API. The mobile app authenticates users via Clerk SSO (Apple or Google sign-in), and Clerk provides identity tokens that are validated by Convex for real-time user data operations. The Hono API does not validate Clerk JWTs — it serves strain data publicly and protects admin/internal endpoints with API keys.
Admin Authentication
Administrative endpoints are protected by the X-Admin-Key header. This is used for operations like blog image generation, batch processing, and other privileged actions.
curl -X POST "https://tiwih-api.vercel.app/api/v1/blog/generate-image" \
-H "Content-Type: application/json" \
-H "X-Admin-Key: your-admin-api-key" \
-d '{"slug": "best-terpenes-for-sleep"}'
Security Features
The admin authentication middleware uses constant-time string comparison to prevent timing attacks. This ensures that an attacker cannot determine partial key matches by measuring response times.
// Constant-time comparison prevents timing oracle attacks
function secureCompare(a: string, b: string): boolean {
const maxLength = Math.max(a.length, b.length);
let result = a.length ^ b.length;
for (let i = 0; i < maxLength; i++) {
const charA = i < a.length ? a.charCodeAt(i) : 0;
const charB = i < b.length ? b.charCodeAt(i) : 0;
result |= charA ^ charB;
}
return result === 0;
}
Missing or Invalid Key
If the X-Admin-Key header is missing:
{
"success": false,
"error": "Admin authentication required",
"code": "ADMIN_AUTH_REQUIRED",
"message": "Missing X-Admin-Key header"
}
If the key is invalid:
{
"success": false,
"error": "Invalid admin API key",
"code": "ADMIN_AUTH_INVALID"
}
Internal Bearer Authentication
Internal endpoints (cron jobs, pipeline triggers) use Bearer token authentication validated against server-side environment variables (API_KEY, CRON_SECRET).
API Key
Cron Secret
Either Key
# Manual admin trigger
curl -X POST "https://tiwih-api.vercel.app/api/v1/admin/backfill" \
-H "Authorization: Bearer your-api-key"
# Vercel cron job (sent automatically by Vercel)
curl "https://tiwih-api.vercel.app/api/v1/cron/daily-sync" \
-H "Authorization: Bearer your-cron-secret"
# Endpoints accepting either key (manual or automated)
curl -X POST "https://tiwih-api.vercel.app/api/v1/trigger/pipeline" \
-H "Authorization: Bearer your-api-key-or-cron-secret"
Security Model
| Environment | Behavior |
|---|
| Production | Fail-closed: denies access if secrets are not configured |
| Development | Fail-open: allows access for easier local testing |
In production, if the required environment variable (API_KEY or CRON_SECRET) is not configured, the middleware denies all access rather than allowing unauthenticated requests through. This is a deliberate security design.
Development Bypass
In development mode or when accessing via localhost, authentication is automatically bypassed for both admin and bearer auth middleware. This allows for easier local development and testing without configuring secrets.
# localhost requests bypass auth automatically
curl "http://localhost:3001/api/v1/blog/generate-image" \
-X POST \
-H "Content-Type: application/json" \
-d '{"slug": "test-post"}'
The bypass applies when any of these conditions are met:
NODE_ENV=development
- Request host contains
localhost
- Request host contains
127.0.0.1
A DEV_BYPASS_KEY environment variable can also be configured for remote device testing (e.g., testing from a phone on the local network). When set, requests with X-Admin-Key matching this value are allowed through.
Error Codes Reference
| Code | HTTP Status | Description |
|---|
UNAUTHORIZED | 401 | Authentication required but not provided |
ADMIN_AUTH_REQUIRED | 401 | Missing X-Admin-Key header |
ADMIN_AUTH_INVALID | 401 | Invalid admin API key |
ADMIN_AUTH_NOT_CONFIGURED | 500 | Server misconfiguration (no key set) |