Complete API reference
Every endpoint Basehim exposes, verified against a running install. The REST API lives under /api/v1; the OAuth and MCP endpoints sit at the root of your domain, outside it.
For an introduction to what the API is for, read The API first. This page is the exhaustive list.
Conventions
- Base URL —
https://your-site.com/api/v1 - Success responses are wrapped in a data envelope:
{"data": …} - Errors follow RFC 7807 problem details:
{"type", "title", "status", "detail"} - Single items are fetched by slug; updates and deletes address them by id. This catches people out —
GET /posts/hello-worldbutDELETE /posts/12. - List endpoints accept
page,per_page,status,qandauthor_id.
Authentication
Three ways in, for three different callers:
- API key —
Authorization: Bearer basehim_…. Generated in the admin. Best for scripts and server-to-server work. - JWT —
POST /api/v1/auth/loginreturns a token; refresh it at/auth/refresh. Best for apps acting on behalf of a signed-in person. - OAuth 2.1 — used by AI agents connecting over MCP. Supports dynamic client registration, so there is no client id or secret to configure by hand.
Reading published content needs no authentication at all. Anything that writes, or reads drafts, does.
Public endpoints — no authentication
| Method | Path | Purpose |
|---|---|---|
| GET | /posts | List published posts |
| GET | /posts/{slug} | A single post |
| GET | /pages | List published pages |
| GET | /pages/{slug} | A single page |
| GET | /search?q= | Full-text search across posts and pages |
| GET | /taxonomies | List taxonomies |
| GET | /taxonomies/{taxonomy}/terms | Terms within a taxonomy |
| GET | /menus/{slug} | A menu and its items |
| GET | /widget-areas | List widget areas |
| GET | /widget-areas/{area} | One area with its widgets |
| GET | /settings/public | Publicly readable settings |
| GET | /posts/{slug}/comments | Comments on a post |
| POST | /posts/{slug}/comments | Submit a comment |
Authentication endpoints
| Method | Path | Purpose |
|---|---|---|
| POST | /auth/login | Exchange credentials for a token |
| POST | /auth/refresh | Renew an expiring token |
| POST | /auth/logout | Invalidate the current token |
| POST | /auth/register | Create an account, where registration is open |
| GET | /me | The authenticated user |
| PATCH | /me | Update your own profile |
Content
| Method | Path | Purpose |
|---|---|---|
| POST | /posts | Create a post |
| PUT / PATCH | /posts/{id} | Update a post |
| DELETE | /posts/{id} | Trash a post |
| POST | /pages | Create a page |
| PUT | /pages/{id} | Update a page |
| DELETE | /pages/{id} | Trash a page |
Media
| Method | Path | Purpose |
|---|---|---|
| GET | /media | Browse the media library |
| POST | /media | Upload a file |
| PATCH | /media/{id} | Update alt text, caption and title |
| DELETE | /media/{id} | Delete a file |
Taxonomies and terms
| Method | Path | Purpose |
|---|---|---|
| POST | /taxonomies/{taxonomy}/terms | Create a category or tag |
| PUT | /terms/{id} | Update a term |
| DELETE | /terms/{id} | Delete a term |
Comments
| Method | Path | Purpose |
|---|---|---|
| GET | /comments | All comments, newest first |
| GET | /comments/counts | Counts by status, for dashboards |
| GET | /comments/{id} | A single comment |
| PATCH | /comments/{id}/status | Approve, unapprove, spam or trash |
| DELETE | /comments/{id} | Delete a comment |
Menus
| Method | Path | Purpose |
|---|---|---|
| GET | /menus | List menus |
| POST | /menus | Create a menu |
| PUT | /menus/{id} | Update a menu |
| DELETE | /menus/{id} | Delete a menu |
| GET | /menus/{id}/items | Items in a menu |
| POST | /menus/{id}/items | Add an item |
| PUT | /menu-items/{id} | Update an item |
| DELETE | /menu-items/{id} | Remove an item |
Note the split: /menus/{slug} reads a menu publicly by slug, while these manage menus by id.
Users
| Method | Path | Purpose |
|---|---|---|
| GET | /users | List users |
| GET | /users/{id} | A single user |
| POST | /users | Create a user |
| PUT | /users/{id} | Update a user |
| DELETE | /users/{id} | Delete a user |
Settings, apps, cache and scheduling
| Method | Path | Purpose |
|---|---|---|
| GET | /settings | All settings |
| PUT | /settings | Update settings |
| GET | /apps | Installed apps |
| GET | /apps/{slug} | One app's details |
| POST | /cache/flush | Clear the cache |
| GET | /schedule | List scheduled tasks |
| POST | /schedule/{app}/{key}/run | Run one task now |
| GET | /schedule/run | Cron entry point |
App lifecycle actions — activate, deactivate, uninstall — deliberately stay in the admin area rather than the API. /schedule/run sits outside the authenticated group on purpose: a crontab sends no cookies and holds no token, so it is guarded by an unguessable token instead.
Desktop agent API
| Method | Path | Purpose |
|---|---|---|
| POST | /agents/register | First contact; mints the agent's token |
| POST | /agents/{uuid}/heartbeat | Check in and collect commands |
| POST | /agents/{uuid}/commands/{id}/ack | Acknowledge a command |
These authenticate with a per-agent bearer token validated against the {uuid} in the path, not a user session. /circuits/agents/* is an alias kept for existing desktop builds.
OAuth 2.1 — root level, not under /api/v1
| Method | Path | Purpose |
|---|---|---|
| GET | /.well-known/oauth-protected-resource | Resource metadata (RFC 9728) |
| GET | /.well-known/oauth-protected-resource/mcp | Path-suffixed variant clients derive from the MCP URL |
| GET | /.well-known/oauth-authorization-server | Server metadata (RFC 8414) |
| GET | /.well-known/openid-configuration | Same metadata, OIDC discovery path |
| POST | /oauth/register | Dynamic client registration |
| GET / POST | /oauth/authorize | Consent screen and approval |
| POST | /oauth/token | Exchange a code, or refresh |
Grants supported: authorization_code and refresh_token, with PKCE (S256).
MCP — root level
| Method | Path | Purpose |
|---|---|---|
| GET | /mcp | Discovery: transport, auth methods, metadata URL |
| POST | /mcp | JSON-RPC 2.0 endpoint |
Accepts either OAuth or a bearer API key. Add the /mcp URL as a custom connector in an AI assistant and it registers itself — there is no client id or secret to configure.
Scopes
Tokens carry scopes, and a token issued for one thing cannot do another. The current set:
posts:read · posts:write · taxonomies:read · taxonomies:write · media:read · comments:read · comments:write · settings:read · users:read
Installed apps can contribute their own scopes, so the list on your site may be longer than this one. Whatever your site advertises is authoritative — fetch /.well-known/oauth-authorization-server to see it.
A note on tokens
A token is a password. Keep it out of client-side code, out of public repositories and out of screenshots. Issue the narrowest scope that does the job, and a separate token per integration so one can be revoked without disturbing the others. If one leaks, revoke it in the admin — it stops working immediately.