# Shots API — External Integration Reference Base URL: `https://review.twotalesvfx.com` All requests must include an `Authorization` header with the configured API key. --- ## Authentication ``` Authorization: Bearer ``` The `API_SECRET_KEY` is set as an environment variable on the server. Contact your system administrator for the key value. --- ## Endpoints ### 1. List Shots ``` GET /api/ext/shots?projectId={projectId} ``` Returns all shots for a project with optional filters. #### Query Parameters | Parameter | Required | Description | |-------------|----------|----------------------------------------------------------| | `projectId` | Yes | The project CUID (e.g. `cmp6l5mzq0001ua0gz07bk72f`) | | `episode` | No | Filter by episode number (e.g. `103`) | | `status` | No | Filter by shot status (see status values below) | | `shotCode` | No | Return only the shot matching this exact code | #### Shot Status Values | Value | Description | |---------------|------------------------------------| | `WAITING` | Not yet started | | `IN_PROGRESS` | Currently being worked on | | `IN_REVIEW` | Submitted for review | | `REVISIONS` | Changes requested | | `COMPLETE` | Approved and complete | #### Example Request ```http GET /api/ext/shots?projectId=cmp6l5mzq0001ua0gz07bk72f&episode=103&status=COMPLETE Authorization: Bearer your-api-key ``` #### Example Response ```json { "shots": [ { "id": "clxxxxxxxxxxxxxx", "shotCode": "UNG_103_010_010", "scene": "010", "episode": "103", "shotNumber": 10, "description": "Hero wide establishing shot", "status": "COMPLETE", "priority": "NORMAL", "frameStart": 1001, "frameEnd": 1120, "fps": 24, "dueDate": "2026-06-01T00:00:00.000Z", "createdAt": "2026-05-20T10:00:00.000Z", "updatedAt": "2026-05-28T14:30:00.000Z", "artist": { "id": "clxxxxxxxxxxxxxx", "name": "Jane Smith", "email": "jane@studio.com" }, "_count": { "versions": 3, "tasks": 2 } } ], "total": 1 } ``` --- ### 2. Get Single Shot ``` GET /api/ext/shots/{id} ``` Returns full detail for one shot including all tasks and the latest version status. #### By Database ID ```http GET /api/ext/shots/clxxxxxxxxxxxxxx Authorization: Bearer your-api-key ``` #### By Shot Code Add `byCode=1` and `projectId` to look up by the human-readable shot code instead: ```http GET /api/ext/shots/UNG_103_010_010?byCode=1&projectId=cmp6l5mzq0001ua0gz07bk72f Authorization: Bearer your-api-key ``` #### Example Response ```json { "shot": { "id": "clxxxxxxxxxxxxxx", "shotCode": "UNG_103_010_010", "scene": "010", "episode": "103", "shotNumber": 10, "description": "Hero wide establishing shot", "status": "COMPLETE", "priority": "NORMAL", "frameStart": 1001, "frameEnd": 1120, "fps": 24, "dueDate": "2026-06-01T00:00:00.000Z", "createdAt": "2026-05-20T10:00:00.000Z", "updatedAt": "2026-05-28T14:30:00.000Z", "project": { "id": "cmp6l5mzq0001ua0gz07bk72f", "name": "UNG Episode 103", "code": "UNG103", "showId": "UNG" }, "artist": { "id": "clxxxxxxxxxxxxxx", "name": "Jane Smith", "email": "jane@studio.com" }, "tasks": [ { "id": "clxxxxxxxxxxxxxx", "title": "Comp", "type": "COMP", "status": "DONE", "priority": "NORMAL", "estimatedHours": 8, "dueDate": "2026-06-01T00:00:00.000Z", "assignedArtist": { "id": "clxxxxxxxxxxxxxx", "name": "Jane Smith", "email": "jane@studio.com" }, "_count": { "versions": 3 } } ], "versions": [ { "id": "clxxxxxxxxxxxxxx", "versionNumber": 3, "approvalStatus": "APPROVED", "createdAt": "2026-05-28T14:30:00.000Z", "artist": { "id": "clxxxxxxxxxxxxxx", "name": "Jane Smith", "email": "jane@studio.com" } } ], "_count": { "versions": 3, "tasks": 2 } } } ``` --- ## Error Responses | Status | Meaning | |--------|----------------------------------------------| | `400` | Missing required parameter (e.g. projectId) | | `401` | Missing or invalid API key | | `404` | Shot not found | | `500` | Internal server error | ```json { "error": "projectId is required" } ``` --- ## Invoicing Use Cases ### Get all completed shots for billing ```http GET /api/ext/shots?projectId={id}&status=COMPLETE ``` ### Get all shots for a specific episode ```http GET /api/ext/shots?projectId={id}&episode=103 ``` ### Get frame count for a shot (for per-frame billing) From the single shot response, calculate: ``` frameCount = frameEnd - frameStart + 1 ``` ### Get estimated hours across all tasks for a shot Sum `estimatedHours` from the `tasks` array in the single shot response. --- ## Shot Code Format Shot codes follow the convention: ``` {showId}_{episode}_{scene}_{shotNumber} e.g. UNG_103_010_010 ^^^ ^^^ ^^^ ^^^ | | | shot number (padded) | | scene | episode show ID ```