API Documentation

Integrate ShotMatch color grading into your applications.

Base URL: https://shotmatch.io/api/v1

Authentication

All authenticated endpoints require an API key passed via the X-API-Key header.

curl -X POST https://shotmatch.io/api/v1/match \ -H "Content-Type: application/json" \ -H "X-API-Key: shotmatch_your_api_key_here" \ -d '{"reference": "...", "target": "..."}'

Create API keys from your Account.

Rate limit: 60 requests/minute per API key.

Sandbox Mode

Optionally add the X-Sandbox: true header to any request to enable sandbox mode. The header is entirely optional — omit it for normal operation. Use your regular API key — there are no separate test or live keys.

curl -X POST https://shotmatch.io/api/v1/match \ -H "Content-Type: application/json" \ -H "X-API-Key: shotmatch_your_api_key_here" \ -H "X-Sandbox: true" \ -d '{"reference": "...", "target": "..."}'

What changes in sandbox mode:

  • No credits deducted — usage is logged but credits are not consumed
  • No GPU/AI processing — Modal, R2, and OpenAI calls are skipped entirely
  • Static demo results — responses contain demo images/videos instead of real output
  • Instant responses — all endpoints return in <50ms
  • All responses include "sandbox": true
One key, two modes. Unlike APIs that issue separate test and live keys, ShotMatch uses a single API key for both. The X-Sandbox header controls the behavior. Validation, authentication, and plan checks still run normally so you can verify your integration end-to-end.

Credits

Each API call may consume credits. Remaining credits are returned in the response.

Endpoint Cost Plan
POST /api/v1/match 1 credit All
POST /api/v1/match/batch 1 credit All
POST /api/v1/match/multi 1 credit All
GET /api/v1/match/multi/modes Free All
POST /api/v1/analyze 1 credit All
GET /api/v1/options Free All
GET /api/v1/presets Free All
POST /api/v1/presets/<preset_name>/apply 1 credit All
GET /api/v1/presets/custom Free All
POST /api/v1/presets/custom Free All
DELETE /api/v1/presets/custom/<preset_id> Free All
GET /api/v1/presets/custom/<preset_id> Free All
PUT /api/v1/presets/custom/<preset_id> Free All
POST /api/v1/presets/custom/from-image Free All
POST /api/v1/presets/preview 1 credit All
POST /api/v1/film-effects/apply 1 credit All
GET /api/v1/film-effects/presets Free All
GET /api/v1/looks Free All
POST /api/v1/looks/<look_name>/apply 1 credit All
POST /api/v1/lut/apply 1 credit All
POST /api/v1/lut/export/before-after 2 credits pro+
POST /api/v1/lut/export/match 2 credits pro+
POST /api/v1/lut/export/preset/<preset_name> 2 credits pro+
GET /api/v1/lut/sizes Free All
POST /api/v1/ai/refine 2 credits All
POST /api/v1/ai/suggest 2 credits All
POST /api/v1/grade 2 credits All
POST /api/v1/white-balance/apply 1 credit All
POST /api/v1/style-transfer/apply 5 credits All
POST /api/v1/video/grade 1 credit pro+
POST /api/v1/video/test 1 credit pro+
GET /api/v1/references Free All
POST /api/v1/references Free All
DELETE /api/v1/references/<ref_id> Free All
PATCH /api/v1/references/<ref_id> Free All
GET /api/v1/references/<ref_id>/image Free All
POST /api/v1/references/batch-delete Free All
GET /api/v1/references/categories Free All
POST /api/v1/references/categories Free All
DELETE /api/v1/references/categories/<cat_id> Free All
PATCH /api/v1/references/categories/<cat_id> Free All
POST /api/v1/references/categories/reorder Free All
POST /api/v1/references/clip Free All
POST /api/v1/references/frame Free All
POST /api/v1/references/reorder Free All
DELETE /api/v1/history Free All
GET /api/v1/history Free All
DELETE /api/v1/history/<entry_id> Free All
GET /api/v1/history/<entry_id>/image Free All
GET /api/v1/history/<entry_id>/lut Free All
GET /api/v1/history/<entry_id>/video Free All
POST /api/v1/history/batch-delete Free All
GET /api/v1/history/filmstrip Free All
GET /api/v1/preferences Free All
PATCH /api/v1/preferences Free All
DELETE /api/v1/storage/<path:key> Free All
POST /api/v1/storage/presign Free All
POST /api/v1/storage/upload Free All
POST /api/v1/storage/upload/video Free All
POST /api/v1/storage/url Free All
GET /api/v1/queue/stats Free All
GET /api/v1/tasks/<task_id> Free All
GET /api/v1/account Free All
GET /api/v1/account/usage Free All
GET /api/v1/health Free All
POST /api/v1/bg-remove/apply 2 credits All
GET /api/v1/plugin/devices Free All
DELETE /api/v1/plugin/devices/<device_id> Free All
GET /api/v1/plugin/lut.cube Free All
GET /api/v1/plugin/presets.json Free All
POST /api/v1/plugin/session Free All
GET /api/v1/plugin/version Free All
GET /api/v1/plugin/whoami Free All
GET /api/v1/stacks Free All
POST /api/v1/stacks Free All
DELETE /api/v1/stacks/<stack_id> Free All
GET /api/v1/stacks/<stack_id> Free All
PUT /api/v1/stacks/<stack_id> Free All
POST /api/v1/stacks/apply 2 credits All
POST /api/v1/stacks/apply-video 1 credit pro+
POST /api/v1/stacks/apply-video/test 1 credit pro+

Error Responses

All errors follow a consistent format:

{ "success": false, "error": "Error message", "details": [] }
Status Description
400Validation error (check details)
401Missing or invalid API key
402Insufficient credits
403Plan upgrade required
404Resource not found
429Rate limit exceeded

Color Matching

POST /api/v1/match #
1 credit

Single image color matching

Request Body

reference string Base64 or URL of reference image (deprecated — prefer reference_key)
reference_key string R2 key from /storage/presign
target string Base64 or URL of target image (deprecated — prefer target_key)
target_key string R2 key from /storage/presign
method "natural" | "direct" | "smooth" | "balanced" Default: natural
params MatchParams

Example Request

{ "method": "natural", "params": { "intensity": 0.7, "preserve_blacks": true, "preserve_highlights": true, "saturation_clamp": 1.2 }, "reference": "data:image/jpeg;base64,/9j/4AAQ...", "target": "data:image/jpeg;base64,/9j/4AAQ..." }

Example Response

{ "poll_url": "/api/v1/tasks/img_a1b2c3d4e5f6", "success": true, "task_id": "img_a1b2c3d4e5f6" }
POST /api/v1/match/batch #
1 credit

Batch image color matching

Request Body

reference string Base64 or URL of reference image (deprecated — prefer reference_key)
reference_key string R2 key from /storage/presign
targets array Base64 target images (deprecated — prefer target_keys)
target_keys array R2 keys from /storage/presign
method "natural" | "direct" | "smooth" | "balanced" Default: natural
params MatchParams

Example Request

{ "method": "natural", "params": { "intensity": 0.7, "preserve_blacks": true, "preserve_highlights": true, "saturation_clamp": 1.2 }, "reference": "data:image/jpeg;base64,/9j/4AAQ...", "targets": [ "data:image/jpeg;base64,/9j/4AAQ...", "data:image/jpeg;base64,/9j/4AAQ..." ] }

Example Response

{ "poll_url": "/api/v1/tasks/img_a1b2c3d4e5f6", "success": true, "task_id": "img_a1b2c3d4e5f6" }
POST /api/v1/match/multi #
1 credit

Multi-reference color matching

Request Body

references array 2-4 base64 or URL reference images (deprecated — prefer reference_keys)
reference_keys array 2-4 R2 keys from /storage/presign
target string Base64 or URL of target image (deprecated — prefer target_key)
target_key string R2 key from /storage/presign
weights array Per-reference weights (must match references length)
method "natural" | "direct" | "smooth" | "balanced" Default: natural
blend_mode "uniform" | "weighted" | "gradient" Default: uniform
transition_width number Default: 0.2
intensity number Default: 0.5
params MatchParams

Example Request

{ "blend_mode": "uniform", "intensity": 0.5, "method": "natural", "references": [ "data:image/jpeg;base64,/9j/4AAQ...", "data:image/jpeg;base64,/9j/4AAQ..." ], "target": "data:image/jpeg;base64,/9j/4AAQ..." }

Example Response

{ "poll_url": "/api/v1/tasks/img_a1b2c3d4e5f6", "success": true, "task_id": "img_a1b2c3d4e5f6" }
GET /api/v1/match/multi/modes #
Free No auth

List multi-reference blend modes

Example Response

{ "blend_modes": [ { "description": "Equal weight for all references", "name": "uniform" }, { "description": "Custom per-reference weights", "name": "weighted" }, { "description": "Spatial gradient blend", "name": "gradient" } ], "success": true }

Analysis

POST /api/v1/analyze #
1 credit

Analyze image color statistics

Request Body

image string Base64 or URL of image (deprecated — prefer image_key)
image_key string R2 key from /storage/presign

Example Request

{ "image": "data:image/jpeg;base64,/9j/4AAQ..." }

Example Response

{ "poll_url": "/api/v1/tasks/img_a1b2c3d4e5f6", "success": true, "task_id": "img_a1b2c3d4e5f6" }

Presets

GET /api/v1/options #
Free No auth

List all presets and film effects

Example Response

{ "film_effects": [ { "label": "35mm Film", "name": "35mm" } ], "looks": [ { "label": "Blade Runner", "name": "blade_runner" } ], "presets": [ { "label": "Cinematic Warm", "name": "cinematic_warm" } ], "success": true }
GET /api/v1/presets #
Free No auth

List available color grading presets

Example Response

{ "presets": { "cinematic": [ { "category": "cinematic", "label": "Cinematic Warm", "name": "cinematic_warm" }, { "category": "cinematic", "label": "Cinematic Cool", "name": "cinematic_cool" } ] }, "success": true }
POST /api/v1/presets/<preset_name>/apply #
1 credit

Apply a color grading preset to an image

Request Body

image string Base64-encoded image (deprecated — prefer image_key)
image_key string R2 key from /storage/presign
intensity number Default: 1.0

Example Request

{ "image": "data:image/jpeg;base64,/9j/4AAQ...", "intensity": 0.8 }

Example Response

{ "poll_url": "/api/v1/tasks/img_a1b2c3d4e5f6", "success": true, "task_id": "img_a1b2c3d4e5f6" }
GET /api/v1/presets/custom #
Free

List custom presets

Example Response

{ "presets": [ { "created_at": "2026-02-24T12:00:00Z", "description": "Warm tones with slight fade", "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "My Warm Look", "params": { "a_scale": 0.95, "a_shift": -2.0, "b_scale": 1.05, "b_shift": 3.0, "fade": 0.05, "highlight_tint_a": -0.5, "highlight_tint_b": 0.5, "l_contrast": 1.1, "l_shift": 5.0, "saturation": 1.1, "shadow_tint_a": 1.0, "shadow_tint_b": -1.0 }, "source_type": "scratch" } ], "success": true }
POST /api/v1/presets/custom #
Free

Create a custom preset

Request Body

name string required
description string
params PresetParams required
source_type "scratch" | "fork" | "reference" | "history" Default: scratch
base_preset string

Example Request

{ "description": "Warm tones with slight fade", "name": "My Warm Look", "params": { "a_scale": 0.95, "a_shift": -2.0, "b_scale": 1.05, "b_shift": 3.0, "fade": 0.05, "highlight_tint_a": -0.5, "highlight_tint_b": 0.5, "l_contrast": 1.1, "l_shift": 5.0, "saturation": 1.1, "shadow_tint_a": 1.0, "shadow_tint_b": -1.0 }, "source_type": "scratch" }

Example Response

{ "preset": { "created_at": "2026-02-24T12:00:00Z", "description": "Warm tones with slight fade", "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "My Warm Look", "params": { "a_scale": 0.95, "a_shift": -2.0, "b_scale": 1.05, "b_shift": 3.0, "fade": 0.05, "highlight_tint_a": -0.5, "highlight_tint_b": 0.5, "l_contrast": 1.1, "l_shift": 5.0, "saturation": 1.1, "shadow_tint_a": 1.0, "shadow_tint_b": -1.0 }, "source_type": "scratch" }, "success": true }
DELETE /api/v1/presets/custom/<preset_id> #
Free

Delete a custom preset

Example Response

{ "success": true }
GET /api/v1/presets/custom/<preset_id> #
Free

Get a custom preset

Example Response

{ "preset": { "created_at": "2026-02-24T12:00:00Z", "description": "Warm tones with slight fade", "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "My Warm Look", "params": { "a_scale": 0.95, "a_shift": -2.0, "b_scale": 1.05, "b_shift": 3.0, "fade": 0.05, "highlight_tint_a": -0.5, "highlight_tint_b": 0.5, "l_contrast": 1.1, "l_shift": 5.0, "saturation": 1.1, "shadow_tint_a": 1.0, "shadow_tint_b": -1.0 }, "source_type": "scratch" }, "success": true }
PUT /api/v1/presets/custom/<preset_id> #
Free

Update a custom preset

Request Body

name string
description string
params PresetParams

Example Request

{ "name": "Updated Warm Look", "params": { "a_scale": 0.95, "a_shift": -2.0, "b_scale": 1.05, "b_shift": 3.0, "fade": 0.05, "highlight_tint_a": -0.5, "highlight_tint_b": 0.5, "l_contrast": 1.1, "l_shift": 5.0, "saturation": 1.1, "shadow_tint_a": 1.0, "shadow_tint_b": -1.0 } }

Example Response

{ "preset": { "created_at": "2026-02-24T12:00:00Z", "description": "Warm tones with slight fade", "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "My Warm Look", "params": { "a_scale": 0.95, "a_shift": -2.0, "b_scale": 1.05, "b_shift": 3.0, "fade": 0.05, "highlight_tint_a": -0.5, "highlight_tint_b": 0.5, "l_contrast": 1.1, "l_shift": 5.0, "saturation": 1.1, "shadow_tint_a": 1.0, "shadow_tint_b": -1.0 }, "source_type": "scratch" }, "success": true }
POST /api/v1/presets/custom/from-image #
Free

Extract preset params from an image

Request Body

image string Base64 image data (provide image or image_key, not both)
image_key string R2 key from /storage/presign

Example Request

{ "image": "data:image/jpeg;base64,/9j/4AAQ..." }

Example Response

{ "success": true }
POST /api/v1/presets/preview #
1 credit

Preview custom LAB params on an image (stateless)

Claude Code integration — This endpoint is ideal for AI-assisted preset design. Point Claude Code (or any LLM with tool use) at the ShotMatch API and describe the color grade you want in plain language — e.g. "dark teal-and-orange, crushed blacks, slight fade like Sin City". Claude translates your description into the 12 LAB parameters, calls this endpoint with your image, and shows you the result. Iterate until you're happy, then save via POST /presets/custom and optionally export a .cube LUT via POST /lut/export/preset/<name>.

Request Body

image string Base64-encoded image (deprecated — prefer image_key)
image_key string R2 key from /storage/presign
params PresetParams required
intensity number Default: 1.0

Example Request

{ "image": "data:image/jpeg;base64,/9j/4AAQ...", "intensity": 0.8, "params": { "a_scale": 0.95, "a_shift": -2.0, "b_scale": 1.05, "b_shift": 3.0, "fade": 0.05, "highlight_tint_a": -0.5, "highlight_tint_b": 0.5, "l_contrast": 1.1, "l_shift": 5.0, "saturation": 1.1, "shadow_tint_a": 1.0, "shadow_tint_b": -1.0 } }

Example Response

{ "poll_url": "/api/v1/tasks/img_a1b2c3d4e5f6", "success": true, "task_id": "img_a1b2c3d4e5f6" }

Film Effects

POST /api/v1/film-effects/apply #
1 credit

Apply film effects to an image

Request Body

image string Base64-encoded image (deprecated — prefer image_key)
image_key string R2 key from /storage/presign
preset string Effect preset name
effects object Granular effect config
intensity number Default: 1.0

Example Request

{ "image": "data:image/jpeg;base64,/9j/4AAQ...", "intensity": 0.8, "preset": "35mm" }

Example Response

{ "poll_url": "/api/v1/tasks/img_a1b2c3d4e5f6", "success": true, "task_id": "img_a1b2c3d4e5f6" }
GET /api/v1/film-effects/presets #
Free No auth

List film effects presets

Example Response

{ "presets": [ { "description": "Classic 35mm film look", "label": "35mm Film", "name": "35mm" }, { "description": "Warm tungsten lighting", "label": "Tungsten Glow", "name": "tungsten_glow" } ], "success": true }

Looks

GET /api/v1/looks #
Free No auth

List available looks

Example Response

{ "looks": [ { "description": "Cyberpunk neon look", "label": "Blade Runner", "name": "blade_runner" }, { "description": "Cool blue moonlit tones", "label": "Moonlight", "name": "moonlight" } ], "success": true }
POST /api/v1/looks/<look_name>/apply #
1 credit

Apply a look to an image

Request Body

image string Base64-encoded image (deprecated — prefer image_key)
image_key string R2 key from /storage/presign
intensity number Default: 1.0
color_intensity number Default: 1.0
effects_intensity number Default: 1.0
effects_overrides object Per-effect override params

Example Request

{ "color_intensity": 0.8, "effects_intensity": 0.5, "image": "data:image/jpeg;base64,/9j/4AAQ...", "intensity": 1.0 }

Example Response

{ "poll_url": "/api/v1/tasks/img_a1b2c3d4e5f6", "success": true, "task_id": "img_a1b2c3d4e5f6" }

LUT Export

POST /api/v1/lut/apply #
1 credit

Apply a LUT extracted from before/after images

Example Request

{ "after": "data:image/jpeg;base64,/9j/4AAQ...", "before": "data:image/jpeg;base64,/9j/4AAQ...", "size": 33, "target": "data:image/jpeg;base64,/9j/4AAQ..." }

Example Response

{ "poll_url": "/api/v1/tasks/img_a1b2c3d4e5f6", "success": true, "task_id": "img_a1b2c3d4e5f6" }
POST /api/v1/lut/export/before-after #
2 credits pro+

Export LUT from before/after images as .cube file

Example Request

{ "after": "data:image/jpeg;base64,/9j/4AAQ...", "before": "data:image/jpeg;base64,/9j/4AAQ...", "size": 33 }
POST /api/v1/lut/export/match #
2 credits pro+

Export color match as LUT file

Example Request

{ "method": "natural", "reference": "data:image/jpeg;base64,/9j/4AAQ...", "size": 33 }
POST /api/v1/lut/export/preset/<preset_name> #
2 credits pro+

Export a preset as LUT file

Example Request

{ "intensity": 1.0, "size": 33 }
GET /api/v1/lut/sizes #
Free No auth

List available LUT sizes

Example Response

{ "sizes": [ { "cube_size": 17, "name": "small" }, { "cube_size": 33, "name": "medium" }, { "cube_size": 65, "name": "large" } ], "success": true }

AI Color Grading

POST /api/v1/ai/refine #
2 credits

Refine AI color grading with follow-up

Request Body

prompt string required Follow-up prompt
original_image string Original base64 image (deprecated — prefer original_image_key)
original_image_key string R2 key of original image from /storage/presign
last_result_image string Last result base64 image (deprecated — prefer last_result_image_key)
last_result_image_key string R2 key of last result image
current_values object required Current ColorGradeValues dict from previous response
messages object[] required Conversation history (list of {role, content} dicts)

Example Request

{ "current_values": { "blacks": -8, "contrast": 12, "exposure": 0.15, "highlights": -20, "saturation": 5, "shadows": 15, "temperature": 6200, "tint": 5, "vibrance": 18, "whites": 10 }, "messages": [ { "content": "Make it look like a warm sunset", "role": "user" }, { "content": "{\"values\": {\"temperature\": 6200}, \"explanation\": \"Applied warm tones\"}", "role": "assistant" } ], "original_image": "data:image/jpeg;base64,/9j/4AAQ...", "prompt": "Make the shadows cooler and add more contrast" }

Example Response

{ "chat_history": [ { "content": "Make the shadows cooler and add more contrast", "role": "user" }, { "content": "I cooled the shadows and increased contrast.", "role": "assistant" } ], "credits_remaining": 42, "explanation": "I cooled the shadows and increased contrast.", "messages": [ { "content": "Make it look like a warm sunset", "role": "user" }, { "content": "{\"values\": {\"temperature\": 6200}, \"explanation\": \"Applied warm tones\"}", "role": "assistant" }, { "content": "Make the shadows cooler and add more contrast", "role": "user" }, { "content": "{\"values\": {\"temperature\": 6200, \"contrast\": 20}, \"explanation\": \"Cooled shadows\"}", "role": "assistant" } ], "processing_time_ms": 3456, "result_key": "results/usr_abc123/2026/02/24/result_x7k9.jpg", "result_url": "https://r2.shotmatch.io/results/usr_abc123/2026/02/24/result_x7k9.jpg", "success": true, "values": { "blacks": -8, "contrast": 12, "exposure": 0.15, "highlights": -20, "saturation": 5, "shadows": 15, "temperature": 6200, "tint": 5, "vibrance": 18, "whites": 10 } }
POST /api/v1/ai/suggest #
2 credits

AI color grading suggestion

Request Body

image string Base64-encoded image (deprecated — prefer image_key)
image_key string R2 key from /storage/presign
prompt string required Color grading prompt

Example Request

{ "image": "data:image/jpeg;base64,/9j/4AAQ...", "prompt": "Make it look like a warm sunset with golden tones" }

Example Response

{ "chat_history": [ { "content": "Make it look like a warm sunset with golden tones", "role": "user" }, { "content": "I warmed up the color temperature and boosted golden tones.", "role": "assistant" } ], "credits_remaining": 42, "explanation": "I warmed up the color temperature and boosted golden tones in the highlights.", "messages": [ { "content": "Make it look like a warm sunset with golden tones", "role": "user" }, { "content": "{\"values\": {\"temperature\": 6200}, \"explanation\": \"Applied warm tones\"}", "role": "assistant" } ], "processing_time_ms": 3456, "result_key": "results/usr_abc123/2026/02/24/result_x7k9.jpg", "result_url": "https://r2.shotmatch.io/results/usr_abc123/2026/02/24/result_x7k9.jpg", "success": true, "values": { "blacks": -8, "contrast": 12, "exposure": 0.15, "highlights": -20, "saturation": 5, "shadows": 15, "temperature": 6200, "tint": 5, "vibrance": 18, "whites": 10 } }
POST /api/v1/grade #
2 credits

Prompt-to-look — natural-language color grading powered by the ShotMatch catalog

Request Body

image string Base64-encoded image (deprecated — prefer image_key)
image_key string R2 key from /storage/presign
prompt string required Natural-language grade description
include_lut boolean Return a .cube LUT URL alongside the preview Default: True
lut_size string LUT resolution: small (17³), medium (33³), large (65³) Default: medium
intensity number Dose of the grade (0=original, 1=full effect, default 1.0) Default: 1.0

Example Request

{ "image_key": "images/usr_abc123/20260224_a1b2c3d4.jpg", "include_lut": true, "lut_size": "medium", "prompt": "Give me the Blade Runner 2049 look but slightly warmer" }

Example Response

{ "absolute_values": null, "credits_remaining": 41, "explanation": "Matched Blade Runner with a warm tweak on temperature.", "lut_key": "results/usr_abc123/2026/05/14/grade_x7k9.cube", "lut_url": "https://r2.shotmatch.io/results/usr_abc123/2026/05/14/grade_x7k9.cube", "match": { "confidence": 0.9, "name": "blade_runner", "type": "look" }, "processing_time_ms": 3120, "result_key": "results/usr_abc123/2026/05/14/grade_x7k9.jpg", "result_url": "https://r2.shotmatch.io/results/usr_abc123/2026/02/24/result_x7k9.jpg", "success": true, "tweaks": { "temperature": 0.15 } }

White Balance

POST /api/v1/white-balance/apply #
1 credit

Apply white balance correction

Request Body

image string Base64-encoded image (deprecated — prefer image_key)
image_key string R2 key from /storage/presign
method "auto" | "gray_world" | "white_patch" | "neutral_point" Default: auto
intensity number Correction intensity (0=none, 1=full) Default: 1.0
neutral_x number Normalized X coordinate of neutral point (0.0=left, 1.0=right)
neutral_y number Normalized Y coordinate of neutral point (0.0=top, 1.0=bottom)

Example Request

{ "image": "data:image/jpeg;base64,/9j/4AAQ...", "intensity": 1.0, "method": "auto" }

Example Response

{ "poll_url": "/api/v1/tasks/img_a1b2c3d4e5f6", "success": true, "task_id": "img_a1b2c3d4e5f6" }

Style Transfer

POST /api/v1/style-transfer/apply #
5 credits

Apply neural style transfer to an image

Request Body

content string Base64-encoded content image (deprecated — prefer content_key)
content_key string R2 key from /storage/presign
style string Base64-encoded style image (deprecated — prefer style_key)
style_key string R2 key from /storage/presign
seed integer Random seed for reproducibility Default: 42

Example Request

{ "content": "data:image/jpeg;base64,/9j/4AAQ...", "seed": 42, "style": "data:image/jpeg;base64,/9j/4AAQ..." }

Example Response

{ "poll_url": "/api/v1/tasks/img_a1b2c3d4e5f6", "success": true, "task_id": "img_a1b2c3d4e5f6" }

Video Grading

POST /api/v1/video/grade #
1 credit pro+

Submit video color grading task (reference or preset)

Request Body

video_key string required S3 key of uploaded video
reference string Base64 reference image (deprecated — prefer reference_key)
reference_key string R2 key of reference image from /storage/presign
preset string Preset name (e.g. cinematic_warm)
preset_intensity number Default: 1.0
method "natural" | "direct" | "smooth" | "balanced" Default: natural
quality "perfect" | "pro" | "test" | "prores" Default: pro
duration number required Client-reported video duration for upfront credit calc
params MatchParams
webhook_url string URL to POST result when processing completes

Example Request

{ "duration": 30.0, "method": "natural", "quality": "pro", "reference": "data:image/jpeg;base64,/9j/4AAQ...", "video_key": "videos/usr_abc123/2026/02/24/clip_x7k9.mp4" }

Example Response

{ "credits_remaining": 42, "credits_required": 90, "poll_url": "/api/v1/tasks/video_a1b2c3d4e5f6", "success": true, "task_id": "video_a1b2c3d4e5f6" }
POST /api/v1/video/test #
1 credit pro+

Test color grade on first video frame

Request Body

video_key string required S3 key of uploaded video
reference string Base64 reference image (deprecated — prefer reference_key)
reference_key string R2 key of reference image from /storage/presign
preset string Preset name
preset_intensity number Default: 1.0
method "natural" | "direct" | "smooth" | "balanced" Default: natural
params MatchParams
look_name string Cinematic look name (e.g. blade_runner)
look_intensity number Default: 1.0
look_color_intensity number Default: 1.0
look_effects_intensity number Default: 1.0
look_effects_overrides object Per-effect override params
multi_references array Base64 reference images (deprecated — prefer multi_reference_keys)
multi_reference_keys array R2 keys of reference images from /storage/presign
multi_blend_mode "uniform" | "weighted" | "gradient" Default: uniform
multi_method "natural" | "direct" | "smooth" | "balanced" Default: natural
multi_transition_width number Default: 0.2
multi_intensity number Default: 0.75

Example Request

{ "method": "natural", "reference": "data:image/jpeg;base64,/9j/4AAQ...", "video_key": "videos/usr_abc123/2026/02/24/clip_x7k9.mp4" }

Example Response

{ "poll_url": "/api/v1/tasks/video_a1b2c3d4e5f6", "success": true, "task_id": "video_a1b2c3d4e5f6" }

References

GET /api/v1/references #
Free

List saved reference images

Example Response

{ "limit": 200, "offset": 0, "references": [ { "category_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "created_at": "2026-02-24T12:00:00Z", "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "Golden Hour", "position": 0, "r2_key": "images/usr_abc123/golden-hour.jpg" } ], "success": true, "total": 1 }
POST /api/v1/references #
Free

Upload a new reference image

Request Body

name string required
image string Base64-encoded image (deprecated — prefer image_key)
image_key string R2 key from /storage/presign
category_id string Category UUID

Example Request

{ "category_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "image": "data:image/jpeg;base64,/9j/4AAQ...", "name": "Golden Hour" }

Example Response

{ "reference": { "category_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "created_at": "2026-02-24T12:00:00Z", "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "Golden Hour", "position": 0, "r2_key": "images/usr_abc123/golden-hour.jpg" }, "success": true }
DELETE /api/v1/references/<ref_id> #
Free

Delete a reference image

Example Response

{ "success": true }
PATCH /api/v1/references/<ref_id> #
Free

Update a reference image

Request Body

name string
category_id string
position integer

Example Request

{ "category_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "name": "Sunset Beach" }

Example Response

{ "success": true }
GET /api/v1/references/<ref_id>/image #
Free

Get reference image as presigned URL

Example Response

{ "key": "images/usr_abc123/golden-hour.jpg", "name": "Golden Hour", "success": true, "url": "https://r2.shotmatch.io/results/usr_abc123/2026/02/24/result_x7k9.jpg" }
POST /api/v1/references/batch-delete #
Free

Delete multiple reference images at once

Request Body

ids string[] required Reference UUIDs to delete

Example Request

{ "ids": [ "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "b2c3d4e5-f6a7-8901-bcde-f12345678901" ] }

Example Response

{ "deleted": 2, "success": true }
GET /api/v1/references/categories #
Free

List reference categories

Example Response

{ "categories": [ { "created_at": "2026-02-24T12:00:00Z", "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "name": "Landscapes", "position": 0 } ], "success": true }
POST /api/v1/references/categories #
Free

Create a reference category

Request Body

name string required

Example Request

{ "name": "Landscapes" }

Example Response

{ "category": { "created_at": "2026-02-24T12:00:00Z", "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "name": "Landscapes", "position": 0 }, "success": true }
DELETE /api/v1/references/categories/<cat_id> #
Free

Delete a reference category

Example Response

{ "success": true }
PATCH /api/v1/references/categories/<cat_id> #
Free

Update a reference category

Request Body

name string
position integer

Example Request

{ "name": "Nature" }

Example Response

{ "success": true }
POST /api/v1/references/categories/reorder #
Free

Reorder reference categories

Request Body

items ReorderItem[] required

Example Request

{ "items": [ { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "position": 0 }, { "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "position": 1 } ] }

Example Response

{ "success": true }
POST /api/v1/references/clip #
Free

Save a video clip to reference library

Example Request

{ "clip_r2_key": "lab_tmp/abc123/clip_001.mp4", "name": "Clip 1 \u2014 my_video.mp4", "poster_r2_key": "lab_tmp/abc123/poster_001.jpg" }

Example Response

{ "reference": { "category_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "created_at": "2026-02-24T12:00:00Z", "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "Golden Hour", "position": 0, "r2_key": "images/usr_abc123/golden-hour.jpg" }, "success": true }
POST /api/v1/references/frame #
Free

Save an extracted frame to reference library

Example Request

{ "frame_r2_key": "lab_tmp/abc123/first_001.jpg", "name": "Clip 1 first frame \u2014 my_video.mp4" }

Example Response

{ "reference": { "category_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "created_at": "2026-02-24T12:00:00Z", "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "Golden Hour", "position": 0, "r2_key": "images/usr_abc123/golden-hour.jpg" }, "success": true }
POST /api/v1/references/reorder #
Free

Reorder reference images

Request Body

items ReorderItem[] required

Example Request

{ "items": [ { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "position": 0 }, { "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "position": 1 } ] }

Example Response

{ "success": true }

History

DELETE /api/v1/history #
Free

Clear all history

Example Response

{ "deleted": 25, "success": true }
GET /api/v1/history #
Free

List history entries

Example Response

{ "entries": [ { "created_at": "2026-02-24T14:30:00Z", "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "label": "match:natural", "r2_key": "results/usr_abc123/2026/02/24/result_x7k9.jpg", "source_type": "api" } ], "limit": 50, "offset": 0, "success": true, "total": 1 }
DELETE /api/v1/history/<entry_id> #
Free

Delete a history entry

Example Response

{ "success": true }
GET /api/v1/history/<entry_id>/image #
Free

Get history image as presigned URL

Example Response

{ "key": "results/usr_abc123/2026/02/24/result_x7k9.jpg", "label": "match:natural", "success": true, "url": "https://r2.shotmatch.io/results/usr_abc123/2026/02/24/result_x7k9.jpg" }
GET /api/v1/history/<entry_id>/lut #
Free

Download LUT from video history entry

GET /api/v1/history/<entry_id>/video #
Free

Get presigned URL for graded video

Example Response

{ "label": "Video", "success": true, "video_url": "https://r2.shotmatch.io/results/usr_abc123/2026/02/24/graded_x7k9.mp4" }
POST /api/v1/history/batch-delete #
Free

Delete multiple history entries at once

Request Body

ids string[] required Reference UUIDs to delete

Example Request

{ "ids": [ "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "b2c3d4e5-f6a7-8901-bcde-f12345678901" ] }

Example Response

{ "deleted": 2, "success": true }
GET /api/v1/history/filmstrip #
Free

Get recent history filmstrip

Example Response

{ "entries": [ { "created_at": "2026-02-24T14:30:00Z", "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "label": "match:natural", "r2_key": "results/usr_abc123/2026/02/24/result_x7k9.jpg", "source_type": "api" } ], "success": true }

Preferences

GET /api/v1/preferences #
Free

Get user preferences

Example Response

{ "preferences": { "auto_apply_on_drag": true, "theme": "dark" }, "success": true }
PATCH /api/v1/preferences #
Free

Update user preferences

Request Body

auto_apply_on_drag boolean
theme string

Example Request

{ "auto_apply_on_drag": true, "theme": "dark" }

Example Response

{ "preferences": { "auto_apply_on_drag": true, "theme": "dark" }, "success": true }

Storage

DELETE /api/v1/storage/<path:key> #
Free

Delete a file from storage

Example Response

{ "success": true }
POST /api/v1/storage/presign #
Free

Get presigned upload URL for direct upload

Request Body

filename string Default: image.jpg
content_type string Default: image/jpeg
folder string Default: images

Example Request

{ "content_type": "image/jpeg", "filename": "photo.jpg", "folder": "images" }

Example Response

{ "fields": { "Content-Type": "image/jpeg", "key": "images/usr_abc123/2026/02/24/img_a1b2.jpg" }, "key": "images/usr_abc123/2026/02/24/img_a1b2.jpg", "success": true, "upload_url": "https://r2.shotmatch.io/presigned-upload?X-Amz-Signature=..." }
POST /api/v1/storage/upload #
Free

Upload a file via base64 JSON

Request Body

data string Base64-encoded file data (deprecated — prefer /storage/presign)
data_key string R2 key from /storage/presign (no-op — file already uploaded)
folder string Default: images

Example Request

{ "data": "data:image/jpeg;base64,/9j/4AAQ...", "folder": "images" }

Example Response

{ "key": "images/usr_abc123/2026/02/24/img_a1b2.jpg", "success": true, "url": "https://r2.shotmatch.io/images/usr_abc123/2026/02/24/img_a1b2.jpg" }
POST /api/v1/storage/upload/video #
Free

Upload a video file via base64 or presign workflow

Example Request

{ "data": "data:video/mp4;base64,AAAAIGZ0eXA...", "filename": "clip.mp4" }

Example Response

{ "key": "videos/usr_abc123/2026/02/24/clip.mp4", "success": true, "url": "https://r2.shotmatch.io/videos/usr_abc123/2026/02/24/clip.mp4" }
POST /api/v1/storage/url #
Free

Refresh presigned URL for existing file

Request Body

key string required S3 object key
expires_in integer Expiry in seconds Default: 604800

Example Request

{ "expires_in": 604800, "key": "results/usr_abc123/2026/02/24/result_x7k9.jpg" }

Example Response

{ "key": "results/usr_abc123/2026/02/24/result_x7k9.jpg", "success": true, "url": "https://r2.shotmatch.io/images/usr_abc123/2026/02/24/img_a1b2.jpg" }

Tasks & Queue

GET /api/v1/queue/stats #
Free

Get queue statistics

Example Response

{ "success": true }
GET /api/v1/tasks/<task_id> #
Free

Get async task status and result

Example Response

{ "status": "completed", "success": true, "task_id": "video_a1b2c3d4e5f6" }

Account

GET /api/v1/account #
Free

Get account information

Example Response

{ "credits_purchased": 42, "credits_remaining": 142, "credits_subscription": 100, "email": "[email protected]", "plan": "pro", "success": true }
GET /api/v1/account/usage #
Free

Get API usage history

Example Response

{ "has_more": false, "limit": 50, "offset": 0, "period_days": 30, "success": true, "total": 1, "usage": [ { "created_at": "2026-02-24T14:30:00Z", "images_count": 1, "method": "natural", "processing_time_ms": 1234, "source": "api" } ] }

Other

GET /api/v1/health #
Free No auth

Health check endpoint

Example Response

{ "checks": {}, "status": "ok", "version": "1.0.0" }

Bg Remove

POST /api/v1/bg-remove/apply #
2 credits

Remove image background (GPU)

Request Body

image string Base64-encoded image (deprecated — prefer image_key)
image_key string R2 key from /storage/presign

Example Request

{ "image": "data:image/jpeg;base64,/9j/4AAQ..." }

Example Response

{ "poll_url": "/api/v1/tasks/img_a1b2c3d4e5f6", "success": true, "task_id": "img_a1b2c3d4e5f6" }

Plugin

GET /api/v1/plugin/devices #
Free

List recent plugin devices for the user

DELETE /api/v1/plugin/devices/<device_id> #
Free

Revoke all plugin sessions for a single device

GET /api/v1/plugin/lut.cube #
Free

Server-generated preset LUT (entitled users only)

GET /api/v1/plugin/presets.json #
Free

Plugin preset catalog (entitlement-gated)

POST /api/v1/plugin/session #
Free

Exchange API key for a 24h plugin session token

Example Response

{ "email": "[email protected]", "entitled": true, "entitlement_reason": "trial", "expires_in": 86400, "plan": "free", "success": true, "token": "smt_\u2026", "token_type": "Bearer", "trial_active": true, "trial_days_remaining": 12 }
GET /api/v1/plugin/version #
Free No auth

Plugin version manifest (auto-update check)

Example Response

{ "download_url": "/account/plugins/download/photoshop", "host": "photoshop", "install_instructions_url": "/admin/plugins", "latest_version": "0.4.0", "min_supported_version": "0.3.0", "release_notes": "Short-lived session tokens; force-update; device tracking.", "success": true }
GET /api/v1/plugin/whoami #
Free

Identify the caller + return entitlement

Example Response

{ "credits_remaining": 0, "email": "[email protected]", "entitled": true, "entitlement_reason": "trial", "plan": "free", "plan_label": "Free", "success": true, "trial_active": true, "trial_days_remaining": 12, "upgrade_url": "https://shotmatch.app/pricing" }

Stacks

GET /api/v1/stacks #
Free

List processing stacks

Example Response

{ "stacks": [ { "created_at": "2026-02-24T12:00:00Z", "description": "White balance then warm preset", "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "Portrait Pipeline", "steps": [ { "enabled": true, "intensity": 1.0, "params": { "method": "auto" }, "type": "white_balance" }, { "enabled": true, "intensity": 0.8, "params": { "preset_name": "cinematic_warm" }, "type": "preset" } ] } ], "success": true }
POST /api/v1/stacks #
Free

Create a processing stack

Request Body

name string required
description string
steps ActionStep[] required

Example Request

{ "description": "White balance then warm preset", "name": "Portrait Pipeline", "steps": [ { "enabled": true, "intensity": 1.0, "params": { "method": "auto" }, "type": "white_balance" }, { "enabled": true, "intensity": 0.8, "params": { "preset_name": "cinematic_warm" }, "type": "preset" } ] }

Example Response

{ "stack": { "created_at": "2026-02-24T12:00:00Z", "description": "White balance then warm preset", "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "Portrait Pipeline", "steps": [ { "enabled": true, "intensity": 1.0, "params": { "method": "auto" }, "type": "white_balance" }, { "enabled": true, "intensity": 0.8, "params": { "preset_name": "cinematic_warm" }, "type": "preset" } ] }, "success": true }
DELETE /api/v1/stacks/<stack_id> #
Free

Delete a processing stack

Example Response

{ "success": true }
GET /api/v1/stacks/<stack_id> #
Free

Get a processing stack

Example Response

{ "stack": { "created_at": "2026-02-24T12:00:00Z", "description": "White balance then warm preset", "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "Portrait Pipeline", "steps": [ { "enabled": true, "intensity": 1.0, "params": { "method": "auto" }, "type": "white_balance" }, { "enabled": true, "intensity": 0.8, "params": { "preset_name": "cinematic_warm" }, "type": "preset" } ] }, "success": true }
PUT /api/v1/stacks/<stack_id> #
Free

Update a processing stack

Request Body

name string
description string
steps array

Example Request

{ "name": "Updated Pipeline", "steps": [ { "enabled": true, "intensity": 1.0, "params": { "preset_name": "cinematic_cool" }, "type": "preset" } ] }

Example Response

{ "stack": { "created_at": "2026-02-24T12:00:00Z", "description": "White balance then warm preset", "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "Portrait Pipeline", "steps": [ { "enabled": true, "intensity": 1.0, "params": { "method": "auto" }, "type": "white_balance" }, { "enabled": true, "intensity": 0.8, "params": { "preset_name": "cinematic_warm" }, "type": "preset" } ] }, "success": true }
POST /api/v1/stacks/apply #
2 credits

Apply a processing stack to an image

Request Body

image string Base64 image data (provide image or image_key, not both)
image_key string R2 key from /storage/presign
stack_id string ID of a saved stack (provide stack_id or steps, not both)
steps array Inline steps array (alternative to stack_id)

Example Request

{ "image": "data:image/jpeg;base64,/9j/4AAQ...", "stack_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" }

Example Response

{ "poll_url": "/api/v1/tasks/img_a1b2c3d4e5f6", "success": true, "task_id": "img_a1b2c3d4e5f6" }
POST /api/v1/stacks/apply-video #
1 credit pro+

Apply a processing stack to a full video

Request Body

video_key string required R2 key from /storage/presign
stack_id string ID of a saved stack
steps array Inline steps array (alternative to stack_id)
duration number required Video duration in seconds (for credit estimation)
quality "perfect" | "pro" | "test" Processing quality preset Default: pro
webhook_url string Optional webhook for completion notification

Example Request

{ "duration": 30.0, "quality": "pro", "stack_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "video_key": "videos/usr_abc123/2026/02/24/clip_x7k9.mp4" }

Example Response

{ "poll_url": "/api/v1/tasks/video_a1b2c3d4e5f6", "success": true, "task_id": "video_a1b2c3d4e5f6" }
POST /api/v1/stacks/apply-video/test #
1 credit pro+

Test a processing stack on the first frame of a video

Request Body

video_key string required R2 key from /storage/presign
stack_id string ID of a saved stack
steps array Inline steps array (alternative to stack_id)

Example Request

{ "stack_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "video_key": "videos/usr_abc123/2026/02/24/clip_x7k9.mp4" }

Example Response

{ "poll_url": "/api/v1/tasks/video_a1b2c3d4e5f6", "success": true, "task_id": "video_a1b2c3d4e5f6" }

This site uses strictly necessary cookies for authentication and preferences. No tracking or advertising cookies. Cookie Policy