Initial marketplace with flamenco and kitsu plugins

Bundles the flamenco-api and kitsu-api skills as Claude Code plugins
under an "adm-tools" marketplace.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-07 17:13:13 +02:00
co-authored by Claude Opus 4.7
commit 3600c870cd
10 changed files with 2812 additions and 0 deletions
+381
View File
@@ -0,0 +1,381 @@
---
name: kitsu-api
description: >
Comprehensive reference for the Kitsu production tracking API (Zou backend) and the gazu Python SDK.
Use this skill whenever working with Kitsu, gazu, CGWire, or production tracking API calls —
whether writing new integrations, debugging API issues, building pipeline tools that talk to Kitsu,
or understanding how the ADM Gadget pipeline interacts with the tracker. Also use when the user
mentions tasks, shots, assets, comments, previews, playlists, or casting in the context of
production tracking. Covers both the REST API (493 endpoints) and the gazu Python wrapper.
---
# Kitsu API & gazu SDK Reference
Kitsu is an open-source production tracking tool for animation/VFX studios, built by CGWire. The backend is called **Zou** and exposes a REST API. **gazu** is the official Python client SDK that wraps this API.
## Quick Reference
- **API docs**: https://api-docs.kitsu.cloud/
- **OpenAPI spec**: https://api-docs.kitsu.cloud/source.json
- **Developer guides**: https://dev.kitsu.cloud/
- **gazu docs**: https://gazu.cg-wire.com/
- **Zou source**: https://github.com/cgwire/zou
- **gazu source**: https://github.com/cgwire/gazu
## Authentication
### User Login (email/password → JWT)
```python
import gazu
gazu.set_host("https://kitsu.mystudio.com/api")
gazu.log_in("user@studio.com", "password")
```
Under the hood this POSTs to `/auth/login` with `{"email": "...", "password": "..."}` and receives a JWT access token + refresh token.
### Bot Authentication (pre-generated token)
Bots are non-physical users that don't count against subscription seats. Create them in Admin > Bots. Use the token directly:
```python
gazu.set_host("https://kitsu.mystudio.com/api")
gazu.set_token("bot_jwt_token_here")
```
### Token Lifecycle
- **Access token**: Short-lived JWT, passed as `Authorization: Bearer <token>` header
- **Refresh token**: Use `GET /auth/refresh-token` to get a new access token
- **Logout**: `GET /auth/logout`
- **Check auth**: `GET /auth/authenticated` (200 = valid, 401 = expired)
### 2FA Support
Kitsu supports TOTP, email OTP, FIDO/WebAuthn, and recovery codes. See `/auth/totp`, `/auth/email-otp`, `/auth/fido` endpoints.
### ADM Pipeline Authentication
In the ADM Gadget pipeline, credentials come from environment variables set by `adm_env.yml`:
- `TRACKER_URL` — Kitsu instance URL (must end with `/api`)
- `TRACKER_LOGIN` — email
- `TRACKER_PASSWORD` — password
- `TRACKER_PROJECT` — project name to connect to
The `Kitsu` adapter class (`gadget/src/gadget/resources/trackers/kitsu.py`) wraps gazu and handles connection/reconnection.
## Core Concepts
### Entity Hierarchy
```
Project
├── Episodes (optional, for TV shows)
│ └── Sequences
│ └── Shots
├── Sequences (for shorts/features)
│ └── Shots
├── Asset Types
│ └── Assets
├── Edits
├── Concepts
└── Scenes
```
### Data Model
Every entity in Kitsu is a dict with at minimum:
- `id` — UUID string
- `name` — display name
- `created_at` / `updated_at` — ISO timestamps
- `data` — custom metadata dict (called `custom_data` in Gadget after normalization)
- `project_id` — parent project UUID
### Key Relationships
- **Shot** → belongs to **Sequence** (via `parent_id`) → belongs to **Episode** (optional)
- **Asset** → belongs to **Asset Type** (via `entity_type_id`)
- **Task** → belongs to **Entity** (shot/asset) + **Task Type** + has **Task Status**
- **Comment** → belongs to **Task**, may have **Preview Files** and **Attachments**
- **Casting** → links Assets to Shots (with `nb_occurences`)
## gazu SDK Patterns
### Project Operations
```python
# List/find projects
projects = gazu.project.all_projects()
open_projects = gazu.project.all_open_projects()
project = gazu.project.get_project_by_name("My Project")
project = gazu.project.get_project(project_id)
# Create project
project = gazu.project.new_project("Name", production_type="short") # short|featurefilm|tvshow
# Team management
gazu.project.add_person_to_team(project, person)
gazu.project.remove_person_from_team(project, person)
team = gazu.project.get_team(project)
```
### Shot Operations
```python
# Episodes (TV shows only)
episode = gazu.shot.new_episode(project, "E01")
episodes = gazu.shot.all_episodes_for_project(project)
# Sequences
sequence = gazu.shot.new_sequence(project, "SQ010", episode=episode)
sequences = gazu.shot.all_sequences_for_project(project)
# Shots
shot = gazu.shot.new_shot(project, sequence, "SH0010",
nb_frames=100, frame_in=101, frame_out=200,
data={"custom_field": "value"})
shot = gazu.shot.get_shot(shot_id)
shot = gazu.shot.get_shot_by_name(sequence, "SH0010")
shots = gazu.shot.all_shots_for_sequence(sequence)
gazu.shot.update_shot(shot) # after modifying dict fields
gazu.shot.remove_shot(shot_id, force=True)
```
### Asset Operations
```python
# Asset types
asset_type = gazu.asset.new_asset_type("Character")
asset_types = gazu.asset.all_asset_types_for_project(project)
# Assets
asset = gazu.asset.new_asset(project, asset_type, "Hero",
description="Main character",
extra_data={"variant": "default"})
asset = gazu.asset.get_asset(asset_id)
asset = gazu.asset.get_asset_by_name(project, "Hero", asset_type)
assets = gazu.asset.all_assets_for_project(project)
gazu.asset.remove_asset(asset_id, force=True)
```
### Task Operations
```python
# Task types & statuses
task_type = gazu.task.get_task_type_by_name("Animation")
wip = gazu.task.get_task_status_by_short_name("wip")
done = gazu.task.get_task_status_by_short_name("done")
# Create tasks
task = gazu.task.new_task(entity, task_type, task_status=wip, assignees=[person])
# Find tasks
tasks = gazu.task.all_tasks_for_shot(shot)
tasks = gazu.task.all_tasks_for_asset(asset)
task = gazu.task.get_task_by_name(entity, task_type) # get_task_by_entity in some versions
# Assignment
gazu.task.assign_task(task, person)
# Time tracking
gazu.task.set_time_spent(task, person, "2024-03-18", duration=8*3600) # seconds
gazu.task.add_time_spent(task, person, "2024-03-18", duration=3600)
# Scheduling
task["start_date"] = "2024-03-01"
task["due_date"] = "2024-03-15"
task["estimation"] = 5 * 8 * 3600 # 5 days in seconds
gazu.task.update_task(task)
```
### Comments & Publishing
```python
# Add comment (also changes task status)
comment = gazu.task.add_comment(task, task_status,
comment="Looking good!",
person=person,
attachments=["/path/to/file.pdf"],
created_at=None)
# Add preview to comment
preview = gazu.task.add_preview(task, comment, "/path/to/render.mp4")
gazu.task.set_main_preview(preview) # set as entity thumbnail
# One-step publish shortcut
comment, preview = gazu.task.publish_preview(task, wip,
comment="WIP update",
preview_file_path="/path/to/file.mp4")
# Read comments
comments = gazu.task.all_comments_for_task(task)
last = gazu.task.get_last_comment_for_task(task)
# Download previews
gazu.files.download_preview_file(preview, "/path/to/output.mp4")
gazu.files.download_preview_file_thumbnail(preview, "/path/to/thumb.png")
```
### Casting (Breakdown)
```python
# Get casting
casting = gazu.casting.get_shot_casting(shot) # assets in a shot
cast_in = gazu.casting.get_asset_cast_in(asset) # shots using an asset
# Update casting
gazu.casting.update_shot_casting(project, shot_id, [
{"asset_id": asset1_id, "nb_occurences": 2},
{"asset_id": asset2_id, "nb_occurences": 1},
])
```
### Persons & Teams
```python
person = gazu.person.new_person("John", "Doe", "john@studio.com",
role="user", departments=[dept])
persons = gazu.person.all_persons()
person = gazu.person.get_person_by_full_name("John Doe")
gazu.person.add_person_to_department(person, department)
```
### Playlists
```python
playlist = gazu.playlist.new_playlist(project, "Daily Review",
for_client=False, for_entity="shot")
gazu.playlist.add_entity_to_playlist(playlist, entity, preview_file=preview)
```
### Event Listeners (Real-time)
```python
gazu.set_event_host("https://kitsu.mystudio.com") # note: no /api suffix
event_client = gazu.events.init()
def on_task_status_changed(data):
print(f"Task {data['task_id']} status changed")
gazu.events.add_listener(event_client, "task:status-changed", on_task_status_changed)
gazu.events.run_client(event_client) # blocks current thread
```
Event naming: `entity:action` (e.g., `asset:new`, `shot:update`, `comment:new`, `task:assign`).
Most entities emit `new`, `update`, `delete`. See `references/events.md` for the full list.
### Caching
```python
gazu.cache.enable() # enable in-memory cache for all read ops
gazu.cache.disable()
gazu.cache.clear_all()
# Per-function control
gazu.asset.all_assets.set_expire(120) # seconds
gazu.asset.all_assets.clear_cache()
gazu.asset.all_assets.disable_cache()
```
### Low-level Client
When gazu doesn't wrap an endpoint, use the raw client:
```python
# GET
data = gazu.client.get("data/projects")
data = gazu.client.fetch_all("tasks", {"project_id": pid, "task_type_id": ttid})
data = gazu.client.fetch_one("projects", project_id)
data = gazu.client.fetch_first("projects", {"name": "MyProject"})
# POST
result = gazu.client.post("data/projects", {"name": "New Project"})
# PUT
result = gazu.client.put(f"data/entities/{entity_id}", updated_data)
# Pagination
page1 = gazu.client.fetch_all("tasks?page=1") # 100 per page
```
### Search
```python
# Full-text search
results = gazu.search.search_entities("bird")
# Returns: {"persons": [...], "assets": [...], "shots": [...]}
# REST API search
results = gazu.client.post("data/search", {
"query": "hero",
"project_id": project_id,
"limit": 10,
"offset": 0,
"index_names": ["assets"] # filter to specific entity types
})
```
## Roles & Permissions
| Role | Access Level |
|------|-------------|
| **Admin** (Studio Manager) | Full read/write to all productions and settings |
| **Manager** (Production Manager) | Create assets/shots, manage tasks, post comments — no studio settings |
| **Supervisor** (Department Lead) | Read/write within assigned departments |
| **User** (Artist) | Comment/upload on assigned tasks only |
| **Vendor** | Like User but can only see assigned tasks |
| **Client** | View-only on assigned productions, client playlists only |
## Custom Actions
Custom Actions trigger HTTP POST requests from the Kitsu web UI to your endpoint. Created by admins in Admin > Custom Actions.
Payload sent to your endpoint:
```json
{
"personid": "uuid",
"personemail": "user@studio.com",
"projectid": "uuid",
"currentpath": "/productions/{id}/assets",
"currentserver": "kitsu.mystudio.com",
"selection": ["task_uuid_1", "task_uuid_2"],
"entitytype": "asset"
}
```
## ADM Gadget Integration
The Gadget pipeline's `Kitsu` adapter (`gadget/src/gadget/resources/trackers/kitsu.py`) wraps gazu with these conventions:
- **ID normalization**: `get_id()` accepts strings (UUID), dicts (extracts `["id"]`), or Gadget entity objects (uses `.id`)
- **Data normalization**: `_norm_data()` renames `data` → `custom_data` to avoid collision with Python dict usage
- **Task normalization**: `retake_count` → `nb_retakes`, `for_entity` → `for_shots` boolean
- **Comment normalization**: `attachment_files` → `attachments`, adds index-based `id` to checklist items, renames preview `original_name` → `name`
- **Shot creation**: Uses raw `gazu.client.post()` because gazu's `new_shot` didn't support all fields needed
Key Gadget patterns:
```python
# Gadget entity-level usage
project = Project.from_env() # loads from env vars
shot = project.shots.get(name="sq170_sh0224")
task = shot.tasks.fetch("Anim3D")
task.comments.new(comment="...", preview=["/path/to/img.png"], set_main_preview=True)
```
## Detailed References
For the complete endpoint catalog (all 493 endpoints), see `references/endpoints.md`.
For the full event types list, see `references/events.md`.
When you need details about a specific endpoint's parameters or response format, fetch the OpenAPI spec:
```bash
curl -s https://api-docs.kitsu.cloud/source.json | python3 -m json.tool
```
Or read it programmatically:
```python
import json, urllib.request
spec = json.loads(urllib.request.urlopen("https://api-docs.kitsu.cloud/source.json").read())
endpoint = spec["paths"]["/data/shots/{shot_id}"]
```
@@ -0,0 +1,742 @@
# Kitsu API — Complete Endpoint Catalog
**493 endpoints** across 24 categories. Base URL: `https://<your-kitsu>/api`
All endpoints require JWT authentication via `Authorization: Bearer <token>` header, except `/auth/login` and `/auth/register`.
## Table of Contents
1. [Authentication](#authentication) — Login, logout, 2FA, SAML
2. [Projects](#projects) — CRUD, settings, team, stats
3. [Shots](#shots) — Shots, sequences, episodes, scenes
4. [Assets](#assets) — Assets, asset types, instances, sharing
5. [Tasks](#tasks) — Tasks, task types, task statuses, assignments, time tracking
6. [Comments](#comments) — Comments, replies, attachments
7. [Previews](#previews) — Preview files, thumbnails, movies
8. [Files](#files) — Working files, output files, software
9. [Casting/Breakdown](#casting) — Entity casting, asset instances
10. [Persons](#persons) — Users, departments, day-offs, time spents
11. [Playlists](#playlists) — Playlists, build jobs
12. [Events](#events) — Event log, login logs
13. [News](#news) — Activity feed
14. [Notifications](#notifications) — User notifications
15. [Search](#search) — Full-text search, filters
16. [Chat](#chat) — Entity chat, messages
17. [Entities](#entities) — Generic entity operations
18. [Concepts & Edits](#concepts-edits) — Concept art, edit entities
19. [Export/Import](#export-import) — CSV, Kitsu, ShotGrid, OTIO
20. [User Context](#user-context) — Current user's data
21. [Custom Actions](#custom-actions) — Webhook-like triggers
22. [Admin](#admin) — Status, config, organisations, studios
23. [Budgets & Scheduling](#budgets-scheduling) — Budgets, milestones, schedule items
24. [Media Files](#media-files) — Pictures, movies, thumbnails
---
## Authentication
| Method | Path | Description |
|--------|------|-------------|
| POST | `/auth/login` | Login with email/password, returns JWT |
| GET | `/auth/logout` | Invalidate current token |
| GET | `/auth/authenticated` | Check if token is valid (200/401) |
| GET | `/auth/refresh-token` | Get new access token |
| POST | `/auth/register` | Register new user |
| POST | `/auth/change-password` | Change password (old_password, password, password_2) |
| POST | `/auth/reset-password` | Request password reset email |
| PUT | `/auth/reset-password` | Complete password reset (token, password) |
| PUT/POST/DELETE | `/auth/totp` | Pre-enable/enable/disable TOTP 2FA |
| GET/POST/DELETE | `/auth/email-otp` | Email OTP 2FA management |
| GET/PUT/POST/DELETE | `/auth/fido` | FIDO/WebAuthn device management |
| PUT | `/auth/recovery-codes` | Generate recovery codes |
| GET | `/auth/saml/login` | SAML SSO login redirect |
| POST | `/auth/saml/sso` | SAML SSO callback |
## Projects
| Method | Path | Description |
|--------|------|-------------|
| GET/POST | `/data/projects` | List all / create project |
| GET | `/data/projects/all` | All projects (admin) |
| GET | `/data/projects/open` | Open projects only |
| GET | `/data/projects/news` | News across all projects |
| GET/PUT/DELETE | `/data/projects/{id}` | Get/update/delete project |
| GET/POST | `/data/projects/{id}/team` | Get/add team members |
| DELETE | `/data/projects/{id}/team/{person_id}` | Remove from team |
| GET | `/data/projects/{id}/task-types` | Project task types |
| GET | `/data/projects/{id}/asset-types` | Project asset types |
| GET | `/data/projects/{id}/assets` | Project assets |
| GET | `/data/projects/{id}/comments` | All project comments |
| GET | `/data/projects/{id}/preview-files` | All project previews |
| GET | `/data/projects/{id}/attachment-files` | All project attachments |
| GET | `/data/projects/{id}/output-files` | All project output files |
| GET | `/data/projects/{id}/news` | Project news feed |
| GET | `/data/projects/{id}/news/{news_id}` | Specific news item |
| GET | `/data/projects/{id}/notifications` | Project notifications |
| GET | `/data/projects/{id}/playlists` | Project playlists |
| GET | `/data/projects/{id}/playlists/all` | All playlists including temp |
| POST | `/data/projects/{id}/playlists/temp` | Create temp playlist |
| GET | `/data/projects/{id}/subscriptions` | Project subscriptions |
| GET | `/data/projects/{id}/tasks` | All project tasks |
| GET | `/data/projects/{id}/time-spents` | Project time tracking |
| GET | `/data/projects/{id}/entity-links` | Project entity links |
| DELETE | `/data/projects/{id}/entity-links/{link_id}` | Remove entity link |
| GET | `/data/projects/{id}/build-jobs` | Build jobs for project |
| GET | `/data/projects/{id}/day-offs` | Project day offs |
### Project Settings
| Method | Path | Description |
|--------|------|-------------|
| POST | `/data/projects/{id}/settings/asset-types` | Add asset type to project |
| DELETE | `/data/projects/{id}/settings/asset-types/{at_id}` | Remove asset type |
| POST | `/data/projects/{id}/settings/task-types` | Add task type to project |
| DELETE | `/data/projects/{id}/settings/task-types/{tt_id}` | Remove task type |
| GET/POST | `/data/projects/{id}/settings/task-status` | Get/add task statuses |
| DELETE | `/data/projects/{id}/settings/task-status/{ts_id}` | Remove task status |
| GET/POST | `/data/projects/{id}/settings/status-automations` | Status automations |
| DELETE | `/data/projects/{id}/settings/status-automations/{sa_id}` | Remove automation |
| GET/POST | `/data/projects/{id}/settings/preview-background-files` | Preview BG files |
| DELETE | `/data/projects/{id}/settings/preview-background-files/{pbf_id}` | Remove BG |
| POST | `/actions/projects/{id}/set-file-tree` | Set project file tree template |
| POST | `/actions/projects/{id}/delete-tasks` | Batch delete tasks |
### Project Metadata
| Method | Path | Description |
|--------|------|-------------|
| GET/POST | `/data/projects/{id}/metadata-descriptors` | Custom metadata fields |
| POST | `/data/projects/{id}/metadata-descriptors/reorder` | Reorder descriptors |
| GET/PUT/DELETE | `/data/projects/{id}/metadata-descriptors/{desc_id}` | CRUD descriptor |
### Project Stats & Quotas
| Method | Path | Description |
|--------|------|-------------|
| GET | `/data/projects/{id}/episodes/stats` | Episode statistics |
| GET | `/data/projects/{id}/episodes/retake-stats` | Retake statistics |
| GET | `/data/projects/{id}/quotas/{task_type_id}` | Quotas by task type |
| GET | `/data/projects/{id}/quotas/persons/{person_id}` | Personal quotas |
| GET | `/data/projects/{id}/task-types/{tt_id}/time-spents` | Time by task type |
## Shots
| Method | Path | Description |
|--------|------|-------------|
| GET | `/data/shots` | All shots (filterable) |
| GET | `/data/shots/all` | All shots (admin) |
| GET | `/data/shots/with-tasks` | Shots with embedded tasks |
| GET/PUT/DELETE | `/data/shots/{id}` | Get/update/delete shot |
| GET | `/data/shots/{id}/tasks` | Shot's tasks |
| GET | `/data/shots/{id}/task-types` | Shot's task types |
| GET | `/data/shots/{id}/assets` | Assets linked to shot |
| GET | `/data/shots/{id}/asset-types` | Asset types in shot |
| GET | `/data/shots/{id}/preview-files` | Shot preview files |
| GET | `/data/shots/{id}/versions` | Shot versions |
| GET/POST | `/data/shots/{id}/asset-instances` | Shot asset instances |
| DELETE | `/data/shots/{id}/asset-instances/{ai_id}` | Remove instance |
| POST | `/data/projects/{id}/shots` | Create shot in project |
### Sequences
| Method | Path | Description |
|--------|------|-------------|
| GET | `/data/sequences` | All sequences |
| GET | `/data/sequences/with-tasks` | Sequences with tasks |
| GET/DELETE | `/data/sequences/{id}` | Get/delete sequence |
| GET | `/data/sequences/{id}/shots` | Shots in sequence |
| GET | `/data/sequences/{id}/shot-tasks` | All shot tasks in sequence |
| GET | `/data/sequences/{id}/scenes` | Scenes in sequence |
| GET | `/data/sequences/{id}/task-types` | Sequence task types |
| GET | `/data/sequences/{id}/tasks` | Sequence tasks |
| GET/POST | `/data/projects/{id}/sequences` | Project sequences |
### Episodes
| Method | Path | Description |
|--------|------|-------------|
| GET | `/data/episodes` | All episodes |
| GET | `/data/episodes/with-tasks` | Episodes with tasks |
| GET/DELETE | `/data/episodes/{id}` | Get/delete episode |
| GET | `/data/episodes/{id}/sequences` | Episode sequences |
| GET | `/data/episodes/{id}/shots` | Episode shots |
| GET | `/data/episodes/{id}/shot-tasks` | Shot tasks for episode |
| GET | `/data/episodes/{id}/asset-tasks` | Asset tasks for episode |
| GET | `/data/episodes/{id}/edit-tasks` | Edit tasks for episode |
| GET | `/data/episodes/{id}/edits` | Edits for episode |
| GET | `/data/episodes/{id}/task-types` | Episode task types |
| GET | `/data/episodes/{id}/tasks` | Episode tasks |
| GET/POST | `/data/projects/{id}/episodes` | Project episodes |
| GET | `/data/projects/{id}/episodes/casting` | All episode casting |
| GET | `/data/projects/{id}/episodes/{ep_id}/playlists` | Episode playlists |
| GET | `/data/projects/{id}/episodes/{ep_id}/sequences/all/casting` | Casting for all sequences |
| GET | `/data/projects/{id}/episodes/{ep_id}/assets/shared-used` | Shared assets in episode |
### Scenes
| Method | Path | Description |
|--------|------|-------------|
| GET | `/data/scenes/all` | All scenes |
| GET | `/data/scenes/with-tasks` | Scenes with tasks |
| GET/DELETE | `/data/scenes/{id}` | Get/delete scene |
| GET/POST | `/data/scenes/{id}/asset-instances` | Scene asset instances |
| GET | `/data/scenes/{id}/camera-instances` | Camera instances |
| GET/POST | `/data/scenes/{id}/shots` | Scene shots |
| DELETE | `/data/scenes/{id}/shots/{shot_id}` | Remove shot from scene |
| GET | `/data/scenes/{id}/task-types` | Scene task types |
| GET | `/data/scenes/{id}/tasks` | Scene tasks |
| GET/POST | `/data/projects/{id}/scenes` | Project scenes |
## Assets
| Method | Path | Description |
|--------|------|-------------|
| GET | `/data/assets` | All assets (filterable by project_id, asset_type_id) |
| GET | `/data/assets/all` | All assets (admin) |
| GET | `/data/assets/with-tasks` | Assets with embedded tasks |
| GET/DELETE | `/data/assets/{id}` | Get/delete asset (force=true to force) |
| GET | `/data/assets/{id}/tasks` | Asset's tasks |
| GET | `/data/assets/{id}/task-types` | Asset's task types |
| GET | `/data/assets/{id}/assets` | Linked assets |
| GET | `/data/assets/{id}/cast-in` | Shots this asset appears in |
| GET/PUT | `/data/assets/{id}/casting` | Get/set asset casting |
| GET | `/data/assets/{id}/shot-asset-instances` | Instances in shots |
| GET | `/data/assets/{id}/scene-asset-instances` | Instances in scenes |
| GET/POST | `/data/assets/{id}/asset-asset-instances` | Asset instances |
| GET | `/data/asset-types` | All asset types |
| GET | `/data/asset-types/{id}` | Specific asset type |
| GET | `/data/projects/{id}/asset-types` | Project asset types |
| GET | `/data/projects/{id}/asset-types/{at_id}/assets` | Assets of type |
| POST | `/data/projects/{id}/asset-types/{at_id}/assets/new` | Create asset |
| GET | `/data/projects/{id}/asset-types/{at_id}/casting` | Casting by type |
| GET | `/data/projects/{id}/assets` | Project assets |
| GET | `/data/projects/{id}/assets/shared-used` | Shared assets |
### Asset Sharing
| Method | Path | Description |
|--------|------|-------------|
| POST | `/actions/assets/share` | Share assets across projects |
| POST | `/actions/projects/{id}/assets/share` | Share project assets |
| POST | `/actions/projects/{id}/asset-types/{at_id}/assets/share` | Share by type |
## Tasks
| Method | Path | Description |
|--------|------|-------------|
| GET/POST | `/data/tasks` | List/create tasks |
| GET | `/data/tasks/open-tasks` | Open tasks |
| GET | `/data/tasks/open-tasks/stats` | Open tasks stats |
| GET/PUT/DELETE | `/data/tasks/{id}` | Get/update/delete task |
| GET | `/data/tasks/{id}/full` | Full task with all relations |
| GET | `/data/tasks/{id}/comments` | Task comments |
| GET/DELETE | `/data/tasks/{id}/comments/{cid}` | Get/delete comment |
| POST | `/data/tasks/{id}/comments/{cid}/reply` | Reply to comment |
| DELETE | `/data/tasks/{id}/comments/{cid}/reply/{rid}` | Delete reply |
| POST | `/data/tasks/{id}/comments/{cid}/ack` | Acknowledge comment |
| DELETE | `/data/tasks/{id}/comments/{cid}/attachments/{aid}` | Delete attachment |
| GET | `/data/tasks/{id}/previews` | Task preview files |
| GET | `/data/tasks/{id}/attachment-files` | Task attachments |
| GET | `/data/tasks/{id}/working-files` | Task working files |
| GET | `/data/tasks/{id}/working-files/last-revisions` | Latest working files |
| POST | `/data/tasks/{id}/working-files/new` | Create working file |
| POST | `/data/tasks/{id}/working-file-path` | Get working file path |
### Task Actions
| Method | Path | Description |
|--------|------|-------------|
| POST | `/actions/tasks/{id}/comment` | Add comment to task |
| POST | `/actions/tasks/{id}/batch-comment` | Batch comment |
| POST | `/actions/tasks/batch-comment` | Batch comment (multi-task) |
| PUT | `/actions/tasks/{id}/assign` | Assign task |
| PUT | `/actions/tasks/clear-assignation` | Clear assignments |
| PUT | `/actions/tasks/{id}/set-main-preview` | Set main preview |
| PUT | `/actions/tasks/{id}/to-review` | Send to review |
| POST | `/actions/tasks/{id}/comments/{cid}/add-preview` | Add preview to comment |
| POST | `/actions/tasks/{id}/comments/{cid}/add-attachment` | Add attachment |
| POST/DELETE | `/actions/tasks/{id}/comments/{cid}/preview-files/{pfid}` | Manage previews |
| POST | `/actions/projects/{id}/tasks/comment-many` | Comment many tasks |
### Task Creation (Bulk)
| Method | Path | Description |
|--------|------|-------------|
| POST | `/actions/projects/{id}/task-types/{tt_id}/shots/create-tasks` | Create tasks for all shots |
| POST | `/actions/projects/{id}/task-types/{tt_id}/assets/create-tasks` | Create tasks for all assets |
| POST | `/actions/projects/{id}/task-types/{tt_id}/edits/create-tasks` | Create tasks for all edits |
| POST | `/actions/projects/{id}/task-types/{tt_id}/concepts/create-tasks` | Create tasks for concepts |
| DELETE | `/actions/projects/{id}/task-types/{tt_id}/delete-tasks` | Delete all tasks of type |
### Time Tracking
| Method | Path | Description |
|--------|------|-------------|
| GET/POST | `/data/time-spents/` | List/create time spents |
| GET/PUT/DELETE | `/data/time-spents/{id}` | CRUD time spent |
| GET | `/actions/tasks/{id}/time-spents` | Task time spents |
| GET | `/actions/tasks/{id}/time-spents/{date}` | Task time on date |
| POST/DELETE | `/actions/tasks/{id}/time-spents/{date}/persons/{pid}` | Set/delete person time |
| POST | `/actions/tasks/{id}/time-spents/{date}/persons/{pid}/add` | Add time |
### Task Types & Statuses
| Method | Path | Description |
|--------|------|-------------|
| GET/POST | `/data/task-types` | List/create task types |
| GET/PUT/DELETE | `/data/task-types/{id}` | CRUD task type |
| GET/POST | `/data/task-status` | List/create task statuses |
| GET/PUT/DELETE | `/data/task-status/{id}` | CRUD task status |
| POST | `/data/task-type-links` | Link task types |
| POST | `/data/task-status-links` | Link task statuses |
| POST | `/actions/projects/{id}/task-types/{tt_id}/set-shot-nb-frames` | Set frame counts |
## Comments
| Method | Path | Description |
|--------|------|-------------|
| GET/POST | `/data/comments` | List/create comments |
| GET/PUT/DELETE | `/data/comments/{id}` | CRUD comment |
## Previews
### Preview Actions
| Method | Path | Description |
|--------|------|-------------|
| PUT | `/actions/preview-files/{id}/set-main-preview` | Set as main preview |
| PUT | `/actions/preview-files/{id}/update-annotations` | Update annotations |
| PUT | `/actions/preview-files/{id}/update-position` | Update position |
| GET | `/actions/preview-files/{id}/extract-frame` | Extract frame |
| GET | `/actions/preview-files/{id}/extract-tile` | Extract tile |
### Preview Data
| Method | Path | Description |
|--------|------|-------------|
| GET/POST | `/data/preview-files` | List/create preview files |
| GET/PUT/DELETE | `/data/preview-files/{id}` | CRUD preview file |
| GET/POST | `/data/preview-background-files` | Background files |
| GET/PUT/DELETE | `/data/preview-background-files/{id}` | CRUD background file |
## Files
| Method | Path | Description |
|--------|------|-------------|
| GET | `/data/files/{id}` | Get file info |
| GET/POST | `/data/working-files` | List/create working files |
| GET/PUT/DELETE | `/data/working-files/{id}` | CRUD working file |
| GET/POST | `/data/working-files/{id}/file` | Upload/download file |
| PUT | `/actions/working-files/{id}/comment` | Comment on working file |
| PUT | `/actions/working-files/{id}/modified` | Mark as modified |
| GET/POST | `/data/output-files` | List/create output files |
| GET/PUT/DELETE | `/data/output-files/{id}` | CRUD output file |
| GET/POST | `/data/output-types` | List/create output types |
| GET/PUT/DELETE | `/data/output-types/{id}` | CRUD output type |
| GET/POST | `/data/attachment-files` | List/create attachments |
| GET/PUT/DELETE | `/data/attachment-files/{id}` | CRUD attachment |
| GET | `/data/attachment-files/{id}/file/{filename}` | Download attachment |
| GET/POST | `/data/softwares` | List/create software entries |
| GET/PUT/DELETE | `/data/softwares/{id}` | CRUD software |
| GET/POST | `/data/file-status/` | File statuses |
| GET/PUT/DELETE | `/data/file-status/{id}` | CRUD file status |
### Entity File Operations
| Method | Path | Description |
|--------|------|-------------|
| GET | `/data/entities/{id}/working-files` | Entity working files |
| GET | `/data/entities/{id}/output-files` | Entity output files |
| GET | `/data/entities/{id}/output-files/last-revisions` | Latest output revisions |
| POST | `/data/entities/{id}/output-files/new` | Create output file |
| POST | `/data/entities/{id}/output-files/next-revision` | Next revision number |
| POST | `/data/entities/{id}/output-file-path` | Get output file path |
| GET | `/data/entities/{id}/output-types` | Entity output types |
| GET | `/data/entities/{id}/output-types/{ot_id}/output-files` | Files by output type |
| GET | `/data/entities/{id}/preview-files` | Entity preview files |
### Asset Instance File Operations
| Method | Path | Description |
|--------|------|-------------|
| GET | `/data/asset-instances/{ai_id}/output-files` | Instance output files |
| GET | `/data/asset-instances/{ai_id}/entities/{te_id}/output-files/last-revisions` | Latest revisions |
| POST | `/data/asset-instances/{ai_id}/entities/{te_id}/output-files/new` | Create output |
| POST | `/data/asset-instances/{ai_id}/entities/{te_id}/output-files/next-revision` | Next revision |
| POST | `/data/asset-instances/{ai_id}/entities/{te_id}/output-file-path` | Get path |
| GET | `/data/asset-instances/{ai_id}/entities/{te_id}/output-types` | Output types |
| GET | `/data/asset-instances/{ai_id}/entities/{te_id}/output-types/{ot_id}/output-files` | Files |
## Casting
| Method | Path | Description |
|--------|------|-------------|
| GET/PUT | `/data/projects/{id}/entities/{eid}/casting` | Entity casting |
| GET | `/data/projects/{id}/asset-types/{at_id}/casting` | Casting by asset type |
| GET | `/data/projects/{id}/sequences/all/casting` | All sequence casting |
| GET | `/data/projects/{id}/sequences/{sid}/casting` | Sequence casting |
| GET/POST | `/data/asset-instances/` | Asset instances |
| GET/PUT/DELETE | `/data/asset-instances/{id}` | CRUD asset instance |
## Persons
| Method | Path | Description |
|--------|------|-------------|
| GET/POST | `/data/persons` | List/create persons |
| GET/PUT/DELETE | `/data/persons/{id}` | CRUD person |
| GET | `/data/persons/{id}/tasks` | Person's tasks |
| GET | `/data/persons/{id}/done-tasks` | Person's completed tasks |
| GET | `/data/persons/{id}/time-spents` | All time spents |
| GET | `/data/persons/{id}/time-spents/{date}` | Time on specific date |
| GET | `/data/persons/{id}/time-spents/day/{y}/{m}/{d}` | Daily time |
| GET | `/data/persons/{id}/time-spents/week/{y}/{w}` | Weekly time |
| GET | `/data/persons/{id}/time-spents/month/{y}/{m}` | Monthly time |
| GET | `/data/persons/{id}/time-spents/month/all/{y}/{m}` | Monthly all |
| GET | `/data/persons/{id}/time-spents/year/{y}` | Yearly time |
| GET | `/data/persons/{id}/related-tasks/{tt_id}` | Related tasks |
| GET | `/data/persons/{id}/quota-shots/day/{y}/{m}/{d}` | Daily quota |
| GET | `/data/persons/{id}/quota-shots/week/{y}/{w}` | Weekly quota |
| GET | `/data/persons/{id}/quota-shots/month/{y}/{m}` | Monthly quota |
| GET/POST | `/data/persons/{id}/desktop-login-logs` | Login logs |
### Person Aggregate Tables
| Method | Path | Description |
|--------|------|-------------|
| GET | `/data/persons/time-spents/day-table/{y}/{m}` | All persons daily |
| GET | `/data/persons/time-spents/week-table/{y}` | All persons weekly |
| GET | `/data/persons/time-spents/month-table/{y}` | All persons monthly |
| GET | `/data/persons/time-spents/year-table/` | All persons yearly |
| GET | `/data/persons/task-dates` | All persons task dates |
| GET | `/data/persons/presence-logs/{month_date}` | Presence logs |
### Day Offs
| Method | Path | Description |
|--------|------|-------------|
| GET/POST | `/data/day-offs/` | List/create day offs |
| GET/PUT/DELETE | `/data/day-offs/{id}` | CRUD day off |
| GET | `/data/persons/{id}/day-offs` | Person day offs |
| GET | `/data/persons/{id}/day-offs/{date}` | Day offs on date |
| GET | `/data/persons/{id}/day-offs/week/{y}/{w}` | Weekly day offs |
| GET | `/data/persons/{id}/day-offs/month/{y}/{m}` | Monthly day offs |
| GET | `/data/persons/{id}/day-offs/year/{y}` | Yearly day offs |
| GET | `/data/persons/day-offs/{y}/{m}` | All persons day offs |
### Person Actions
| Method | Path | Description |
|--------|------|-------------|
| PUT | `/actions/persons/{id}/assign` | Assign person |
| POST | `/actions/persons/{id}/change-password` | Change password |
| DELETE | `/actions/persons/{id}/clear-avatar` | Clear avatar |
| POST | `/actions/persons/{id}/departments/add` | Add to department |
| DELETE | `/actions/persons/{id}/departments/{did}` | Remove from dept |
| DELETE | `/actions/persons/{id}/disable-two-factor-authentication` | Disable 2FA |
| GET | `/actions/persons/{id}/invite` | Send invite |
### Departments
| Method | Path | Description |
|--------|------|-------------|
| GET/POST | `/data/departments` | List/create departments |
| GET/PUT/DELETE | `/data/departments/{id}` | CRUD department |
| GET | `/data/departments/hardware-items` | All hardware items |
| GET | `/data/departments/software-licenses` | All software licenses |
| POST | `/data/departments/{id}/hardware-items` | Add hardware |
| GET/DELETE | `/data/departments/{id}/hardware-items/{hid}` | Get/remove |
| POST | `/data/departments/{id}/software-licenses` | Add license |
| GET/DELETE | `/data/departments/{id}/software-licenses/{sid}` | Get/remove |
## Playlists
| Method | Path | Description |
|--------|------|-------------|
| GET/POST | `/data/playlists/` | List/create playlists |
| GET/PUT/DELETE | `/data/playlists/{id}` | CRUD playlist |
| GET | `/data/playlists/entities/{eid}/preview-files` | Entity previews in playlists |
| GET | `/data/playlists/preview-files/running` | Running preview builds |
| GET | `/data/playlists/{id}/build/mp4` | Build MP4 |
| GET | `/data/playlists/{id}/download/zip` | Download ZIP |
| GET/DELETE | `/data/playlists/{id}/jobs/{jid}` | Build job status |
| GET | `/data/playlists/{id}/jobs/{jid}/build/mp4` | Job MP4 |
| POST | `/data/playlists/{id}/notify-clients` | Notify clients |
| POST | `/actions/playlists/{id}/add-entity` | Add entity to playlist |
## Events
| Method | Path | Description |
|--------|------|-------------|
| GET/POST | `/data/events/` | List/create events |
| GET | `/data/events/last` | Recent events (page_size, before, after, only_files) |
| GET | `/data/events/login-logs/last` | Recent login logs |
| GET/PUT/DELETE | `/data/events/{id}` | CRUD event |
## News
| Method | Path | Description |
|--------|------|-------------|
| GET/POST | `/data/news/` | List/create news |
| GET/PUT/DELETE | `/data/news/{id}` | CRUD news |
| GET | `/data/entities/{id}/news` | Entity news |
## Notifications
| Method | Path | Description |
|--------|------|-------------|
| GET/POST | `/data/notifications/` | List/create notifications |
| GET/PUT/DELETE | `/data/notifications/{id}` | CRUD notification |
## Search
| Method | Path | Description |
|--------|------|-------------|
| POST | `/data/search` | Full-text search (query, project_id, limit, offset, index_names) |
| GET/POST | `/data/search-filters/` | Saved search filters |
| GET/PUT/DELETE | `/data/search-filters/{id}` | CRUD search filter |
| GET/POST | `/data/search-filter-groups/` | Filter groups |
| GET/PUT/DELETE | `/data/search-filter-groups/{id}` | CRUD filter group |
## Chat
| Method | Path | Description |
|--------|------|-------------|
| GET/POST | `/data/chats/` | List/create chats |
| GET/PUT/DELETE | `/data/chats/{id}` | CRUD chat |
| GET/POST | `/data/chat-messages/` | List/create messages |
| GET/PUT/DELETE | `/data/chat-messages/{id}` | CRUD message |
| GET | `/data/entities/{eid}/chat` | Entity chat |
| GET/POST | `/data/entities/{eid}/chat/messages` | Entity chat messages |
| GET/DELETE | `/data/entities/{eid}/chat/messages/{mid}` | Get/delete message |
| POST/DELETE | `/actions/user/chats/{eid}/join` | Join/leave entity chat |
## Entities (Generic)
| Method | Path | Description |
|--------|------|-------------|
| GET/POST | `/data/entities` | List/create entities |
| GET/PUT/DELETE | `/data/entities/{id}` | CRUD entity |
| POST | `/data/entities/guess_from_path` | Guess entity from file path |
| GET | `/data/entities/{id}/entities-linked/with-tasks` | Linked entities with tasks |
| GET | `/data/entities/{id}/time-spents` | Entity time spents |
| GET | `/data/entities/{id}/task-types/{tt_id}/tasks` | Tasks by type |
| GET/POST | `/data/entity-links/` | Entity links |
| GET/PUT/DELETE | `/data/entity-links/{id}` | CRUD entity link |
| GET/POST | `/data/entity-types` | Entity types |
| GET/PUT/DELETE | `/data/entity-types/{id}` | CRUD entity type |
## Concepts & Edits
### Concepts
| Method | Path | Description |
|--------|------|-------------|
| GET | `/data/concepts` | All concepts |
| GET | `/data/concepts/with-tasks` | Concepts with tasks |
| GET/DELETE | `/data/concepts/{id}` | Get/delete concept |
| GET | `/data/concepts/{id}/preview-files` | Concept previews |
| GET | `/data/concepts/{id}/task-types` | Concept task types |
| GET | `/data/concepts/{id}/tasks` | Concept tasks |
| GET/POST | `/data/projects/{id}/concepts` | Project concepts |
### Edits
| Method | Path | Description |
|--------|------|-------------|
| GET | `/data/edits` | All edits |
| GET | `/data/edits/all` | All edits (admin) |
| GET | `/data/edits/with-tasks` | Edits with tasks |
| GET/DELETE | `/data/edits/{id}` | Get/delete edit |
| GET | `/data/edits/{id}/preview-files` | Edit previews |
| GET | `/data/edits/{id}/task-types` | Edit task types |
| GET | `/data/edits/{id}/tasks` | Edit tasks |
| GET | `/data/edits/{id}/versions` | Edit versions |
| GET/POST | `/data/projects/{id}/edits` | Project edits |
## Export/Import
### CSV Export
| Method | Path | Description |
|--------|------|-------------|
| GET | `/export/csv/persons.csv` | Export persons |
| GET | `/export/csv/projects.csv` | Export projects |
| GET | `/export/csv/task-types.csv` | Export task types |
| GET | `/export/csv/tasks.csv` | Export tasks |
| GET | `/export/csv/time-spents.csv` | Export time spents |
| GET | `/export/csv/projects/{id}/assets.csv` | Export assets |
| GET | `/export/csv/projects/{id}/shots.csv` | Export shots |
| GET | `/export/csv/projects/{id}/edits.csv` | Export edits |
| GET | `/export/csv/projects/{id}/casting.csv` | Export casting |
| GET | `/export/csv/playlists/{id}` | Export playlist |
### CSV Import
| Method | Path | Description |
|--------|------|-------------|
| POST | `/import/csv/persons` | Import persons |
| POST | `/import/csv/projects/{id}/assets` | Import assets |
| POST | `/import/csv/projects/{id}/shots` | Import shots |
| POST | `/import/csv/projects/{id}/edits` | Import edits |
| POST | `/import/csv/projects/{id}/casting` | Import casting |
| POST | `/import/csv/projects/{id}/task-types/{tt_id}/estimations` | Import estimations |
| POST | `/import/csv/projects/{id}/episodes/{ep_id}/task-types/{tt_id}/estimations` | Episode estimations |
### Kitsu Import
| Method | Path | Description |
|--------|------|-------------|
| POST | `/import/kitsu/projects` | Import from Kitsu |
| POST | `/import/kitsu/entities` | Import entities |
| POST | `/import/kitsu/tasks` | Import tasks |
| POST | `/import/kitsu/comments` | Import comments |
| POST | `/import/kitsu/entity-links` | Import links |
### OTIO Import
| Method | Path | Description |
|--------|------|-------------|
| POST | `/import/otio/projects/{id}` | Import OTIO |
| POST | `/import/otio/projects/{id}/episodes/{ep_id}` | Import OTIO with episode |
## User Context (Current User)
| Method | Path | Description |
|--------|------|-------------|
| GET | `/data/user/context` | Current user context |
| GET | `/data/user/tasks` | My tasks |
| GET | `/data/user/tasks-to-check` | Tasks to review |
| GET | `/data/user/done-tasks` | My completed tasks |
| GET | `/data/user/notifications` | My notifications |
| GET/PUT | `/data/user/notifications/{id}` | Get/mark notification |
| POST | `/actions/user/notifications/mark-all-as-read` | Mark all read |
| GET | `/data/user/chats` | My chats |
| GET | `/data/user/time-spents` | My time spents |
| GET | `/data/user/time-spents/{date}` | My time on date |
| GET | `/data/user/day-offs/{date}` | My day offs |
| GET/POST | `/data/user/filters` | My saved filters |
| PUT/DELETE | `/data/user/filters/{id}` | Update/delete filter |
| GET/POST | `/data/user/filter-groups` | My filter groups |
| GET/PUT/DELETE | `/data/user/filter-groups/{id}` | CRUD filter group |
| GET/POST | `/data/user/desktop-login-logs` | Desktop login logs |
| DELETE | `/actions/user/clear-avatar` | Clear my avatar |
| GET | `/data/user/projects/open` | My open projects |
| GET | `/data/user/projects/{id}/asset-types` | My project asset types |
| GET | `/data/user/projects/{id}/asset-types/{at_id}/assets` | My project assets |
| GET | `/data/user/projects/{id}/episodes` | My project episodes |
| GET | `/data/user/projects/{id}/sequences` | My project sequences |
| GET | `/data/user/projects/{id}/task-types/{tt_id}/sequence-subscriptions` | My subscriptions |
| GET | `/data/user/assets/{id}/task-types` | My asset task types |
| GET | `/data/user/assets/{id}/tasks` | My asset tasks |
| GET | `/data/user/shots/{id}/task-types` | My shot task types |
| GET | `/data/user/shots/{id}/tasks` | My shot tasks |
| GET | `/data/user/sequences/{id}/shots` | My sequence shots |
| GET | `/data/user/sequences/{id}/scenes` | My sequence scenes |
| GET | `/data/user/sequences/{id}/task-types` | My sequence task types |
| GET | `/data/user/sequences/{id}/tasks` | My sequence tasks |
| GET | `/data/user/scenes/{id}/task-types` | My scene task types |
| GET | `/data/user/scenes/{id}/tasks` | My scene tasks |
| GET | `/data/user/entities/{sid}/task-types/{tt_id}/subscribed` | Subscription status |
| GET | `/data/user/tasks/{id}/subscribed` | Task subscription status |
| GET | `/data/user/tasks/{id}/time-spents/{date}` | My task time |
| POST | `/actions/user/tasks/{id}/subscribe` | Subscribe to task |
| DELETE | `/actions/user/tasks/{id}/unsubscribe` | Unsubscribe from task |
| POST | `/actions/user/sequences/{sid}/task-types/{tt_id}/subscribe` | Subscribe to sequence |
| DELETE | `/actions/user/sequences/{sid}/task-types/{tt_id}/unsubscribe` | Unsubscribe |
## Custom Actions
| Method | Path | Description |
|--------|------|-------------|
| GET/POST | `/data/custom-actions/` | List/create custom actions |
| GET/PUT/DELETE | `/data/custom-actions/{id}` | CRUD custom action |
## Admin & System
| Method | Path | Description |
|--------|------|-------------|
| GET | `/` | API root |
| GET | `/config` | Server configuration |
| GET | `/stats` | Server statistics |
| GET | `/status` | Server status |
| GET | `/status.txt` | Status text |
| GET | `/status/influx` | InfluxDB metrics |
| GET | `/status/resources` | Resource usage |
| GET | `/status/test-event` | Test SSE event |
| GET/POST | `/data/organisations` | Organisations |
| GET/PUT/DELETE | `/data/organisations/{id}` | CRUD organisation |
| GET/POST | `/data/studios` | Studios |
| GET/PUT/DELETE | `/data/studios/{id}` | CRUD studio |
| GET/POST | `/data/project-status` | Project statuses |
| GET/PUT/DELETE | `/data/project-status/{id}` | CRUD project status |
| GET/POST | `/data/status-automations/` | Status automations |
| GET/PUT/DELETE | `/data/status-automations/{id}` | CRUD status automation |
| GET/POST | `/data/plugins` | Plugins |
| GET/PUT/DELETE | `/data/plugins/{id}` | CRUD plugin |
| GET/POST | `/data/subscriptions/` | Subscriptions |
| GET/PUT/DELETE | `/data/subscriptions/{id}` | CRUD subscription |
| GET/POST | `/data/salary-scales` | Salary scales |
| GET/PUT/DELETE | `/data/salary-scales/{id}` | CRUD salary scale |
| GET/POST | `/data/hardware-items` | Hardware items |
| GET/PUT/DELETE | `/data/hardware-items/{id}` | CRUD hardware item |
## Budgets & Scheduling
| Method | Path | Description |
|--------|------|-------------|
| GET/POST | `/data/projects/{id}/budgets` | Project budgets |
| GET | `/data/projects/{id}/budgets/time-spents` | Budget time spents |
| GET/PUT/DELETE | `/data/projects/{id}/budgets/{bid}` | CRUD budget |
| GET/POST | `/data/projects/{id}/budgets/{bid}/entries` | Budget entries |
| GET/PUT/DELETE | `/data/projects/{id}/budgets/{bid}/entries/{eid}` | CRUD entry |
| GET/POST | `/data/milestones/` | Milestones |
| GET/PUT/DELETE | `/data/milestones/{id}` | CRUD milestone |
| GET | `/data/projects/{id}/milestones` | Project milestones |
| GET/POST | `/data/schedule-items/` | Schedule items |
| GET/PUT/DELETE | `/data/schedule-items/{id}` | CRUD schedule item |
| GET | `/data/projects/{id}/schedule-items` | Project schedule items |
| GET | `/data/projects/{id}/schedule-items/task-types` | Schedule by task type |
| GET | `/data/projects/{id}/schedule-items/{tt_id}/asset-types` | By asset type |
| GET | `/data/projects/{id}/schedule-items/{tt_id}/episodes` | By episode |
| GET | `/data/projects/{id}/schedule-items/{tt_id}/sequences` | By sequence |
| GET/POST | `/data/production-schedule-versions` | Schedule versions |
| GET/PUT/DELETE | `/data/production-schedule-versions/{id}` | CRUD version |
| GET | `/data/production-schedule-versions/{id}/task-links` | Version task links |
| GET/POST | `/data/production-schedule-version-task-links` | Task links |
| GET/PUT/DELETE | `/data/production-schedule-version-task-links/{id}` | CRUD task link |
| POST | `/actions/production-schedule-versions/{id}/apply-to-production` | Apply schedule |
| POST | `/actions/production-schedule-versions/{id}/set-task-links-from-production` | Sync from prod |
| POST | `/actions/production-schedule-versions/{id}/set-task-links-from-production-schedule-version` | Sync from version |
## Media Files
### Pictures
| Method | Path | Description |
|--------|------|-------------|
| POST | `/pictures/preview-files/{id}` | Upload preview image |
| GET | `/pictures/originals/preview-files/{id}.png` | Original PNG |
| GET | `/pictures/originals/preview-files/{id}.{ext}` | Original (any ext) |
| GET | `/pictures/originals/preview-files/{id}/download` | Download original |
| GET | `/pictures/previews/preview-files/{id}.png` | Preview size |
| GET | `/pictures/thumbnails/preview-files/{id}.png` | Thumbnail |
| GET | `/pictures/thumbnails-square/preview-files/{id}.png` | Square thumbnail |
| GET | `/pictures/thumbnails/attachment-files/{id}.png` | Attachment thumbnail |
| GET/POST | `/pictures/thumbnails/persons/{id}` | Person avatar |
| GET/POST | `/pictures/thumbnails/persons/{id}.png` | Person avatar PNG |
| GET/POST | `/pictures/thumbnails/projects/{id}` | Project thumbnail |
| GET/POST | `/pictures/thumbnails/projects/{id}.png` | Project thumbnail PNG |
| GET/POST | `/pictures/thumbnails/organisations/{id}` | Org thumbnail |
| GET/POST | `/pictures/thumbnails/organisations/{id}.png` | Org thumbnail PNG |
| POST | `/pictures/preview-background-files/{id}` | Upload BG file |
| GET | `/pictures/preview-background-files/{id}.{ext}` | Get BG file |
| GET/POST | `/pictures/thumbnails/preview-background-files/{id}.png` | BG thumbnail |
### Movies
| Method | Path | Description |
|--------|------|-------------|
| GET | `/movies/originals/preview-files/{id}.mp4` | Original movie |
| GET | `/movies/originals/preview-files/{id}/download` | Download movie |
| GET | `/movies/low/preview-files/{id}.mp4` | Low-res movie |
| GET | `/movies/tiles/preview-files/{id}.png` | Movie tile strip |
@@ -0,0 +1,183 @@
# Kitsu Event Types
Events are emitted in real-time via Server-Sent Events (SSE) and stored in the event log.
## Listening to Events
```python
import gazu
gazu.set_host("https://kitsu.mystudio.com/api")
gazu.set_event_host("https://kitsu.mystudio.com") # no /api suffix
gazu.log_in("user@studio.com", "password")
event_client = gazu.events.init()
def handler(data):
print(data)
gazu.events.add_listener(event_client, "task:status-changed", handler)
gazu.events.run_client(event_client) # blocks
```
Run the listener in a separate thread since `run_client()` blocks.
## Event Naming Convention
Pattern: `entity_type:action`
Entity type is the model name lowercased with spaces replaced by hyphens.
## Callback Data
The callback `data` dict always includes:
- The entity ID (e.g., `asset_id`, `shot_id`, `task_id`)
- `project_id` when relevant
## Complete Event List
### Assets
- `asset:new` — Asset created
- `asset:update` — Asset updated
- `asset:delete` — Asset deleted
- `asset:new-link` — Asset linked to another entity
- `asset:remove-link` — Asset link removed
- `asset:casting-update` — Asset casting changed
- `asset-type:new` — Asset type created
- `asset-type:update` — Asset type updated
- `asset-type:delete` — Asset type deleted
- `asset-instance:new` — Asset instance created
- `asset-instance:update` — Asset instance updated
- `asset-instance:delete` — Asset instance deleted
### Shots / Sequences / Episodes / Scenes
- `shot:new` — Shot created
- `shot:update` — Shot updated
- `shot:delete` — Shot deleted
- `shot:casting-update` — Shot casting changed
- `sequence:new` — Sequence created
- `sequence:update` — Sequence updated
- `sequence:delete` — Sequence deleted
- `episode:new` — Episode created
- `episode:update` — Episode updated
- `episode:delete` — Episode deleted
- `scene:new` — Scene created
- `scene:update` — Scene updated
- `scene:delete` — Scene deleted
### Tasks
- `task:new` — Task created
- `task:update` — Task updated
- `task:delete` — Task deleted
- `task:assign` — Person assigned to task
- `task:unassign` — Person unassigned from task
- `task:status-changed` — Task status changed (via comment)
- `task:to-review` — Task sent for review
- `task-type:new` — Task type created
- `task-type:update` — Task type updated
- `task-type:delete` — Task type deleted
- `task-status:new` — Task status created
- `task-status:update` — Task status updated
- `task-status:delete` — Task status deleted
### Comments
- `comment:new` — Comment posted
- `comment:update` — Comment edited
- `comment:delete` — Comment removed
- `comment:reply` — Reply added to comment
- `comment:acknowledge` — Comment acknowledged
### Files
- `preview-file:new` — Preview file uploaded
- `preview-file:update` — Preview file updated
- `working-file:new` — Working file created
- `output-file:new` — Output file created
- `output-file:update` — Output file updated
- `output-file:delete` — Output file deleted
### Persons
- `person:new` — Person created
- `person:update` — Person updated
- `person:delete` — Person deleted
### Projects
- `project:new` — Project created
- `project:update` — Project updated
- `project:delete` — Project deleted
### Edits & Concepts
- `edit:new` — Edit created
- `edit:update` — Edit updated
- `edit:delete` — Edit deleted
- `concept:new` — Concept created
- `concept:update` — Concept updated
- `concept:delete` — Concept deleted
### Playlists
- `playlist:new` — Playlist created
- `playlist:update` — Playlist updated
- `playlist:delete` — Playlist deleted
### Notifications
- `notification:new` — Notification created
- `notification:update` — Notification updated
- `notification:delete` — Notification deleted
### Chat
- `chat:new` — Chat created
- `chat:update` — Chat updated
- `chat:delete` — Chat deleted
- `chat-message:new` — Message sent
- `chat-message:update` — Message edited
- `chat-message:delete` — Message deleted
### News
- `news:new` — News item created
- `news:update` — News item updated
- `news:delete` — News item deleted
### Entity Links
- `entity-link:new` — Entity link created
- `entity-link:delete` — Entity link removed
### Budget
- `budget:new` — Budget created
- `budget:update` — Budget updated
- `budget:delete` — Budget deleted
- `budget-entry:new` — Budget entry created
- `budget-entry:update` — Budget entry updated
- `budget-entry:delete` — Budget entry deleted
### Schedule
- `schedule-item:new` — Schedule item created
- `schedule-item:update` — Schedule item updated
- `schedule-item:delete` — Schedule item deleted
- `milestone:new` — Milestone created
- `milestone:update` — Milestone updated
- `milestone:delete` — Milestone deleted
### Time Tracking
- `time-spent:new` — Time entry created
- `time-spent:update` — Time entry updated
- `time-spent:delete` — Time entry deleted
### Build Jobs
- `build-job:new` — Build job created
- `build-job:update` — Build job updated
- `build-job:delete` — Build job deleted
## Reading Event History
```python
# Recent events
events = gazu.client.get("data/events/last?page_size=100")
# Filter by date
events = gazu.client.get("data/events/last?page_size=100&before=2024-02-01&after=2024-01-01")
# File events only
events = gazu.client.get("data/events/last?page_size=100&only_files=true")
# Login logs
logs = gazu.client.get("data/events/login-logs/last")
```