75f75d8d19
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
104 lines
4.5 KiB
Markdown
104 lines
4.5 KiB
Markdown
# 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:
|
|
|
|
```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"
|
|
}
|
|
}'
|
|
```
|