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.
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
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
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
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
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.
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_idfor images,data.taskIdfor videos. It is a real, pollable task;getAsyncResponsewith 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:
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:
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.
messagereads"Video generation started"anddata.statusreads"processing"on a hit as well. Branch oncached, 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
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)
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
cachedis not returned on retrieval responses — only on the creation response.
Billing
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
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
Sync image caching
Planned
similarity score on media hit responses
Planned
Last updated
