Skip to main content
The GenieHelper server runs as a forked AnythingLLM Express process on port 3001. All GenieHelper-specific endpoints are mounted under /api/ alongside the standard AnythingLLM routes.

Base URL

http://localhost:3001
For production deployments, the server is proxied behind Nginx with WebSocket support. All requests to /api/genie/*, /api/queue/*, /api/credentials/*, /api/skills/*, and /api/usage are served by this process.

Authentication

All GenieHelper custom endpoints require a Directus JWT passed as a Bearer token in the Authorization header.
Authorization: Bearer <directus_jwt>
The token is issued by Directus on login and carries the user’s identity, role, and subscription tier. The unifiedAuth middleware (server/utils/middleware/unifiedAuth.js) validates the Directus JWT on every request, bridges the Directus user to the corresponding Prisma/AnythingLLM user via anythingllm_user_id, and attaches req.directusUser for downstream handlers.
The same Directus JWT works across both GenieHelper custom endpoints and native AnythingLLM endpoints. You do not need separate tokens.
Tokens are short-lived. The dashboard handles auto-refresh. If you are calling the API directly, refresh your token before it expires to avoid 401 errors.

Endpoints

MethodPathDescription
POST/api/genie/stream-chatSend a message; returns an SSE stream with the agent response
GET/api/queue/statsRead BullMQ queue depths and taxonomy cache status
POST/api/queue/mediaEnqueue a media processing job
POST/api/queue/retry/:jobIdRe-enqueue a failed media job
POST/api/queue/taxonomy/invalidateBust the taxonomy DuckDB cache
POST/api/credentials/storeEncrypt and persist platform credentials
POST/api/credentials/revealDecrypt and return platform credentials
GET/api/skillsList available agent skills with filtering and pagination
GET/api/skills/:idFetch a single skill by UUID or name
POST/api/skills/activateStimulus propagation — find relevant skills for a task
POST/api/skills/searchFull-text skill search
GET/api/skills/:id/relatedGet skills related to a given skill
GET/api/usageRead current user’s subscription quota and remaining allowances
POST/api/usage/incrementIncrement a usage counter for a billable action
POST/api/registerInvite-gated public registration (rate-limited)
GET/PATCH/api/onboardingOnboarding state machine read and update
POST/api/rbac-syncWebhook: sync Directus role change to AnythingLLM permissions
POST/api/impersonateAdmin-only: swap session to impersonate a user
POST/api/captions/generateGenerate AI captions with quota enforcement
GET/PATCH/api/user-proxyUser profile read and file upload via admin-token proxy
GET/api/fansFan profile data retrieval
POST/api/posts/scheduleCreate a scheduled post with tier quota enforcement
POST/api/gooseGoose agent admin operations

Rate limiting

Only the registration endpoint is rate-limited at the Express layer:
RouteLimitWindow
POST /api/register10 requests15 minutes
This limit is enforced by express-rate-limit in server/endpoints/api/register.js and applies per IP address. It protects the invite-gated registration flow from abuse. All other endpoints are not rate-limited at the HTTP layer. Instead, billable operations are governed by subscription tier quotas (see below).

Subscription quota enforcement

All quota-gated operations pass through subscriptionValidator.js before executing:
const { allowed, reason } = await canPerform(userId, operationType, directusClient);
if (!allowed) return res.status(403).json({ error: 'tier_limit_reached', reason });
canPerform() reads the user’s current usage from the user_usage_counts Directus collection and compares it against the limits defined in config/tier_rate_limits.json. The validator is fail-closed: if anything goes wrong reading quota data — network error, missing collection, unexpected exception — the function returns { allowed: false, reason: 'quota_check_failed' } rather than letting the request through.
Quota enforcement is fail-closed by design. If subscriptionValidator.js cannot reach Directus, the request is denied. Ensure MCP_SERVICE_TOKEN is valid and Directus is reachable.

Tier limits at a glance

FeatureStarterCreatorProStudio
Caption generation3/mo50/mo200/moUnlimited
Taxonomy AI calls10/mo100/mo500/moUnlimited
AI media operations5/mo30/mo150/moUnlimited
Limits are sourced from config/tier_rate_limits.json. Usage resets at the start of each billing cycle.

Error responses

All endpoints return JSON error responses in the following format:
{
  "error": "Human-readable error message",
  "reason": "machine_readable_code"
}
HTTP statusMeaning
400Missing or invalid request body parameters
401Missing, expired, or invalid Directus JWT
403Valid token but insufficient permissions or tier quota exhausted
404Requested resource not found
429Rate limit exceeded (registration endpoint only)
500Unexpected server error
503Account setup incomplete (e.g., missing AnythingLLM workspace)

Stream Chat

POST /api/genie/stream-chat — SSE streaming, Node RAG, ACTION interception

Job Queue

POST/GET /api/queue — BullMQ job enqueue and status polling

Credentials

POST /api/credentials — AES-256-GCM encrypted platform credential storage

Skills

GET/POST /api/skills — skill discovery and stimulus propagation

Usage

GET /api/usage — subscription quota status for the current billing cycle

Build docs developers (and LLMs) love