Skip to content

API Authentication Guide

API Authentication Guide

How to authenticate requests to the bloqr-backend API.

Overview

The bloqr-backend API supports three authentication methods:

  1. Clerk JWT — For browser-based users (automatic via the web UI)
  2. API Key — For programmatic/CLI access
  3. 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://bloqr-backend.jk-com.workers.dev/, authentication is handled automatically:

  1. Sign in via the Clerk-powered sign-in page
  2. The Angular frontend obtains a JWT from Clerk
  3. The authInterceptor attaches it to all API requests as Authorization: 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

  1. Sign in to the web UI
  2. Navigate to Settings → API Keys
  3. Click “Create API Key”
  4. Configure:
    • Name: Descriptive label (e.g., “CI/CD Pipeline”, “My Script”)
    • Scopes: Select permissions — compile, rules, or admin
    • Expiration: Optional (1–365 days)
  5. 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:

Terminal window
curl -X POST https://bloqr-backend.jk-com.workers.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

ScopeGrants 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

LimitValue
Max keys per user25
Rate limitBased on owner’s tier (default: 60 req/min)
Expiration1–365 days (optional; never-expiring allowed)
Key name max length100 characters

Managing API Keys

ActionEndpointMethod
Create/api/keysPOST
List/api/keysGET
Update/api/keys/:idPATCH
Revoke/api/keys/:idDELETE

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:

TierRate LimitHow to Get
Anonymous10 req/minNo auth (being deprecated)
Free60 req/minSign up for free account
Pro300 req/minUpgrade to Pro subscription
AdminUnlimitedAdmin role in Clerk

Rate limit headers are included in every response:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1700000000

When 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:

EndpointMethodDescription
/api/versionGETAPI version information
/api/clerk-configGETClerk publishable key
/api/turnstile-configGETTurnstile configuration
/healthGETHealth check
/api/webhooks/clerkPOSTClerk webhook receiver

Authenticated Endpoints (Auth Required After Migration)

These endpoints currently allow anonymous access but will require authentication:

EndpointMethodCurrentAfter Migration
/compilePOSTAnonymous + TurnstileFree+
/compile/streamPOSTAnonymous + TurnstileFree+
/compile/batchPOSTAnonymous + TurnstileFree+
/compile/asyncPOSTAnonymous + TurnstilePro+
/compile/batch/asyncPOSTAnonymous + TurnstilePro+
/validate-rulePOSTAnonymousFree+
/rulesGETAnonymousFree+
/rules/:idGETAnonymousFree+
/api/deploymentsGETAnonymousPublic (unchanged)
/metricsGETAnonymousFree+

Protected Endpoints (Auth Already Required)

EndpointMethodRequired Auth
/api/keysPOSTAuthenticated (any tier)
/api/keysGETAuthenticated (any tier)
/api/keys/:idDELETEAuthenticated (any tier)
/api/keys/:idPATCHAuthenticated (any tier)
/api/notifyPOSTAuthenticated (any tier)

Admin Endpoints

EndpointMethodRequired Auth
/admin/storage/statsGETAdmin key or Admin tier
/admin/storage/clear-expiredPOSTAdmin key or Admin tier
/admin/storage/clear-cachePOSTAdmin key or Admin tier
/admin/storage/exportGETAdmin key or Admin tier
/admin/storage/vacuumPOSTAdmin key or Admin tier
/admin/storage/tablesGETAdmin key or Admin tier
/admin/storage/queryPOSTAdmin 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 Authorization header
  • 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:

  1. Create an account — Sign up at the web UI
  2. Create an API key — For any scripts or integrations
  3. Update your scripts — Add Authorization: Bearer blq_... header
  4. Test — Verify your integration works with authentication
  5. Monitor rate limits — Free tier is 60 req/min (up from 10 anonymous)

See Removing Anonymous Access for the full migration plan.

Examples

cURL

Terminal window
# Compile with API key
curl -X POST https://bloqr-backend.jk-com.workers.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://bloqr-backend.jk-com.workers.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://bloqr-backend.jk-com.workers.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')