Files
hermes-agent 75f75d8d19
Nix Flake Check / Nix Flake Check (push) Successful in 1m55s
Build and Test / Build and Test (push) Successful in 8m25s
Make API auth mandatory, manage tokens via web UI
BREAKING CHANGE: API authentication is now always required. The
PINCHFLAT_API_TOKEN env var is no longer used. Instead, tokens are
stored in the database and managed via Settings → API Access.

Changes:
- Add api_token column to settings table (migration)
- ApiAuthPlug reads from DB; returns 401 if no token configured
- Add API Access section to Settings page with generate/regenerate/revoke
- Add POST /settings/generate_api_token and /settings/revoke_api_token
- Remove api_token from config.exs and runtime.exs
- Update all API controller tests to set auth token in setup
- Update auth plug tests for mandatory authentication
- 1008 tests pass, zero warnings
2026-07-04 11:51:40 +00:00

4.5 KiB

Pinchflat API

This fork adds a JSON REST API to Pinchflat for programmatic access, enabling MCP server integration and other automation use cases.

API Authentication

The API always requires a Bearer token — there is no open-access mode. Generate a token from the web UI under Settings → API Access:

  1. Navigate to Settings
  2. Click "Generate API Token"
  3. Copy the token (it won't be shown in full again)

Clients must send the token in the Authorization header:

Authorization: Bearer *** to regenerate or revoke the token at any time.

API Endpoints

All endpoints are under /api/v1.

Sources

Method Path Description
GET /api/v1/sources List all sources
GET /api/v1/sources/:id Get a source with its pending tasks
POST /api/v1/sources Create a new source
PUT /api/v1/sources/:id Update a source
DELETE /api/v1/sources/:id Delete a source (marks for deletion)
POST /api/v1/sources/:source_id/force_download_pending Force download pending media
POST /api/v1/sources/:source_id/force_redownload Force re-download existing media
POST /api/v1/sources/:source_id/force_index Force re-index
POST /api/v1/sources/:source_id/force_metadata_refresh Force metadata refresh
POST /api/v1/sources/:source_id/sync_files_on_disk Sync files on disk

Media Items

Method Path Description
GET /api/v1/media List all media items (optional ?source_id=X filter)
GET /api/v1/media/search?q=query Search media items
GET /api/v1/media/:id Get a media item
PUT /api/v1/media/:id Update a media item
DELETE /api/v1/media/:id Delete media files
POST /api/v1/media/:media_item_id/force_download Force download a media item

Media Profiles

Method Path Description
GET /api/v1/media_profiles List all media profiles
GET /api/v1/media_profiles/:id Get a media profile
POST /api/v1/media_profiles Create a media profile
PUT /api/v1/media_profiles/:id Update a media profile
DELETE /api/v1/media_profiles/:id Delete a media profile

Settings

Method Path Description
GET /api/v1/settings Get settings (route_token excluded)
PUT /api/v1/settings Update settings
GET /api/v1/app_info Get app info (version, environment, etc.)

Tasks

Method Path Description
GET /api/v1/tasks List all tasks (optional ?source_id=X filter)
GET /api/v1/tasks/:id Get a task

Response Format

All responses are JSON. Successful responses use:

{"data": ...}

Error responses use:

{ "errors": { "field": "error message" } }

Example: Create a Source

curl -X POST http://localhost:8945/api/v1/sources \
  -H "Authorization: Bearer your-token" \
  -H "Content-Type: application/json" \
  -d '{
    "source": {
      "media_profile_id": 1,
      "collection_type": "channel",
      "original_url": "https://www.youtube.com/@SomeChannel"
    }
  }'