API Authentication Guide
API Authentication Guide
How to authenticate requests to the bloqr-backend API.
Overview
The bloqr-backend API supports three authentication methods:
- Clerk JWT — For browser-based users (automatic via the web UI)
- API Key — For programmatic/CLI access
- Anonymous — Limited access, being deprecated
Important: Anonymous access will be removed in a future release. All API endpoints will require authentication. See Removing Anonymous Access.
Authentication Methods
Method 1: Clerk JWT (Browser Users)
If you use the web UI at https://api.bloqr.dev/, authentication is handled automatically:
- Sign in via the Clerk-powered sign-in page
- The Angular frontend obtains a JWT from Clerk
- The
authInterceptorattaches it to all API requests asAuthorization: Bearer <jwt>
You don’t need to do anything — the frontend handles JWT lifecycle, refresh, and attachment.
Method 2: API Key (Programmatic Access)
For scripts, CI/CD pipelines, or third-party integrations, use an API key.
Creating an API Key
- Sign in to the web UI
- Navigate to Settings → API Keys
- Click “Create API Key”
- Configure:
- Name: Descriptive label (e.g., “CI/CD Pipeline”, “My Script”)
- Scopes: Select permissions —
compile,rules, oradmin - Expiration: Optional (1–365 days)
- Copy the key immediately — it’s shown only once
The key looks like: blq_a1b2c3d4e5f6... (blq_ prefix + 48 hex characters, 52 characters total). Legacy keys with the abc_ prefix are also still accepted.
Using an API Key
Include the key in the Authorization header:
curl -X POST https://api.bloqr.dev/compile \ -H "Authorization: Bearer blq_Xk9mP2..." \ -H "Content-Type: application/json" \ -d '{ "sources": ["https://raw.githubusercontent.com/user/list/main/filters.txt"], "transformations": ["validate", "deduplicate", "compress"] }'API Key Scopes
| Scope | Grants Access To |
|---|---|
compile | /compile, /compile/stream, /compile/batch |
rules | /rules CRUD endpoints |
admin | /admin/* endpoints |
Note: Clerk JWT-authenticated users bypass scope checks — scopes only apply to API key access.
API Key Limits
| Limit | Value |
|---|---|
| Max keys per user | 25 |
| Rate limit | Based on owner’s tier (default: 60 req/min) |
| Expiration | 1–365 days (optional; never-expiring allowed) |
| Key name max length | 100 characters |
Managing API Keys
| Action | Endpoint | Method |
|---|---|---|
| Create | /api/keys | POST |
| List | /api/keys | GET |
| Update | /api/keys/:id | PATCH |
| Revoke | /api/keys/:id | DELETE |
Method 3: Anonymous Access (Being Deprecated)
Currently, some endpoints allow unauthenticated access with severe rate limits (10 requests/minute). This will be removed in a future release.
Rate Limiting
Rate limits are enforced per-tier:
| Tier | Rate Limit | How to Get |
|---|---|---|
| Anonymous | 10 req/min | No auth (being deprecated) |
| Free | 60 req/min | Sign up for free account |
| Pro | 300 req/min | Upgrade to Pro subscription |
| Admin | Unlimited | Admin role in Clerk |
Rate limit headers are included in every response:
X-RateLimit-Limit: 60X-RateLimit-Remaining: 58X-RateLimit-Reset: 1700000000When rate-limited, you’ll receive:
HTTP/1.1 429 Too Many Requests
{ "success": false, "error": "Rate limit exceeded. Try again in 45 seconds.", "retryAfter": 45}Endpoint Protection Matrix
Public Endpoints (No Auth Required)
These endpoints remain publicly accessible:
| Endpoint | Method | Description |
|---|---|---|
/api/version | GET | API version information |
/api/clerk-config | GET | Clerk publishable key |
/api/turnstile-config | GET | Turnstile configuration |
/health | GET | Health check |
/api/webhooks/clerk | POST | Clerk webhook receiver |
Authenticated Endpoints (Auth Required After Migration)
These endpoints currently allow anonymous access but will require authentication:
| Endpoint | Method | Current | After Migration |
|---|---|---|---|
/compile | POST | Anonymous + Turnstile | Free+ |
/compile/stream | POST | Anonymous + Turnstile | Free+ |
/compile/batch | POST | Anonymous + Turnstile | Free+ |
/compile/async | POST | Anonymous + Turnstile | Pro+ |
/compile/batch/async | POST | Anonymous + Turnstile | Pro+ |
/validate-rule | POST | Anonymous | Free+ |
/rules | GET | Anonymous | Free+ |
/rules/:id | GET | Anonymous | Free+ |
/api/deployments | GET | Anonymous | Public (unchanged) |
/metrics | GET | Anonymous | Free+ |
Protected Endpoints (Auth Already Required)
| Endpoint | Method | Required Auth |
|---|---|---|
/api/keys | POST | Authenticated (any tier) |
/api/keys | GET | Authenticated (any tier) |
/api/keys/:id | DELETE | Authenticated (any tier) |
/api/keys/:id | PATCH | Authenticated (any tier) |
/api/notify | POST | Authenticated (any tier) |
Admin Endpoints
| Endpoint | Method | Required Auth |
|---|---|---|
/admin/storage/stats | GET | Admin key or Admin tier |
/admin/storage/clear-expired | POST | Admin key or Admin tier |
/admin/storage/clear-cache | POST | Admin key or Admin tier |
/admin/storage/export | GET | Admin key or Admin tier |
/admin/storage/vacuum | POST | Admin key or Admin tier |
/admin/storage/tables | GET | Admin key or Admin tier |
/admin/storage/query | POST | Admin key or Admin tier |
Error Responses
401 Unauthorized
Returned when authentication is required but not provided or invalid:
{ "success": false, "error": "Authentication required"}Common causes:
- Missing
Authorizationheader - Expired JWT (Clerk JWTs expire after ~60 seconds; the frontend auto-refreshes)
- Invalid or revoked API key
- Malformed Bearer token
403 Forbidden
Returned when authenticated but lacking permission:
{ "success": false, "error": "Insufficient tier: requires pro, current tier is free"}Common causes:
- Tier too low for the endpoint
- API key missing required scope
- CF Access verification failed (admin routes)
429 Too Many Requests
Returned when rate limit is exceeded:
{ "success": false, "error": "Rate limit exceeded. Try again in 30 seconds.", "retryAfter": 30}Migration Guide: Preparing for Required Auth
When anonymous access is removed:
- Create an account — Sign up at the web UI
- Create an API key — For any scripts or integrations
- Update your scripts — Add
Authorization: Bearer blq_...header - Test — Verify your integration works with authentication
- Monitor rate limits — Free tier is 60 req/min (up from 10 anonymous)
See Removing Anonymous Access for the full migration plan.
Examples
cURL
# Compile with API keycurl -X POST https://api.bloqr.dev/compile \ -H "Authorization: Bearer blq_your_api_key_here" \ -H "Content-Type: application/json" \ -d '{"sources": ["https://example.com/filters.txt"]}'JavaScript/TypeScript (fetch)
const response = await fetch('https://api.bloqr.dev/compile', { method: 'POST', headers: { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ sources: ['https://example.com/filters.txt'], transformations: ['validate', 'deduplicate'], }),});
if (response.status === 429) { const retryAfter = response.headers.get('Retry-After'); console.log(`Rate limited. Retry after ${retryAfter} seconds`);}Python (requests)
import requests
response = requests.post( 'https://api.bloqr.dev/compile', headers={'Authorization': f'Bearer {API_KEY}'}, json={ 'sources': ['https://example.com/filters.txt'], 'transformations': ['validate', 'deduplicate'], },)
if response.status_code == 429: retry_after = response.headers.get('Retry-After') print(f'Rate limited. Retry after {retry_after} seconds')Bloqr AI™ — The privacy you didn't know you needed.
© 2026 Bloqr AI™, a trademark of Bloqr Systems™. Created by Bloqr Systems™, founded by Jayson Knight.
Internet Hygiene (n.) — the ongoing practices that keep your digital life clean, private, and safe.
Our product repos live in the BloqrAI org, part of the Bloqr Systems GitHub Enterprise. Product repos are internal-visibility — enterprise membership is required to view them.