Skip to main content
Base URL: http://localhost:8002 (local worker — the only supported deployment today). Status: Alpha. Surface area is broad but not contractually stable across releases. Last updated: 2026-05-23.

Jump to a group

Authentication

OAuth 2.1 Client Credentials grant. poindexter setup provisions the initial CLI client.

Tasks

Create, list, approve, and reject content tasks. The lifecycle is pending → in_progress → awaiting_approval.

Posts

Public post list + search, plus authenticated update / soft-delete.

Settings

Read and update app_settings rows over the REST surface.

Overview

Reference for the REST API exposed by the Poindexter worker. All routes are under /api/* — there is no URL-based versioning.
Stability warning. The API is not yet considered stable. Route shapes change between releases, especially around task metadata. Pin to a specific commit until the first tagged release.

API Principles

  • RESTful: Standard HTTP methods and status codes
  • JSON: All requests/responses in JSON format
  • Authentication: Bearer token in Authorization header
  • Pagination: Limit/offset for list endpoints

Authentication

OAuth 2.1 Client Credentials

All protected endpoints require an OAuth-issued JWT in the Authorization header:
poindexter setup provisions an initial CLI OAuth client on first run. Mint a fresh JWT for ad-hoc curl tests with:
Or POST against the token endpoint directly:
To register additional clients (brain daemon, MCP servers, scripts, OpenClaw, Grafana), run the matching poindexter auth migrate-* helper. The legacy static-Bearer fallback was removed in Glad-Labs/poindexter#249.

Development Bypass

When development_mode is true in app_settings, the literal token dev-token is accepted as a Bearer credential:
Never enable development_mode in production. As of the 2026-04-25 rotation, development_mode=false by default — the bypass is dormant unless an operator explicitly flips the flag.

Public Endpoints (no auth required)

  • GET /api/health — system health
  • GET /api/posts — published post list
  • GET /api/posts/{slug} — single post by slug
  • GET /api/categories — category list
  • GET /api/posts/search?q=... — post search

Core Endpoints

System Health

GET /api/health

Response (200 OK):
(services/task_executor.py was deleted 2026-05-16 in the Prefect Stage 4 cutover; dispatch is now Prefect-native and there is no task_executor component in the health payload.)

Tasks

GET /api/tasks

List tasks (requires auth). Supports ?status=pending&limit=20&offset=0.

POST /api/tasks

Create a content task.
The task enters the pipeline automatically: pending → in_progress → awaiting_approval (or rejected if QA fails).

POST /api/tasks/{task_id}/approve

Approve a task for publishing. Publishes immediately unless publish_at is set.

POST /api/tasks/{task_id}/reject

Reject a task with feedback.

Posts

GET /api/posts

List published posts. Public (no auth).

GET /api/posts/{slug}

Get a single post by slug. Public.

GET /api/posts/search?q={query}

Search posts by title/content. Public.

Settings

GET /api/settings

List all app_settings (requires auth).

PUT /api/settings/{key}

Update a setting.

Other Endpoints

Everything prefixed /api is the REST surface. Media routes (/episodes/*, /images/generated/*) and the RSS feed sit at the server root without the /api prefix to match classic web expectations.

Webhook security

POST /alertmanager verifies the Alertmanager webhook signature (HMAC-SHA256, shared secret in app_settings.alertmanager_webhook_secret). Invalid signatures are rejected with 401. Preview tokens (/api/posts/preview/{token}, /preview/{token}) are single-purpose signed tokens issued by the worker at post creation. They expire after 24 hours and can only be used to read — never to modify state.

Error Responses

Common status codes: 400 validation, 401 missing/bad token, 404 not found, 500 server error.