# find-scene API

API for searching and downloading movie/TV show scenes by dialog, time, or visual description.

## Base URL

```
https://api.find-scene.com
```

All endpoints are `POST` with `Content-Type: application/json`, except
`GET /api/operation/{id}`.

## Authentication

Every API request requires a `_token` field in the JSON body.

```json
{ "_token": "user-api-token", ...other fields }
```

### How to get a token

1. Go to https://find-scene.com and sign in
2. Open https://find-scene.com/settings
3. Click "Generate new token" — the token is shown once, so copy it immediately
4. Include it as `_token` in every API request body

To revoke a token, go to https://find-scene.com/settings and click "Revoke" next
to the token you want to disable.

## Response Format

All successful responses are wrapped in `{ "result": <structured object> }`.
Each endpoint returns a typed JSON object (not a plain string). Error responses
use `{ "error": "message" }` at the top level (HTTP 4xx/5xx) or
`{ "result": { "error": "message" } }` for domain-level errors within a 200
response.

### Video Source Hash

An internal find-scene ID for a video file, starting with the `video-` prefix
(e.g., `video-3b7da43b43`). Obtained from the `videoSourceHashes` field of a
completed `get_best_video_source` operation. Pass it as `videoSourceHash` to
downloads, frame extraction, and high-accuracy text source lookups. This is NOT
an IMDB ID or filename.

### Text Source Hash

An internal find-scene ID for a subtitle/text file, starting with the `text-`
prefix (e.g., `text-eb354dfaa7`). Obtained from the `textSourceHashes` field
of a completed `get_text_source` or `get_high_accuracy_text_source`
operation. Pass it as `textSourceHash` to phrase search and subtitle
retrieval. NOT a filename or IMDB ID.

### Async Operations

`get_best_video_source`, `get_text_source`, `get_high_accuracy_text_source`,
`download_by_time`, `extract_frame`, `stitch_videos`,
`stitch_videos_side_by_side` and `transcribe_by_time` return an operation ID
(not a direct result). You must poll `GET /api/operation/{id}` until status is
`completed`, then use the result fields from the response.

**Statuses:** `in_progress`, `completed`, `failed`, `cancelled`

### Time Format

All time parameters use `HH:MM:SS` format, e.g. `"00:01:30"`.

## Typical Workflows

### Workflow 1: Find and download a scene by quote

```
1. quote_to_movie        -> identify which movie contains the quote
2. get_best_video_source -> returns operation ID, poll until completed to get videoSourceHashes
3. get_text_source       -> returns operation ID, poll until completed to get textSourceHashes
4. search_phrase         -> find exact timestamp of the quote
5. download_by_time      -> schedule clip download (returns operation ID)
6. GET /api/operation/id -> poll until completed, get download URL
```

### Workflow 2: Download a scene by time

```
1. get_best_video_source -> returns operation ID, poll until completed to get videoSourceHashes
2. download_by_time      -> schedule download with start/end times
3. GET /api/operation/id -> poll until completed
```

### Workflow 3: Search by visual scene description

```
1. find_by_scene_description -> search by what happens visually
2. get_best_video_source     -> returns operation ID, poll until completed to get videoSourceHashes
3. download_by_time          -> download the scene
4. GET /api/operation/id     -> poll until completed
```

### Workflow 4: Find which episode contains a quote (TV series)

```
1. find_episode_by_phrase -> find season/episode for a phrase
2. get_best_video_source  -> returns operation ID, poll until completed to get videoSourceHashes
3. get_text_source        -> returns operation ID, poll until completed to get textSourceHashes
4. search_phrase          -> get exact timestamp
5. download_by_time       -> download clip
6. GET /api/operation/id  -> poll until completed
```

### Workflow 5: Extract a frame / screenshot

```
1. get_best_video_source -> get videoSourceHashes
2. extract_frame         -> schedule frame extraction (returns operation ID)
3. GET /api/operation/id -> poll until completed, get image URL
```

## Tips

- Always get the video source hash first before attempting downloads or text
  source lookups.
- Use `get_high_accuracy_text_source` (with a videoSourceHash) over
  `get_text_source` when you have a video source, for better subtitle timing
  alignment.
- All async tools return operation IDs.
  Never return these to the user as download links. Always poll until you get the
  actual result.
- Keep clip durations reasonable (under 60 seconds) to avoid long processing
  times.
- For TV series, use `find_episode_by_phrase` first to identify the episode
  before searching within it.
- The `find_by_scene_description` endpoint requires the video to have been
  indexed. If it returns no results, use
  `request_indexing_for_scene_description` and try again later.
- OpenAPI spec is available at `https://api.find-scene.com/api/openapi.json` for
  machine-readable schema details.

## Error Handling

- **400**: Invalid parameters (check required fields)
- **401**: Invalid or missing `_token`
- **500**: Internal server error (retry or report)

## API Endpoints Reference

The list below is a summary. For the full, machine-readable request and
response schemas (fields, types, required/optional, and validation rules),
always consult the OpenAPI spec at
`https://api.find-scene.com/api/openapi.json`. Only send fields defined
there.

### `POST /api/get_best_video_source`

Schedules a task to get the best video source for a given video. The result will be automatically delivered when complete. You will be notified when the operation finishes — do not poll or check status.

### `POST /api/compute_running_time`

Compute the running time of a video.

### `POST /api/get_high_accuracy_text_source`

Schedules a task to get a text source for given video source. The result will be automatically delivered when complete. You will be notified when the operation finishes — do not poll or check status.

### `POST /api/get_text_source`

Schedules a task to get a text source for given video details. If you have the video source use the other version, it will be more accurate with the timings. Note that this outputs a text source hash. NOT a video source hash. The result will be automatically delivered when complete. You will be notified when the operation finishes — do not poll or check status.

### `POST /api/search_phrase`

Search for a phrase within a specific subtitle text source. This is NOT a global search: you MUST pass a textSourceHash (a 'text-...' hash obtained earlier in this conversation from get_high_accuracy_text_source or get_text_source). Never call this tool before you have one.

### `POST /api/get_srt_entries_around_phrase`

Get subtitle entries (text and times) around a phrase, for a given video. Returns entries within a time window before and after the phrase.

### `POST /api/get_srt_entries_by_time_range`

Get subtitle entries (text and times) for a given video and time range.

### `POST /api/download_by_time`

Schedules a task to download a video part by time. The result will be automatically delivered to the user (UI + email) and billed when complete. You will be notified when the operation finishes — do not poll or check status.

### `POST /api/extract_frame`

Extract a single frame from a video at a specific time. Useful for creating stickers or screenshots. The result will be automatically delivered to the user when complete. You will be notified when the operation finishes — do not poll or check status.

### `POST /api/stitch_videos`

Stitch multiple previously downloaded video clips into a single video. Accepts URLs from completed download_by_time operations. The result will be automatically delivered to the user (UI + email) and billed when complete. You will be notified when the operation finishes — do not poll or check status.

### `POST /api/stitch_videos_side_by_side`

Place multiple previously downloaded video clips side by side in a single frame. All videos play simultaneously. Accepts URLs from completed download_by_time operations. The result will be automatically delivered to the user (UI + email) and billed when complete. You will be notified when the operation finishes — do not poll or check status.

### `POST /api/cancel_operation`

Cancel a stuck async operation by its ID.

### `POST /api/is_movie_name`

Check if the title is a movie name

### `POST /api/quote_to_movie`

Get movie name from quote

### `POST /api/find_episode_by_phrase`

Find a series episode by a phrase. This is not for movies, but tv shows.

### `POST /api/query_imdb`

Get movie information from IMDB, including the imdb id itself, if you only have the title.

### `POST /api/popular_quotes_from_title`

Get popular quotes from a movie or TV show title

### `POST /api/find_by_scene_description`

Search scene by non dialog description.

### `POST /api/request_indexing_for_scene_description`

Request indexing of a video. If it's a series we need to know the season and episode.

### `POST /api/check_quota`

Check how many search credits the current user has remaining. Credits work on a rolling 30-day window — each credit returns exactly 30 days after it was used. If the user is low on credits, tell them when their next credit returns.

### `POST /api/generate_stripe_checkout_link`

Generate a Stripe checkout link for the user to upgrade to Pro. Optional 'tier' parameter allows selecting between '50_credits', '150_credits', or '500_credits'.

### `POST /api/generate_stripe_portal_link`

Generate a Stripe customer portal link for the user to manage or cancel their subscription.

### `GET /api/operation/{id}`

Poll the status of an async operation (returned by download_by_time or extract_frame)
