HTTP API Reference
Endpoint-level overview of Durabull API resources, capabilities, and key limits.
Base URL
All endpoints are mounted under:
/api
Bootstrap and health:
GET /api/healthGET /api/app/configGET /api/modeGET /api/telemetry/statusPOST /api/telemetry/events
Authentication and Session
- Better Auth endpoints under
/api/auth/* - Session snapshot:
GET /api/session
In authless mode, auth endpoints return authless-safe behavior for session/signout and reject unsupported auth actions.
Remote App Config
GET /api/app/config is the client bootstrap endpoint used by the web app to load runtime mode and analytics settings.
Behavior:
- Always returns
200with JSON config. - Works for both authenticated and unauthenticated requests.
- In authless mode, returns authless/runtime flags from server env and mode.
- If a valid signed-in user is present (non-authless mode), the API attempts to update that user's
lastSignInAttimestamp before returning config.
Response shape:
{
"authless": false,
"envConnections": false,
"persistence": "postgres",
"stateless": false,
"environment": "production",
"posthog": {
"enabled": true,
"key": "phc_***",
"host": "/ingest",
"uiHost": "https://us.posthog.com"
},
"telemetry": {
"enabled": true,
"collectionRequired": true,
"dedupeIdentifiedPosthogEvents": false,
"disclosureUrl": "https://durabull.io/privacy"
}
}
Field notes:
authless: whetherDURABULL_AUTHLESSmode is active.envConnections: whether env-driven connection mode is active.persistence: server persistence mode (postgresorpglite).stateless:truewhen running inpglitemode.environment:NODE_ENV(development,test, orproduction; defaults todevelopment).posthog.enabled:truewhenPOSTHOG_KEYis set.posthog.key: PostHog project key (ornullwhen disabled). When set, Durabull preserves PostHog's native browser collection and sends manual analytics calls with their original properties to that project.posthog.host: always/ingest(Durabull's reverse-proxied analytics endpoint).posthog.uiHost: PostHog UI host used by the frontend.telemetry.enabled: whether Durabull anonymous/pseudonymous telemetry is active for this runtime.telemetry.collectionRequired: alwaystruefor production/self-hosted usage.telemetry.dedupeIdentifiedPosthogEvents:trueonly when the configured PostHog project is Durabull-managed, so anonymous Durabull telemetry can be deduplicated once a user has been identified in the same Durabull-owned PostHog stream.telemetry.disclosureUrl: public documentation for Durabull telemetry collection.
Anonymous Telemetry
Durabull routes sanitized product analytics through POST /api/telemetry/events. Event names remain
the same canonical names used by the app, such as queue_paused, connection_created, and
$pageview. Self-hosted instances re-sanitize payloads before forwarding them to Durabull's
existing cloud API at POST /api/telemetry/collect.
POSTHOG_KEY configures a PostHog destination for the cloud product or instance owner. It does not
disable Durabull anonymous telemetry, and Durabull does not provide a product-level telemetry
opt-out. When a self-hosted owner provides POSTHOG_KEY, they receive the full PostHog browser
stream for their project while Durabull still receives independently sanitized anonymous telemetry.
Durabull telemetry includes feature and route usage, safe runtime context, booleans, enums, and aggregate buckets. It does not include Redis URLs, queue names, Redis key names, job data, logs, emails, names, organizations, hostnames, raw URLs, search patterns, stack traces, or raw error messages.
Connection Management
GET /api/connectionsGET /api/connections/:idPOST /api/connectionsPATCH /api/connections/:idDELETE /api/connections/:idPOST /api/connections/test
When DURABULL_ENV_CONNECTIONS=true, create/update/delete routes return 403.
Connection-Scoped Resources
All routes below are under:
/api/c/:connectionId/...
Queues
GET /queuesGET /queues/:queueNameGET /queues/:queueName/metricsPOST /queues/:queueName/pausePOST /queues/:queueName/resumePOST /queues/:queueName/cleanPOST /queues/:queueName/purgePOST /queues/:queueName/obliterateDELETE /queues/:queueNameGET /queues/:queueName/can-delete
Jobs
GET /queues/:queueName/jobsGET /queues/:queueName/jobs/:jobIdGET /queues/:queueName/jobs/:jobId/logsDELETE /queues/:queueName/jobs/:jobId/logsGET /queues/:queueName/jobs/:jobId/stacktracesPOST /queues/:queueName/jobsPOST /queues/:queueName/jobs/retryPOST /queues/:queueName/jobs/removePOST /queues/:queueName/jobs/invoke
POST /queues/:queueName/jobs accepts optional BullMQ job options alongside name and data:
{
"name": "send-welcome-email",
"data": { "userId": "123" },
"delay": 5000,
"priority": 5,
"attempts": 3,
"backoff": {
"type": "exponential",
"delay": 1000
},
"removeOnComplete": 100,
"removeOnFail": true
}
Supported option fields match scheduled job template options plus delay: attempts, priority, backoff, removeOnComplete, and removeOnFail.
Scheduled Jobs
GET /scheduled-jobsGET /scheduled-jobs/queue/:queueNamePOST /scheduled-jobs/queue/:queueNameGET /scheduled-jobs/queue/:queueName/:schedulerIdPUT /scheduled-jobs/queue/:queueName/:schedulerIdDELETE /scheduled-jobs/queue/:queueName/:schedulerId
Workers
GET /workers
Metrics
GET /metrics
Native Queue Metrics
Route:
GET /queues/:queueName/metrics
Query parameters:
windowMinutes(optional): convenience range in minutesstart(optional): BullMQ metrics start index (0is newest point)end(optional): BullMQ metrics end index (-1means oldest available)priorities(optional): comma-separated buckets forgetCountsPerPriority(for example1,2,5,10,20,50)includePrometheus(optional):1ortrueto include nativeexportPrometheusMetrics()output
Response includes BullMQ-native telemetry only:
- raw completed/failed metrics buckets + metadata
- queue state (
isPaused,isMaxed, workers/schedulers) - native job counts by status
- queue meta fields (
concurrency,max,duration,maxLenEvents,paused,version) - native rate-limit + global limiter info
- sampled counts per priority bucket
- provider-compat warnings if some introspection calls are unavailable
Connection Metrics API
Route:
GET /metrics
Optional query parameters:
detailed:1ortrueto return full native payload per queuewindowMinutesprioritiesincludePrometheus
Redis Keys
GET /redis-keys/searchGET /redis-keys/value/:keyDELETE /redis-keys/:key
Rate Limits and Payload Constraints
- General API and auth endpoints have in-memory rate limiting in production.
- Connection test route uses stricter limits.
- Request body limit is
1MB. - Bulk job actions cap
jobIdsat100per request. - Pagination page sizes are typically capped at
100.
Error Semantics
Common status patterns:
400: validation/input mismatch401: unauthenticated403: forbidden (org scope, env connection mode restrictions)404: missing connection/resource429: rate limited500: internal error
Screenshot placeholder: API explorer or cURL snippets with representative responses.
Queue Purge API (Destructive)
Use this endpoint to remove jobs from a queue by selected statuses, or purge all statuses in one operation.
Route:
POST /api/c/:connectionId/queues/:queueName/purge
Required Safety Confirmation
This route is intentionally destructive and always requires exact queue-name confirmation:
- request body
confirmNamemust exactly equal:queueName - mismatch returns
400
Request Body
{
"confirmName": "send-welcome-email",
"statuses": ["active", "failed", "waiting"]
}
For full purge across all statuses:
{
"confirmName": "send-welcome-email",
"statuses": ["all"]
}
Allowed statuses values:
allwaitingactivedelayedcompletedfailedpausedprioritized
Operational Behavior
- The API deduplicates requested statuses.
- If
statusescontainsall, it expands to all purgeable statuses. - For each status, the API repeatedly calls BullMQ cleanup in batches of
1000until the status is empty. - A safety cap of
500batches per status is enforced to avoid unbounded loops.- If reached, route returns
409and indicates which status hit the cap.
- If reached, route returns
Success Response
{
"success": true,
"queueName": "send-welcome-email",
"statusesPurged": ["waiting", "active", "failed"],
"totalRemoved": 18,
"removedByStatus": {
"waiting": 3,
"active": 10,
"failed": 5
},
"removedJobIdsSample": ["1", "2", "3"]
}
Notes:
removedJobIdsSampleis intentionally capped (sample only), not an exhaustive list.removedByStatuscontains counts for statuses actually purged in that request.
Error Responses
400:- queue name confirmation mismatch
- empty/invalid
statusespayload
409:- purge safety cap reached for a specific status