AuthAPI Authentication Guide

API Authentication Guide

How to authenticate requests to the bloqr-backend API.

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://api.bloqr.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:

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

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

# Compile with API key
curl -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')