st body. All configuration and authorization are handled through HTTP headers.
| Header | Type | Description |
|---|
X-Local-Crawler-Secret | string | The secret token validated by authorizeLocalCrawlerApi(). Must match the LOCAL_CRAWLER_UI_SECRET environment variable. |
Accept | string | application/json (recommended) |
Example Request Structure
GET /api/local-only/category-stats HTTP/1.1
Host: your-domain.com
X-Local-Crawler-Secret: <your-secret-token>
Accept: application/json
No additional parameters are supported. The endpoint performs a full aggregation on each call and returns a point-in-time snapshot.
Success Response (200 OK)
The endpoint returns a JSON object containing category-level statistics, uncategorized article counts, and a generation timestamp.
{
"success": true,
"categories": [
{
"slug": "getting-started",
"name": "ε
₯ι¨ζε",
"nameEn": "Getting Started",
"publishedCount": 14,
"totalWithStatus": 18
},
{
"slug": "api-reference",
"name": "API εθ",
"nameEn": "API Reference",
"publishedCount": 42,
"totalWithStatus": 45
}
],
"uncategorizedPublished": 3,
"timestamp": "2024-06-15T10:32:00.000Z"
}
Response Fields
| Field | Type | Description |
|---|
success | boolean | Always true on successful execution. |
categories | array | List of category objects with aggregated metrics. |
categories[].slug | string | URL-friendly identifier for the category. |
categories[].name | string | Localized category name. |
categories[].nameEn | string | English fallback name. |
categories[].publishedCount | number | Count of articles with status = 'PUBLISHED'. |
categories[].totalWithStatus | number | Count of articles where status IS NOT NULL. |
uncategorizedPublished | number | Published articles not linked to any category. |
timestamp | string | ISO 8601 timestamp of when the query was executed. |
Error Responses
| Status Code | JSON Payload | Trigger Condition |
|---|
401 | {"error": "Unauthorized"} | Missing or invalid X-Local-Crawler-Secret header. |
404 | {"error": "Not found"} | Local crawler UI feature is disabled via environment configuration. |
500 | {"error": "SUPABASE_SERVICE_ROLE_KEY not configured"} | Required Supabase service key is missing from environment variables. |
500 | {"error": "Failed to fetch categories"} | Database query for the Category table failed. |
500 | {"error": "<database-error-message>"} | Any other Supabase/PostgreSQL error during execution. |
Usage Example
The following curl command demonstrates a standard request to retrieve category statistics:
curl -X GET "https://your-domain.com/api/local-only/category-stats" \
-H "X-Local-Crawler-Secret: your-secret-token-here" \
-H "Accept: application/json"
Expected Output:
{
"success": true,
"categories": [
{
"slug": "tutorials",
"name": "ζη¨",
"nameEn": "Tutorials",
"publishedCount": 28,
"totalWithStatus": 31
}
],
"uncategorizedPublished": 0,
"timestamp": "2024-06-15T10:32:00.000Z"
}
Common Pitfalls
- Missing Authorization Header: Despite the endpoint being publicly routable, the application layer strictly validates the
X-Local-Crawler-Secret header. Omitting this header or providing an incorrect value will immediately return a 401 Unauthorized response. Ensure your crawler or client injects the correct secret before making requests.
- Feature Flag Disabled: The endpoint is guarded by
assertLocalCrawlerUiEnabled(). If the local crawler UI feature is disabled in your environment configuration, the endpoint will return a 404 Not found response rather than a 403 or 503. Verify that the feature flag is active in your deployment environment.
- Memory-Intensive Aggregation: The endpoint fetches all article IDs and category-article relations into application memory before performing Set-based aggregation. While efficient for moderate-sized knowledge bases, extremely large datasets (100k+ articles) may cause temporary memory spikes or longer response times. For high-frequency polling, consider implementing client-side caching or scheduling requests during off-peak hours.
This endpoint is typically used in conjunction with other content synchronization and category management APIs within the platform:
- Category Listing Endpoints: Used to fetch full category metadata, hierarchy, and routing paths. Pair these with
/category-stats to render navigation trees with live article counters.
- Article Metadata Sync APIs: Used to pull individual article details, slugs, and status flags. Cross-reference these with the
publishedCount and totalWithStatus metrics to validate content pipeline health.
- Uncategorized Content Auditing: The
uncategorizedPublished field is designed to feed into content governance workflows that automatically flag or route orphaned articles to appropriate categories.
By integrating this endpoint into your content pipeline, you can maintain accurate category metrics, automate uncategorized content detection, and ensure your knowledge base navigation reflects real-time publishing activity.