For the complete documentation index, see llms.txt. This page is also available as Markdown.

Response Caching: Images & Video (Async)

This page covers caching for asynchronous image generation (POST /api/v1/images/generations) and video generation (POST /api/v1/videos). For text completions, see Response Caching: Text.

Overview

For images and videos, FastRouter caches the task, not just the payload. When a request matches a cached entry, FastRouter returns the same task ID as the original request along with cached: true, and the client retrieves the result through the normal getAsyncResponse polling flow. No new provider job is created, and the request is not billed.

Modality
Generate
Retrieve
Caching status

Image (async)

POST /api/v1/images/generations

POST /api/v1/getAsyncResponse or GET /api/v1/images/{task_id}

Supported

Video (always async)

POST /api/v1/videos

POST /api/v1/getAsyncResponse

Supported

Image (sync)

POST /api/v1/images/generations

—

Not yet supported — coming soon

Caching is especially effective for product catalogs, thumbnails and templated creatives (images), and for marketing loops, previews and repeated demo prompts (videos).


Key Benefits

Benefit
Description

Faster Results

A hit returns an existing task ID, skipping the full generation wait entirely

Cost Reduction

Image and video cache hits are free — the hitting request is not billed

Consistent Outputs

Identical prompts return the identical asset

Reduced Provider Load

Fewer upstream jobs queued at Leonardo, Pollo, and other providers

Explicit Hit Signal

cached: true on the creation response tells clients the task ID came from cache

Custom Cache Keys

User-defined namespaces for precise cache control


Eligibility

Request
Cached?

POST /api/v1/videos (always async)

Yes

POST /api/v1/images/generations with response_type: "async"

Yes

POST /api/v1/images/generations on an async-only model (e.g. Leonardo, Flux via Leonardo)

Yes — routed async regardless of response_type

POST /api/v1/images/generations processed synchronously

No — cache is bypassed (no lookup, no store)

A sync-processed request neither reads from nor writes to the cache, so it will not populate an entry that a later async request could hit. Sync image caching is planned.


Feature Specification

Caching is enabled by including a cache_key header and an optional cache configuration object in the request body. The contract is identical for images and videos.

Headers

Header
Type
Required
Description

Authorization

string

Yes

Bearer token with API key

Content-Type

string

Yes

application/json

cache_key

string

Yes (for caching)

User-defined cache namespace. If omitted, caching is disabled

Tracing headers (traceparent, x-span-id, x-span-name) are passed through and do not affect the cache key.

Cache Key Header

The cache_key header defines the primary cache namespace — for example product-thumbnails, marketing-loops, or imagegen1. FastRouter combines it with hashed request attributes to form the final lookup key.

The endpoint is part of the key, so the same cache_key used on /api/v1/images/generations and /api/v1/videos produces two independent namespaces.

Cache Object Parameters

Parameter
Type
Default
Required
Description

expiration_time

integer

57600 (16h)

No

Cache TTL in seconds (60–604800)

filter_on_model

boolean

true

No

Match cache on model name

filter_on_provider

boolean

false

No

Match cache on provider

similarity_threshold

number

1.0

No

Semantic similarity score (0–1) on the prompt required to reuse a task

conversation_mode and last_n_turns are text-only and are ignored here.

🔍 similarity_threshold Explained

Semantic matching is applied to the prompt text only. All other generation parameters (size, length, resolution, reference media, etc.) must match exactly regardless of threshold.

Value
Behavior

1.0 (default)

Exact prompt match only

Why exact match by default for media? "A red car on a beach" and "a crimson car by the sea" may embed at 0.9 similarity, but a user rarely wants the same image for both. Lower the threshold deliberately for cases like FAQ illustrations or placeholder assets, where interchangeability is acceptable.


How a Cache Hit Behaves

Detecting a hit. The creation response carries a top-level cached: true when the returned task ID came from cache. The field is absent on a miss. This is the field clients should branch on.

Task ID semantics.

  • A hit returns the original task ID (fr_-prefixed) — task_id for images, data.taskId for videos. It is a real, pollable task; getAsyncResponse with that ID works regardless of which request created it.

  • Each hitting request still gets its own chat_id, so it appears in the Activity Log as its own row.

  • Task IDs are org-scoped; a task ID is never returned to a different organization.

Billing. A hit is not charged. estimate_usage.credits_used is 0 on an image hit; on a video hit the credit fields are omitted from estimate_usage entirely. estimate_usage.provider still names the provider that produced the original asset.

Polling. getAsyncResponse returns the original task's record — the same data, the same fastrouter_assets, and the usage of the generation that actually ran. It does not carry cached, and its usage is not zeroed. Poll responses are not re-billed; measure cache savings from the creation response or the Activity Log, not from the polling response.

Assets. getAsyncResponse returns both the provider data[].url and fastrouter_assets.urls. Treat fastrouter_assets.urls as authoritative — signed provider URLs (Leonardo CDN, Pollo CDN, TOS-signed links) expire well before the hosted copy does.

fastrouter_assets.cached_at / expires_at describe asset hosting retention (up to 30 days depending on plan), which is independent of the response-cache TTL set by expiration_time. The cache TTL governs whether a new request is matched to an existing task; asset retention governs how long the hosted URL stays downloadable.


Cache Lookup

FastRouter normalizes to its canonical model slug for lookup — bytedance/seedance-1.5-pro and bytedance/seedance-1-5-pro hash identically. With filter_on_provider: false (the default), the same model routed through different providers shares one entry.


Image Caching (Async)

Sample Request

To force async routing on a model that also has a sync provider, add "response_type": "async".

Parameter Sensitivity

Always included in the cache key:

Parameter
Notes

prompt

Subject to similarity_threshold

n

Requesting 2 images ≠ requesting 4. See "n handling" below

size

Exact match. auto is resolved to the model default before hashing

quality

Exact match. auto resolved before hashing

style

Exact match

background

Exact match

output_format

Exact match (changes the bytes produced)

seed

Exact match if provided. Omitted seed and explicit seed are distinct keys

Reference / input images

Hashed by content (SHA-256 of bytes, or of the fetched URL body)

mask (edits)

Hashed by content

Ignored for cache hashing: response_format, user, tracing headers.

n handling: A cached entry for n=4 is not reused for n=1. Keeping n in the key avoids ambiguity over which subset to return.

response_format handling: Not hashed. The cached asset is served as url or b64_json per the hitting request.

response_type handling: Not hashed, but it determines eligibility — only async-processed requests participate in the cache.

Creation Response — Cache MISS

Creation Response — Cache HIT

An identical request sent 62 seconds later:

task_id is identical to the first request's. chat_id, created, and estimate_usage.chat_id are new for this request, and credits_used is 0.

Retrieval

Polling the shared task ID returns byte-identical data and fastrouter_assets for every caller. usage reports the original generation's cost (0.0135) — this is a record of what the asset cost to produce, not a charge against the hitting request.


Video Caching

Video generation is always asynchronous: POST /api/v1/videos returns data.taskId, and the client polls POST /api/v1/getAsyncResponse until data.status is succeed / completed.

Sample Request

Parameter Sensitivity

Always included in the cache key:

Parameter
Notes

prompt

Subject to similarity_threshold

negative_prompt

Exact match

length

Exact match

resolution

Exact match

aspect_ratio / fps

Exact match

generateAudio

Exact match

mode / quality (e.g. std, pro)

Exact match

seed

Exact match if provided

cfg_scale / motion_strength

Exact match

Reference image / first-frame / last-frame

Hashed by content

camera_control

Exact match (serialized)

Ignored for cache hashing: callback_url / webhook, user, tracing headers (traceparent, x-span-id, x-span-name).

Creation Response — Cache MISS

Creation Response — Cache HIT

data.taskId is identical to the first request's, and the credit fields are omitted from estimate_usage because nothing is charged. cached sits at the top level, alongside data — not inside it.

message reads "Video generation started" and data.status reads "processing" on a hit as well. Branch on cached, not on the message or status, to tell a reused task from a new one.

Retrieval

Every caller polling this task ID receives the same data, generations, and fastrouter_assets. The taskId / model rules for getAsyncResponse are unchanged: fr_-prefixed IDs require no model.


Response Fields

Creation Response

Field
Type
Description

cached

boolean

Top-level. true when the task ID came from cache; absent on a miss

task_id (image) / data.taskId (video)

string

The task to poll. Identical to the original request's on a hit

chat_id

string

New per request, including hits (for Activity Log and billing)

created

integer

Timestamp of this request

estimate_usage

object

Projected cost. credits_used: 0 (image) or credit fields omitted (video) on a hit

Retrieval Response (getAsyncResponse)

Field
Type
Description

data

object/array

The generated asset record from the original task

fastrouter_assets

object

Hosted asset URLs, cached_at, expires_at. Authoritative download source

usage

object

The original generation's cost. Not a charge against this request

cached is not returned on retrieval responses — only on the creation response.


Billing

Scenario
Behavior

Cache MISS

estimate_usage at submission; final usage billed at standard price when the job completes. Failed jobs are not billed

Cache HIT

Not billed. No credits are deducted at submission or at completion

Storage

Free


Limits

Limit
Value

Min TTL

60 s

Default TTL

57,600 s (16h)

Max TTL

604,800 s (7 days)

Hosted asset retention

Up to 30 days depending on plan

Max cache_key length

128 chars, [A-Za-z0-9_\-:.]


Roadmap

Item
Status

Sync image caching

Planned

similarity score on media hit responses

Planned

Last updated