Add JSON REST API for MCP integration
Build, Lint, and Test / Build, Lint, and Test (push) Failing after 13m0s

- Add /api/v1 namespace with Bearer token auth (PINCHFLAT_API_TOKEN env var)
- API controllers for sources, media items, media profiles, settings, tasks
- Support for all source actions: create, update, delete, force_download_pending,
  force_redownload, force_index, force_metadata_refresh, sync_files_on_disk
- Media item endpoints: list, show, search, force_download, update, delete
- Media profile CRUD endpoints
- Settings show/update and app_info endpoints
- Task listing endpoints
- Add Jason.Encoder for Task schema
- Comprehensive test suite for all API endpoints
- Gitea Actions CI workflow (runs existing checks + API-specific tests)
- API documentation in docs/API.md
This commit is contained in:
2026-07-03 23:22:24 +00:00
parent 67d8bd5598
commit 172c1ff264
19 changed files with 1122 additions and 1 deletions
+108
View File
@@ -0,0 +1,108 @@
# 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 is protected by a Bearer token. Set the `PINCHFLAT_API_TOKEN`
environment variable to a secure value:
```bash
docker run \
-e PINCHFLAT_API_TOKEN=your-secret-token \
...
```
If the token is not set, API authentication is disabled (useful for
development, but **not recommended for production**).
Clients must send the token in the `Authorization` header:
```
Authorization: Bearer your-secret-token
```
## 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:
```json
{"data": ...}
```
Error responses use:
```json
{"errors": {"field": "error message"}}
```
## Example: Create a Source
```bash
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"
}
}'
```