Skip to main content

Jumper Public API v1

Base URL: http://localhost:6699/api/v1 Jumper analyzes your media files locally on your machine. This API lets external tools (MAM systems, automation scripts, custom integrations) tap into those capabilities: semantic search across video, speech transcription, face detection and clustering, and more.

Authentication

Every endpoint except /health requires a Jumper Pro license key. Pass it one of two ways: A non-empty JSON license_key takes precedence over the header. Send the raw key without quotes around the value or a Bearer prefix. The UI and API use the same Pro entitlements; no separate API entitlement is needed. Successful key validation is cached for 30 minutes. Requests with the same key within that window can skip the network check; the key is validated again after the cache expires. When an on-prem license server is configured in Jumper, this validation uses the signed machine-file forwarding flow instead of contacting Keygen directly. /auth_by_settings is an internal bootstrap endpoint and does not authenticate later /api/v1 calls by itself. Public API clients should still send X-License-Key or license_key on each /api/v1 request. Error responses:
Jumper Pro license required covers both invalid keys and valid non-Pro keys. Inspect the actual response message to distinguish them. A valid non-Pro key can return message: "OK" with HTTP 403. Enterprise policy denials use policy_error instead of error and message. Activating Jumper in the UI does not authenticate your script. A failing API request can coexist with a valid Pro session when the script sends a different key. To check access before submitting media, use the same key that works in the UI:
Preserve the HTTP status and complete response body when diagnosing a failure. /health and a successful Socket.IO connection only establish connectivity; they do not prove API authorization. The public API accepts local requests on the machine running Jumper.

Typical Workflow

Most integrations follow this pattern:
  1. Check health — verify the backend is running
  2. Analyze media — run visual and/or speech analysis on your files
  3. Orient with summaries — compare one-line overviews and drill into relevant time ranges when summaries exist
  4. Load analysis data — load analysis results into memory for searching
  5. Search — find matching moments, optionally constrained to summary-derived ranges
  6. Verify evidence — retrieve transcriptions and thumbnails before making source claims or edit decisions

Endpoints

Health

GET /health

No authentication required. Use this to check if the backend is running. Response:

Models

GET /models/loaded

Returns which visual and speech analysis models are currently loaded in memory. Example request:
Response:
model_key is the model actually loaded and may be null. requested_model_key is the model Jumper attempted to load. load_status is loading, ready, failed, or unavailable; after a successful fallback, fallback_from contains the requested model key and model_key contains the default model that was loaded instead.

GET /models/available

Lists all visual models supported on this hardware, which are downloaded, and which is active. Example request:
Response:
model_info is an array of single-key objects, where each key is a model_key from supported_models. current_system is one of mac-arm, mac-x86, windows, or linux. loaded_model may be null while loading or after a terminal load failure. The requested, status, error, and fallback fields have the same meaning as on /models/loaded.

POST /models/load

Switches to a different visual model. The model must already be downloaded. This clears loaded visual analysis data from memory — you’ll need to reload it afterwards. Example request:
Response:

Media Metadata

POST /media/metadata

Returns file properties (duration, FPS, timecode) and analysis status for each file. This is the way to check which files have been analyzed and to get their hash_str identifiers. Invalid or unreadable media files are omitted; if none can be parsed, the response is 400. An unavailable Analysis folder returns 503. Example request:
Response:
Fields explained:
  • video_cached — true if visual analysis data exists (for videos/images)
  • audio_cached — true if a transcription exists (for videos/audio)
  • hash_str — unique identifier for this file, used internally and in other endpoints

Analysis

POST /analyze

Starts analyzing media files. This is asynchronous — it returns immediately with a task_id, and the actual work runs in the background. You can combine visual analysis, transcription, face clustering, and named hierarchical summaries in one call. Summary generation requires a supported Apple silicon or Windows device and a locally downloaded Summary model. The REST endpoint is headless: it does not require MCP, an agent, or an approval step. Batching matters: one request with 50 files is much faster than 50 one-file requests on the same backend, because Jumper loads the ML models per analysis request. Only one analysis task can run at a time per backend instance. A new /analyze request first tries to stop any current task. If the previous task is still unwinding, the new request returns 409. Example request — visual + transcription + face clustering:
detect_speakers is optional and defaults to true. Set it to false to skip final speaker diarization for the speech batch. speaker_count is optional and defaults to "auto"; accepted values are "auto", 1, 2, 3, 4, and "5+". For pyannote, 1-4 becomes num_speakers, while "5+" becomes min_speakers=5, max_speakers=12. preferred_qwen_model_key is optional and applies to Qwen-supported languages; use "faster" for the 0.6B model, "more accurate" for the 1.7B model, or "auto"/omit it for Jumper’s default. detect_speakers, speaker_count, and preferred_qwen_model_key can also be supplied on individual transcription_jobs to override the batch setting. Example request — with face clustering:
Response (202):
face_clustering_jobs[].sample_faces optionally supplies named reference images for that collection. Each person needs a non-empty name and 1–3 images total across face_paths (local paths readable by Jumper) and face_images (base64 image bytes or data:image/...;base64,...). Each image must show one face. For clipboard images or browser uploads, send face_images; native local file selection can use face_paths. Remote image URLs are not accepted. Limits are 100 people per sample array, 200 characters per name, 10 MiB and 24 megapixels per image, and 50 MiB of inline image bytes across the request. Top-level sample_faces supplies defaults to every requested face collection. A job’s explicit sample_faces overrides those defaults, including [] to skip automatic naming for that job. Supplying samples without a valid face job is an input error. After clustering, confident matches receive their supplied names before Summary Analysis. Unmatched or ambiguous references do not assign names; inspect the sample_face_naming progress result for assignments and reasons. Tracking progress: Connect to the SocketIO server at http://localhost:6699, emit join with the returned task_id, then listen for progress events:
The REST task_id identifies the Socket.IO room. There is currently no durable REST job-status or resume endpoint, so unattended clients should retain the socket events and confirm generated summaries with the read endpoints below. Analysis endpoints accept explicit file paths; enumerate folders in the client before submitting a batch. Summary events use type: "summary". During processing they may include summary_stage (loading_model, preparing_evidence, generating_observations, generating_summary, or generating_short_summary) and summary_node_id. Asynchronous failures include summary_error. Clients should accept progress as either a JSON number or a decimal string because Summary events currently format it as a string. Transcription job fields: summary_requests is an optional array of per-file configurations. Visual analysis is the only required dependency: each path must already have complete visual analysis or also appear in visual_media_paths in the same request. Missing or disabled transcript and face evidence is non-fatal. Omitting collection creates a standalone analysis and is the default. Collections only organize independent per-file analyses; they do not combine clips or produce collection-level summaries. Collection names reuse existing records case-insensitively while preserving their canonical stored name and description. Summary request fields: Supported summary_objective.preset values are general_understanding, trailer_teaser, action_trailer, visual_showcase, highlight_reel, event_recap, documentary_research, unscripted_story, interview_selects, archive_discovery, season_theme_analysis, b_roll_selects, social_cutdown, character_storyline_tracking, continuity_review, and custom. Supported priority_hints are beauty_scale, action_danger_violence, conflict, reactions, humor, reveals_reversals, strong_dialogue, people_relationships, claims_evidence, themes_contradictions, rare_material, clean_coverage, processes_demos, crowd_energy, locations_atmosphere, and resolutions_open_questions. Windows Summary model keys are qwen3-vl-2b-instruct, qwen3-vl-4b-instruct, and qwen3-vl-8b-instruct. Apple silicon keys are qwen3-vl-4b-instruct-8bit, qwen3-vl-8b-instruct-8bit, and qwen3-vl-32b-instruct-8bit. Omit summary_model_key to use Jumper’s recommended model for the machine. Download the model in the Jumper UI before starting the REST job. Example request — visual + Summary Analysis:

POST /analyze/cancel

Requests cancellation of any running analysis task. Returns 200 when the task has stopped (or no task is running), or 202 with still_stopping: true while the task is still unwinding.
Response:

Hierarchical Summaries

Summaries are a bounded navigation layer over media. Start with a one-line overview, drill only promising branches, and use each node’s search_scope to constrain later searches. Summary prose is not source proof; verify exact facts, identities, quotations, and edit points with frame, transcript, or people evidence. Use these REST endpoints instead of reading summaries/<hash>/summary_v3.json directly. Cache artifacts and their directory layout are private implementation details and may change between Jumper releases. Summary reads access persisted artifacts directly and do not require /analysis-data/load.

POST /summaries/collections

Lists named collections and counts without enumerating or returning members by default. This is the inexpensive global discovery route. To expand one collection, pass its collection_id with include_members: true. The response contains every member of only that collection without a 500-member cap. Each compact registry-backed member contains only summary_ref, hash_str, media_path, media_basename, analysis_id, and analysis_name; fetch the selected analysis through /summaries/overview.

POST /summaries/list

Lists named analyses and one-line summaries for selected media_paths or hash_strs. This is not global discovery: omitting both selectors returns an empty summaries array.

POST /summaries/overview

Pass cache_dir and either summary_ref or one of path/hash_str with an optional analysis_id. Prefer the summary_ref returned during discovery because it uniquely identifies the media and named analysis. The response contains the same summary_ref, analysis metadata, short_summary, the full selected root text, and truncated previews of its immediate children.

POST /summaries/node

Pass the same selector plus node_id, keeping the summary_ref from the overview attached to every request because node IDs are local to one analysis. The response contains the same summary_ref, that node, and its immediate children. Set include_evidence: true on a leaf to receive a top-level evidence object containing compact sampled-frame references, transcript excerpts, speaker names, named people, and attribution hints. Image bytes and embeddings are never returned. Nodes may include bounded verification_hints. Each hint identifies an evidence limitation, affected range, supporting evidence IDs, and a suggested follow-up such as checking people/transcript context or reading a bounded transcript range. These are actionable source checks, not claims that the summary is wrong. Overview and node responses also include quality for the selected analysis as a whole, even when reading a subtree. Unreadable sampled images appear in warnings; intervals with no readable images appear in uncovered_ranges (start_seconds, end_seconds) and an explicit coverage warning. Other readable images and intervals are still summarized. Use this field to disclose missing evidence instead of relying on the generated summary text to mention it. The lists failed_node_ids, uncovered_ranges, and warnings contain at most eight entries each; warning strings are limited to 500 characters. Their full counts are failed_node_count, uncovered_range_count, and warning_count. The corresponding flags are failed_nodes_truncated, uncovered_ranges_truncated, and warnings_truncated. Every node includes a half-open 1 FPS search range:
Pass this object unchanged as segments_to_frame_indices to a visual search to search only the first five minutes.

Analysis Data Management

Before you can search, the analysis data needs to be loaded into memory. There are two approaches:

POST /analysis-data/load

Loads analysis data from the folder into memory — visual embeddings for the active visual model, people metadata, and transcriptions. Requires a loaded visual model (503 if none is loaded). A visual-model or Analysis-folder change while loading returns 409. Use /analysis-data/load-transcriptions for transcript-only workflows.
Response:

POST /analysis-data/load-for-media

Loads missing visual analysis data for specific video/image files. If no visual analysis context is loaded, Jumper first loads the folder’s unified visual data, which may include other media. It then supplements that data with missing requested files and skips files already in memory. An existing context must match the requested Analysis folder and active visual model; a mismatch or a context change while loading returns 409. A missing visual model or unreadable Analysis folder returns 503. This endpoint does not load transcriptions. Use /analysis-data/load to load everything, or /analysis-data/load-transcriptions for transcript-only workflows.
Response:

POST /analysis-data/load-transcriptions

Loads transcription data into memory separately. This is useful if you only need transcript search and don’t want to load visual analysis data. Transcriptions are also loaded automatically by /analysis-data/load.
Response:

Metadata Filters

POST /metadata/facets

Returns curated metadata filter facets and coverage for a searchable scope. Call this when you need to render metadata filter options, then pass selected filters to search as metadata_filter_request. For search_all: true or scope.mode: "global", the response is scoped to the backend’s loaded searchable media for the requested media_type (visual, speech, or any), not every row in the local metadata database. Example request:
Path-scoped request with known hashes:
media_paths and hash_strs are index-aligned. For path scopes, supply hashes returned by /media/metadata; this endpoint does not hash source files automatically. Paths without supplied hashes count as missing coverage and produce no facet options. If you omit scope, Jumper derives it from search_all, media_type, media_paths, hash_strs, and expected_count. Response:
Facet IDs and option values are intentionally stable API values. Option labels are for display. The facet list is curated; low-value raw fields such as exact duration seconds, exact frame counts, codec levels, and noisy object-like timecode values are omitted. Using selected filters in search:
Supported operators are is_any_of, is_not, include_any_of, include_all_of, exclude_any_of, exclude_all_of, before, after, greater_than, and less_than.
All search endpoints require analysis data to be loaded into memory first (see above). Visual search returns HTTP 400 while Summary Analysis is running. The visual search endpoints (/search/text, /search/image, /search/frame) return the same match structure and order results best-first. Jumper does not return similarity scores in the response payload. The optional exclude field is a soft ranking signal, not a hard filter. metadata_filter_request applies hard metadata filters from /metadata/facets. segments_to_frame_indices applies one or more half-open per-media ranges on the 1 FPS analysis grid and intersects with people and metadata filters.

POST /search/text

Semantic visual search — describe what you’re looking for in plain language. Example request:
Response:
frame_idx is the frame number on the 1-FPS embedding grid, returned as a string. Results are returned in rank order. If some analysis or frames could not be read, the response includes a toast_warning alongside the available matches. Parameters: Filtering by people: If you’ve run face clustering, you can restrict results to frames containing specific people:

POST /search/image

Find moments visually similar to a reference image. Optionally combine with a text query. Example request:
Parameters:

POST /search/frame

Find moments similar to a specific frame in a video — a “find more like this” search. Example request:
Parameters:

POST /search/transcript

Search through loaded transcriptions for segments containing a query string. Uses case-insensitive substring matching. To search only within one named transcript speaker, pass speaker or speaker_name. Example request:
Response:
Speaker filtering uses transcript speaker display names stored in transcription metadata. It is separate from face-clustering people names and does not use people_filter. Matches may also include media_type (audio or video) when Jumper can determine it. Parameters:

Transcriptions

POST /transcriptions

Returns speech transcriptions for media files that have been transcribed via /analyze. Example request:
Response:
Each segment is an array: [start_seconds, text, end_seconds, media_path]. The response also includes transcription_data, a mapping keyed by media path for files with speaker metadata. Each entry contains segments in the same legacy array shape, hash_str, and speakers, a mapping of transcript-local IDs such as SPEAKER_00 to metadata containing zero-based segment_indices and an optional display name. Files without speaker metadata are omitted from transcription_data; the mapping is empty when no requested file has it. If the Analysis folder cannot be read, this endpoint returns HTTP 503. Files without available transcriptions are omitted from both mappings.

POST /transcriptions/range

Returns only transcript segments overlapping one half-open source time range. Prefer hash_str so Jumper can read the cached transcript without touching the source media file.
If truncated is true, repeat the same request with after_segment_index set to next_after_segment_index. max_segments defaults to 120 and must be an integer from 1 to 500; values outside that range return HTTP 400. Responses also use a fixed 24,000-character text budget. If one pathological source segment alone exceeds that budget, its text is truncated in place with an explicit marker; the segment reports text_truncated: true and original_character_count, while the response lists its index in truncated_segment_indices. Missing or empty transcripts return an empty segments array with transcript_status set to not_available or empty.

Thumbnails

POST /thumbnails

Get base64-encoded JPEG thumbnail images for specific media/timestamp pairs. Example request:
Response:
Each thumbnail is a base64-encoded JPEG string, or null for audio files or when no frame could be retrieved.

POST /thumbnails/scene

Get a strip of thumbnails spanning a time range. Useful for timeline scrubbers. Example request:
Response:
Each entry is [base64_jpeg, timestamp]. For ranges longer than 100 seconds, Jumper samples 100 evenly-spaced frames instead of one per second. Shorter ranges include both integer-second endpoints. Audio files and still images return {"scene_thumbnails": null}.

Face Clustering

Jumper detects faces across video frames and automatically groups them by identity. These endpoints let you inspect, name, and refine those groups.

GET /faces/clusters

Lists all clustering jobs and their statistics. Example request:
Response:
face_storage_version reports the on-disk face storage format for the job. Newer jobs use the packed format; older legacy jobs may not be mutable for reclustering or merges.

POST /faces/clusters/samples

Get sample face thumbnail images for each cluster. Useful for building a “who is this?” UI. Example request:
Response:
Parameters: With include_noise: true, the response also includes noise_size and noise_sample (base64-encoded JPEGs). If the collection has no saved face data, HTTP 200 returns {"warning": "No face data available for this collection"}.

POST /faces/clusters/faces

Get paginated face images for specific cluster(s). For browsing all faces in a cluster. Supply cluster_id or a non-empty cluster_ids array. Pagination applies separately to each selected cluster. Example request:
Parameters: Response:
faces contains base64-encoded JPEG images, not face entry IDs. size counts face detections; available_faces counts images available for pagination. If no saved cluster data is available, the response contains an empty clusters array and a warning.

PUT /faces/clusters/names

Assign human-readable names to clusters. Use an empty string or null as the name to clear an assignment. Example request:
Response:

POST /faces/recluster

Re-runs face clustering with different parameters. Useful for tuning how aggressively faces are grouped. Runs asynchronously. Returns HTTP 409 if another analysis task is running or the face collection uses read-only legacy storage. Legacy collections support reading and naming groups, but cannot be reclustered or modified with merges and moves. Example request:
Response (202):
Parameters:

POST /faces/clusters/modify

Merge clusters or move individual faces between clusters. Useful for correcting mistakes. Legacy face collections return HTTP 409. Example — merge two clusters:
A merge needs at least two existing cluster_ids. target_cluster_id is optional and must be one of those IDs. If omitted, Jumper prefers a named cluster, then the largest cluster. Each move has from_cluster_id, to_cluster_id, and entry_ids (face entry UUIDs). Both clusters must already exist. The face-image pagination endpoint does not return these entry IDs. Response:
Applied moves return {"from": "source-cluster-id", "to": "target-cluster-id", "moved": 3}.

Watch Folders

Watch folders let Jumper automatically analyze new media files as they appear in a directory.

GET /watch-folders

Lists all configured watch folders and the background service status.
Response:

POST /watch-folders

Add a new watch folder. The folder and any explicit cache_dir must exist on disk. Creating an enabled folder saves its configuration. If the watch-folder service is stopped, call /watch-folders/service/start to begin monitoring.
Response (201):
Parameters: metadata_filter_request.filters uses the same facet_id, operator, and values fields as search metadata filters. The scope is the watched folder’s candidate files; a supplied scope field is ignored. Set filters to [] or send null to clear these filters. excluded_filename_globs apply to the basename only, not the relative or absolute path. excluded_folder_globs entries without a path separator match any folder name; for example, finished skips files inside any folder named finished or Finished. Entries with / or \ match relative folder paths under the watched folder; for example, client_a/finished_* skips matching folders under client_a only. Backslashes are normalized to /. Path patterns match segment by segment, so */folder2/finished matches one parent folder above folder2, while folder2/finished matches only from the watch-folder root.

PUT /watch-folders/{id}

Update settings for an existing watch folder. Only include the fields you want to change. The settings above are supported except folder_path, which cannot be changed. Set cache_dir to null to restore the app’s default Analysis folder. Invalid analysis settings, exclusions, or a nonexistent/disallowed Analysis folder return HTTP 400. A missing watch-folder ID returns HTTP 404.

DELETE /watch-folders/{id}

Remove a watch folder. Does not delete any analysis data.

POST /watch-folders/service/start

Start the background service that monitors watch folders. This uses the enabled watch-folder configuration already stored in settings; it does not require prior UI interaction in the current session.

POST /watch-folders/service/stop

Request a stop of the background service. The request returns immediately and state may be "stopping" while current work finishes. Poll /watch-folders/service/status until state is "stopped".

GET /watch-folders/service/status

Check if the service is running.
Response:

Cache Paths

POST /cache-paths

Get the visual and audio cache folder paths for a specific media file. Useful for inspecting or managing analysis data on disk.
Response:
Paths are null if the corresponding cache folder does not exist.

Export

POST /export/clips

Export trimmed video clips to a folder using ffmpeg. Example request:
Response:
Parameters: The endpoint returns HTTP 200 with a result for every clip, including individual export failures. Check each result’s success and error, as well as the summary.

POST /export/premiere-xml

Generate a Premiere Pro compatible XML sequence file (XMEML v4). Import it into Premiere Pro or another NLE that supports XMEML. Example request:
Response:
Parameters: total_duration_seconds is the exported sequence’s maximum end time after frame rounding, including gaps and overlapping tracks. Use track: "audio" for audio-only source files and track: "video" to place video without its audio.

POST /export/transcript

Export transcript segments to a file (TXT, CSV, DOCX, or PDF). Example request:
Response:
Parameters: When exporting rows returned by /transcriptions, remove their fourth media_path field or replace it with a speaker display label. Otherwise the exporter treats the media path as the speaker label. row_count counts the submitted segments and excludes inserted silence rows.

Error Format

Endpoint errors generally include an error field:
Authentication failures also include message with validation details. Enterprise policy denials return {"policy_error": "Reason the request was denied"}. Common status codes:

SocketIO Progress Tracking

For long-running operations (/analyze, /faces/recluster), connect to the SocketIO server at http://localhost:6699 and join the room matching the returned task_id. In Socket.IO terms, emit join with the returned task_id, then listen for progress. Event: progress
Common fields:
  • progress — numeric percentage
  • video_path — the file currently being processed, or null for some clustering updates
  • done — true when the task is complete
  • type — "video" for visual analysis, "speech" for transcription
  • is_cluster_job — present for face-clustering progress
  • cluster_job_name — present for face-clustering progress
  • cluster_media_hashes — present on some clustering completion events
Last modified on October 11, 2026