Adds a Notifications tab to Settings so an operator can pick which events reach their phone, published to a single self-hosted ntfy topic. The notifier subscribes to the realtime event hub the dashboard already consumes, so every notifiable event keeps exactly one publisher. Inbound media had no event, so `media.received` is added and published from the existing durable `gotImage` gate in the chat service — one notification per conversation, never repeated when the room re-syncs. It feeds the in-app notification bell as well. - Best-effort delivery: a rejecting or unreachable ntfy server is logged and never propagated into the path that produced the event. - Events buffered before the notifier attaches are skipped, so a restart cannot replay a backlog to somebody's phone. - Settings are applied field by field onto the live config object, so a save takes effect without a restart. - The access token is environment-owned (NTFY_AUTH_TOKEN) like the other secrets: stripped before the settings record is written, never returned by the API, which reports only `hasAuthToken`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
125 lines
7.7 KiB
Markdown
125 lines
7.7 KiB
Markdown
# RedditBot API
|
|
|
|
This file is generated from `src/web/api-catalog.ts`. Run `npm run docs:api`
|
|
after changing the HTTP surface. The live OpenAPI 3.1 document is available at
|
|
`GET /api/openapi.json`, and compact agent discovery is available at
|
|
`GET /api/v1/capabilities`.
|
|
|
|
## Authentication
|
|
|
|
The dashboard token is an administrator credential. Browser users can exchange
|
|
it for an HttpOnly, SameSite=Strict session; API clients can send it as a bearer
|
|
token.
|
|
|
|
Optional least-privilege bearer credentials are configured with:
|
|
|
|
- `REDDIT_BOT_AGENT_READ_TOKEN`: GET, HEAD, SSE, and private-media reads except debug routes.
|
|
- `REDDIT_BOT_AGENT_CONTROL_TOKEN`: read access plus mutations under `/api/v1`.
|
|
|
|
Control credentials cannot send messages, import sessions, activate accounts,
|
|
or update legacy configuration endpoints. Those operations require the
|
|
administrator dashboard token.
|
|
|
|
## Agent entry points
|
|
|
|
- `GET /healthz`: unauthenticated process liveness with no private state.
|
|
- `GET /api/v1/readyz`: component readiness and authentication degradation.
|
|
- `GET /api/v1/overview`: bot, account, sync, rate-limit, and recent-error snapshot.
|
|
- `GET /api/v1/control`: current running state.
|
|
- `POST /api/v1/control/start`, `/stop`, or `POST /api/v1/control`: explicit bot control.
|
|
- `POST /api/v1/jobs`: tracked chat/media sync; poll `GET /api/v1/jobs/:id`.
|
|
- `GET /api/events/stream`: replayable typed SSE events.
|
|
|
|
## MCP server
|
|
|
|
Run the stdio MCP adapter with `npm run mcp`. It connects to
|
|
`REDDIT_BOT_API_URL` (default `http://127.0.0.1:3000`) and reads its bearer
|
|
credential from `REDDIT_BOT_AGENT_TOKEN`, then the scoped agent variables, and
|
|
finally `WEB_DASHBOARD_TOKEN`.
|
|
|
|
Read tools cover overview, readiness, accounts, activity, conversations,
|
|
errors, sync state, and performance. Control tools include `start_bot`,
|
|
`stop_bot`, `set_bot_running`, `trigger_sync`, and `get_job`. External
|
|
message tools are separately annotated as destructive/non-idempotent and need
|
|
an administrator credential.
|
|
|
|
## Operations
|
|
|
|
| Method | Path | Summary | Access | Mutates |
|
|
|---|---|---|---|---|
|
|
| `GET` | `/healthz` | Process liveness | read | no |
|
|
| `GET` | `/api/v1/overview` | Consolidated operational snapshot | read | no |
|
|
| `GET` | `/api/v1/readyz` | Component readiness | read | no |
|
|
| `GET` | `/api/v1/capabilities` | Discover API operations and safety attributes | read | no |
|
|
| `GET` | `/api/openapi.json` | OpenAPI 3.1 description | read | no |
|
|
| `GET` | `/api/v1/control` | Get bot running state | read | no |
|
|
| `POST` | `/api/v1/control` | Set bot running state | control | yes |
|
|
| `POST` | `/api/v1/control/start` | Start bot processing | control | yes |
|
|
| `POST` | `/api/v1/control/stop` | Stop bot processing | control | yes |
|
|
| `GET` | `/api/v1/jobs` | List recent asynchronous jobs | read | no |
|
|
| `GET` | `/api/v1/jobs/{id}` | Get asynchronous job state | read | no |
|
|
| `POST` | `/api/v1/jobs` | Start chat or media synchronisation | control | yes |
|
|
| `GET` | `/api/stats` | Get bot statistics | read | no |
|
|
| `GET` | `/api/analytics/candidate-funnel` | Get durable candidate funnel counts | read | no |
|
|
| `GET` | `/api/activity` | Get recent activity | read | no |
|
|
| `GET` | `/api/posts/by-author/{username}` | Get processed posts by author | read | no |
|
|
| `GET` | `/api/messages` | Get recent sent messages | read | no |
|
|
| `GET` | `/api/successful` | Get successful message examples | read | no |
|
|
| `GET` | `/api/chats` | Get active chats | read | no |
|
|
| `GET` | `/api/chats/sync` | Get chat sync state | read | no |
|
|
| `POST` | `/api/chats/sync/delta` | Trigger incremental chat sync | admin | yes |
|
|
| `POST` | `/api/chats/sync/full` | Trigger full chat sync | admin | yes |
|
|
| `POST` | `/api/chats/fetch-all` | Fetch all chats synchronously | admin | yes |
|
|
| `GET` | `/api/conversations` | List conversations | read | no |
|
|
| `GET` | `/api/conversations/{id}` | Get conversation detail | read | no |
|
|
| `POST` | `/api/conversations/{id}/suggest-reply` | Generate a reply suggestion | admin | yes |
|
|
| `POST` | `/api/conversations/{id}/suggest-media-ask` | Generate a media request suggestion | admin | yes |
|
|
| `POST` | `/api/conversations/{id}/send-reply` | Send a conversation reply | admin | yes |
|
|
| `GET` | `/api/conversations/{id}/shareable-media` | List every enabled exchange-library image not yet shared in this conversation | read | no |
|
|
| `POST` | `/api/conversations/{id}/share-media` | Send a selected exchange-library image | admin | yes |
|
|
| `POST` | `/api/conversations/start` | Start a new conversation | admin | yes |
|
|
| `POST` | `/api/conversations/{id}/read` | Advance the operator read watermark | admin | yes |
|
|
| `POST` | `/api/conversations/{id}/unread` | Return a conversation to the unread queue | admin | yes |
|
|
| `POST` | `/api/conversations/{id}/status` | Snooze, resolve or reopen a conversation | admin | yes |
|
|
| `POST` | `/api/conversations/bulk-read` | Mark many conversations read in one request | admin | yes |
|
|
| `POST` | `/api/conversations/seller-scan` | Force a seller pass over every active conversation | admin | yes |
|
|
| `GET` | `/api/media` | List received private media | read | no |
|
|
| `GET` | `/api/media/sync` | Get media sync state | read | no |
|
|
| `POST` | `/api/media/sync` | Trigger media sync | admin | yes |
|
|
| `POST` | `/api/media/sync/full` | Trigger full media sync | admin | yes |
|
|
| `GET` | `/api/media-library` | List operator-owned exchange images | read | no |
|
|
| `POST` | `/api/media-library` | Upload and classify an operator-owned exchange image | admin | yes |
|
|
| `PATCH` | `/api/media-library/{id}` | Correct tags or enable an exchange image | admin | yes |
|
|
| `DELETE` | `/api/media-library/{id}` | Delete an exchange image | admin | yes |
|
|
| `POST` | `/api/start` | Start bot processing (legacy) | admin | yes |
|
|
| `POST` | `/api/stop` | Stop bot processing (legacy) | admin | yes |
|
|
| `GET` | `/api/timers` | Get rate-limit timers | read | no |
|
|
| `GET` | `/api/analytics/by-subreddit` | Get performance by subreddit | read | no |
|
|
| `GET` | `/api/analytics/by-strategy` | Get performance by strategy | read | no |
|
|
| `GET` | `/api/analytics/funnel` | Get mature message outcome funnel | read | no |
|
|
| `GET` | `/api/analytics/trend` | Get daily performance trend | read | no |
|
|
| `GET` | `/api/analytics/ai-usage` | Get OpenRouter cost and model reliability | read | no |
|
|
| `GET` | `/api/attention` | Get operator attention items | read | no |
|
|
| `GET` | `/api/outreach` | Get active outreach candidates and funnel stages | read | no |
|
|
| `GET` | `/api/config` | Get non-secret application configuration | read | no |
|
|
| `PUT` | `/api/config` | Update application configuration | admin | yes |
|
|
| `GET` | `/api/push-notifications` | Get push notification settings | read | no |
|
|
| `PUT` | `/api/push-notifications` | Update push notification settings | admin | yes |
|
|
| `POST` | `/api/push-notifications/test` | Send a test push notification | admin | yes |
|
|
| `GET` | `/api/login/status` | Get Reddit session state | read | no |
|
|
| `POST` | `/api/login/session-import` | Import Reddit and Matrix credentials | admin | yes |
|
|
| `GET` | `/api/accounts` | List Reddit accounts | read | no |
|
|
| `POST` | `/api/accounts/{accountId}/activate` | Activate a Reddit account | admin | yes |
|
|
| `GET` | `/api/logs/stream` | Stream legacy log events | read | no |
|
|
| `GET` | `/api/events/stream` | Stream typed application events | read | no |
|
|
| `GET` | `/api/logs` | Get recent structured logs | read | no |
|
|
| `GET` | `/api/debug/cookies` | Get redacted cookie diagnostics when enabled | admin | no |
|
|
| `POST` | `/api/debug/check-responses` | Run response check when enabled | admin | yes |
|
|
|
|
## Error model
|
|
|
|
Errors use JSON with an `error` string and optional `detail`. Authentication
|
|
failures are `401`; recognized but insufficient agent credentials receive
|
|
`403`; invalid inputs receive `400`; unavailable services receive `503`.
|
|
Long-running agent jobs expose failure text in the job resource.
|