Free, open images.
Shared by everyone.
A free, openly licensed image library that gets better the more it's used. Every prompt returns the closest match in milliseconds; the phrases the library can't answer well yet get generated in the background and added — so the pool keeps expanding and the matches keep sharpening for everyone.
Closest match, not always exact.
wagmi.photos searches the shared library before anything else. Everyday prompts almost always land a strong match. Hyper-specific prompts return the closest image that already exists — close, but maybe not every detail.
High match
Closest match · may differ
An image library that grows as more people use it
Your request flows down, your image comes straight back up — and every new image joins the shared library, so the next person's prompt is more likely to be a hit.

- 1Your prompt's BGE vector is matched against the stored prompt of every image in the library.
- 2Near match — the image is served instantly. That's a hit.
- 3Truly new — you get a 202 and the prompt joins the build queue. No waiting.
- 4The backfill generates the most-requested misses, so tomorrow they're hits.
Runs the background GPUs that generate truly new images.
Stores every image durably — zero egress back to the edge.
Indexes each new image's prompt vector so the next similar prompt is a hit.
Built for speed and price.
What one image costs
List price per 1024×1024 image · July 2026A cache hit serves an existing image from the shared library — no generation fee, no egress. A truly new prompt is generated once at the model's price, then it's free for everyone after. Library access needs a wagmi.photos plan (from $0/mo) — you pay for access, never per image.
Sources: OpenAI API pricing · Google Gemini API pricing · fal.ai — FLUX.1 [schnell] · retrieved July 2026
How long one image takes
Typical generation time · July 2026Generation times vary with load and settings. A cache hit skips generation entirely — one vector search at the edge, and the image is on its way.
Source: Artificial Analysis generation-time benchmarks · retrieved July 2026. Cache-hit latency is the wagmi.photos edge target.
One endpoint. Cache included.
Point the official OpenAI SDK at a new base URL — no other changes. You get back the
OpenAI response shape plus a
shared_cache block
telling you whether it was a hit, how close the match was, and what it saved you.
curl -X POST https://api.wagmi.photos/v1/images/generations \ -H "Authorization: Bearer $WAGMI_KEY" \ -H "Content-Type: application/json" \ -d '{ "prompt": "a vintage bicycle against a brick wall", "cache_tolerance": 0.15, "generate_on_miss": true }'
from openai import OpenAI client = OpenAI( base_url="https://api.wagmi.photos/v1", api_key="sc-your-key", ) img = client.images.generate( prompt="a vintage bicycle " "against a brick wall", extra_body={ "cache_tolerance": 0.15, "generate_on_miss": True}, ) print(img.data[0].url)
import OpenAI from "openai"; const client = new OpenAI({ baseURL: "https://api.wagmi.photos/v1", apiKey: "sc-your-key", }); const img = await client.images .generate({ prompt: "a vintage bicycle " + "against a brick wall", cache_tolerance: 0.15, generate_on_miss: true, }); console.log(img.data[0].url);
Response
{
"data": [{
"url": "https://cdn.wagmi.photos/
img/pd12m-8f31…"
}],
"shared_cache": {
"result": "hit",
"similarity": 0.9312,
"source": "pd12m",
"model_used": "flux-schnell",
"cost_saved_usd": 0.04
}
}
Simple, predictable pricing
Scale your image generation without the scaling costs. No egress fees, no surprises.
Free
Perfect for sandboxing, prototyping, and integrating the cache.
- Restricted cache lookup rate
- Standard CDN asset delivery
- Access to public domain index
- Immediate GPU fallbacks
- SLA uptime guarantees
Pro
Unlimited semantic cache delivery and managed automatic fallbacks for production apps.
- Unlimited semantic cache lookups
- Managed automatic queue fallback
- Z-Image-Turbo background compute
- High-priority cache warming
- SLA uptime guarantees
BYOK
Bring your own GMI Cloud keys. Private GPU generations, straight into the cache.
- Unlimited semantic cache lookups
- Custom GMI Cloud GPU compute
- Private object storage syncing
- Dedicated key generation access
- Zero markup on model generations
Stop paying for the same image twice.
Plug in wagmi.photos and let every generation pull its weight.
Questions, answered
The short version of how the shared library works, what you get back, and what it costs.
What is wagmi.photos?
Do I always get exactly my prompt?
What does cache_tolerance do?
hit versus an approximate match. It never changes what you get back — you always receive the closest image — it just controls the label and which prompts get flagged as gaps worth generating.What happens when my prompt isn't in the library yet?
generate_on_miss: true) the prompt is queued and generated in the background by the shared backend, then stored in the library — so the pool keeps growing toward real demand. Set generate_on_miss: false to only ever pull from the cache and never trigger a generation.Is it OpenAI-compatible?
shared_cache block telling you whether it was a hit, how close the match was, and what it saved you.Is it really free? What's the license?
What is BYOK?
Generator config
Session history
Telemetry & performance
Credentials & authentication
Authorization: Bearer sc-…). The playground here is already authenticated by your login.
Advanced actions
This clears your browser's local state — the telemetry counters, session history, and playground settings. Your account and API keys are stored server-side and are not affected.
API reference
One OpenAI-compatible endpoint, a shared image library in front of it. Everything below is the whole API.
Authentication
All generation requests need a Bearer key, and keys belong to your account. Log in with a magic link (we email it to you — no password), then create a key on the Account page. Or call the endpoint directly with your logged-in session cookie:
# requires a logged-in session — unauthenticated calls return 401 curl -X POST https://api.wagmi.photos/v1/keys/generate \ -H "Cookie: wagmi_session=…" \ -H "Content-Type: application/json" \ -d '{ "label": "my-laptop" }' { "key": "sc-nA93…", "created_at": 1783468800 }
Key minting is rate-limited (10 per minute per IP). Store the key yourself — it is
hashed (SHA-256) before it touches our database, so it cannot be shown again. Send
it on every request as Authorization: Bearer sc-your-key.
Generate or fetch an image
The request shape matches the OpenAI Images API, so the official SDKs work by
pointing base_url at https://api.wagmi.photos/v1.
Your prompt is embedded with BGE and matched against the stored prompt of every
image in the shared library; the closest match above your tolerance floor is
served instantly.
Request body
| Field | Type | Default | Description |
|---|---|---|---|
| prompt | string | required | What you want. Prompts are normalized (trimmed, lowercased, whitespace collapsed) before matching and queueing. |
| cache_tolerance | number 0–1 | 0.15 | How far a match may drift from your prompt. 0 accepts only the closest matches, 1 accepts the loosest. See how matching works. |
| generate_on_miss | boolean | true | Whether a miss queues background GPU generation for this prompt. Set false for cache-only behaviour. See semantics. |
| n | integer | 1 | Only 1 is supported; anything else returns 422. |
| size | string | — | Accepted for OpenAI compatibility. Every response already includes thumb, medium and large URLs. |
| model | string | — | Accepted for OpenAI compatibility. Matching is model-agnostic; shared_cache.model_used reports the model that created the served image. |
Example
curl -X POST https://api.wagmi.photos/v1/images/generations \ -H "Authorization: Bearer $WAGMI_KEY" -H "Content-Type: application/json" \ -d '{ "prompt": "a lighthouse in a storm", "cache_tolerance": 0.15, "generate_on_miss": false }'
Response — served from the library (200)
{
"created": 1783468800,
"data": [{ "url": "https://cdn.wagmi.photos/img/pd12m-8f31…" }],
"shared_cache": {
"result": "hit",
"similarity": 0.93,
"cost_saved_usd": 0.04,
"model_used": "flux-schnell",
"source": "pd12m",
"sizes": { "thumb": "…", "medium": "…", "large": "…" },
"original_url": "https://pd12m.s3.us-west-2.amazonaws.com/…"
}
}
original_url is the external source image when one exists, and
null for generated images.
Response — nothing close enough yet (202)
{
"created": 1783468800,
"data": [],
"shared_cache": {
"result": "pending",
"similarity": 0,
"cost_saved_usd": 0,
"generation_queued": true
}
}
Result values
| result | Status | Meaning |
|---|---|---|
| hit | 200 | Similarity is at or above your tolerance floor. The image is served; nothing is queued. |
| approximate | 200 | The best image falls below your floor. It is served anyway so you have something to show, and the prompt is queued for generation (unless opted out). generation_queued is included and cost_saved_usd is 0 — only true hits count as savings. |
| pending | 202 | The library has nothing to serve. data is empty and the prompt is queued for generation (unless opted out). Retry the same prompt later — once built, it is a hit for everyone. |
How matching works
Matching is prompt-to-prompt: your prompt's BGE text embedding
(bge-base-en-v1.5 on Workers AI) is compared by cosine similarity
against the stored prompt embedding of every library image. Your
cache_tolerance (clamped to 0–1) maps linearly to the similarity
floor: floor = 0.87 − tolerance × (0.87 − 0.75), so tolerance 0
→ floor 0.87 and tolerance 1 → floor 0.75. The single nearest library
prompt is compared against that floor — at or above it you get a
hit, below it an approximate. Realistic scores live in
the ~0.7–0.95 band. See how
semantic matching works for the full picture.
generate_on_miss semantics
Generation costs GPU time, so it is opt-out per request — but the queue is shared, and one prompt can be requested by many callers with different flags. The rules:
- Default is generate. A miss with the field unset (or
true) queues the prompt for background generation. - Opting out is per prompt, not per library.
generate_on_miss: falsestill records the prompt and its demand count — it just tells the backfill to skip it. - Generation wins. If the prompt is already queued for generation, a later request with
falsedoes not un-queue it. And if the prompt was stored opted-out, the first request that arrives with the field unset ortrueupgrades it, so it gets generated. Once a prompt wants generation, it stays wanted. - The response tells you the effective state.
shared_cache.generation_queuedonpendingandapproximateresponses reflects the merged result, not just your request — sendfalsefor a prompt someone else queued and you will getgeneration_queued: trueback.
generate_on_miss: false when you only want
instant, $0 answers — placeholder art, previews, high-volume UI fills — and a miss
should stay a miss instead of spending GPU time.
Errors
| Status | When |
|---|---|
| 400 | Body is not valid JSON, or not a JSON object. |
| 401 | Missing or invalid API key. |
| 422 | n is set to anything but 1, or generate_on_miss is not a boolean. |
| 429 | Rate limit exceeded — generation requests (per account) and key minting (per IP) are each limited to 10 per minute. |
| 502 | An upstream dependency failed; the body includes a detail string. |
Health
Returns {"status":"ok"}. No authentication.
A drop-in for the OpenAI Images API
Keep the official OpenAI SDK. Change one line — the base URL — and every request is answered cache-first, with a shared_cache block riding along in the response.
The only change
base_url = "https://api.openai.com/v1"
base_url = "https://api.wagmi.photos/v1"
Swap your key for a wagmi.photos key (sc-…). Method names, the prompt field, and the way you read data[0].url stay exactly the same.
Python
from openai import OpenAI client = OpenAI( base_url="https://api.wagmi.photos/v1", api_key="sc-your-key", ) img = client.images.generate( prompt="a lighthouse in a storm", extra_body={ "cache_tolerance": 0.15, "generate_on_miss": True, }, ) print(img.data[0].url) # raw response also carries a shared_cache block
JavaScript
import OpenAI from "openai"; const client = new OpenAI({ baseURL: "https://api.wagmi.photos/v1", apiKey: "sc-your-key", }); const img = await client.images.generate({ prompt: "a lighthouse in a storm", cache_tolerance: 0.15, generate_on_miss: true, }); console.log(img.data[0].url);
cURL
curl -X POST https://api.wagmi.photos/v1/images/generations \ -H "Authorization: Bearer $WAGMI_KEY" \ -H "Content-Type: application/json" \ -d '{ "prompt": "a lighthouse in a storm" }'
What stays the same, what you gain
Unchanged
- The official OpenAI SDKs and method names
- The
promptfield and request flow - Reading the image from
data[0].url
Added by wagmi.photos
- A
shared_cacheblock: result, similarity, cost saved - ~0.1 s cache hits at $0 per image
cache_toleranceandgenerate_on_misscontrols
202 means nothing close was cached yet — data is empty and (unless you opted out) the prompt was queued to generate. Handle it like a soft miss: proceed without an image or retry later. Full details in the API reference.How semantic matching works
Every library image is stored with the prompt that made it. A match is just the nearest stored prompt to your prompt — text to text, no keywords, no tags.
Prompts match prompts
wagmi.photos embeds text prompts into a 768-dimensional space with the
bge-base-en-v1.5 model, running on Workers AI at the edge. Every
image in the library is indexed by the embedding of
its own prompt —
there are no image vectors. Because your prompt and the stored prompts are embedded
by the same model, "a golden retriever" lands right next to the prompts that
already produced one.
From prompt to match
- Your prompt is normalized (trimmed, lowercased, whitespace collapsed).
- BGE turns it into a 768-dim text vector at the edge.
- Vectorize finds the single nearest stored prompt vector by cosine similarity.
- That similarity is compared to your tolerance floor — at or above it is a hit; below it is approximate.
Similarity, illustrated
Illustrative cosine-similarity scores — in practice they land in a fairly narrow ~0.7–0.95 band. The generic prompt lands squarely on an existing prompt; the very specific one only finds a distant cousin.
Tolerance sets the floor
Your cache_tolerance (clamped to 0–1) maps linearly to the cosine-similarity floor a match must clear: floor = 0.87 − tolerance × (0.87 − 0.75).
At or above the floor you get a hit. Below it, the closest image is still served as approximate and the prompt is queued to generate (unless you opted out).
Give your agent cheap images
Paste this skill file into your coding agent — a Claude Code SKILL.md, a Cursor rule, or a system-prompt block — so it reaches for the shared cache before paying to generate.
The skill file
Save it as SKILL.md or drop it straight into your agent's instructions. It hands the agent the endpoint, the request shape, and — the part that matters — how to act on hit / approximate / pending.
---
name: wagmi-photos-images
description: Fetch images cheaply and instantly from the wagmi.photos shared cache before paying to generate. Use whenever a task needs an image and "close enough" beats pixel-perfect.
---
# wagmi.photos — cache-first images
Get an image in ~100 ms for $0 by matching the shared library first. Only pay a
generator when the prompt is genuinely new or must be exact.
## When to use this
- You need a stock-style or illustrative image and an approximate match is fine.
- You want to avoid generation cost and latency by default.
Do NOT rely on the cache when the image must match a hyper-specific prompt
exactly (brand assets, precise composition). Use a dedicated image model there.
## Endpoint
POST https://api.wagmi.photos/v1/images/generations
Authorization: Bearer sc-your-key
Content-Type: application/json
Body fields:
- prompt (string, required)
- cache_tolerance (0..1, default 0.15) lower = stricter match
- generate_on_miss (bool, default true) false = never spend GPU on a miss
## Call it
curl -X POST https://api.wagmi.photos/v1/images/generations \
-H "Authorization: Bearer $WAGMI_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt": "a vintage bicycle against a brick wall",
"cache_tolerance": 0.15,
"generate_on_miss": true}'
## Act on shared_cache.result
- "hit" (HTTP 200): use data[0].url. Free and instant, you are done.
- "approximate" (HTTP 200): a close image is in data[0].url. Use it only if it
fits the task; the exact prompt was queued for next time.
- "pending" (HTTP 202): nothing close yet, data is empty. Generate with
your own model if you need an image now. The prompt was queued
(unless you opted out), so retrying later will hit for $0.
## Rules for the agent
1. Default to the cache. Send generate_on_miss=false when you only want free,
instant results and a miss is acceptable.
2. Never treat "approximate" as exact — verify it matches the request.
3. On 202, do not block waiting. Proceed without an image or fall back to a real
generator, then retry the same prompt later for a cheap hit.
4. Reuse one wagmi.photos key. It is hashed server-side; keep it secret.
How the agent should behave
Default path — cheap & fast
- Ask the cache first for anything illustrative.
- Accept
approximatewhen it fits the task. - Set
generate_on_miss=falsefor throwaway previews.
When exact matters
- Lower
cache_tolerancetoward 0 for near-exact only. - Leave
generate_on_miss=trueso misses get built. - On
pending, fall back to a dedicated model.
Wire up a key
Keys are tied to your account. Log in with a magic link (email, no password), create a key on the Account page, then export it as WAGMI_KEY:
# 1. Log in at https://wagmi.photos/#/login (magic-link email) # 2. Account → Create API key → copy the sc-… key (shown once) export WAGMI_KEY=sc-…
Prefer the API? POST /v1/keys/generate also works with a logged-in session cookie — unauthenticated calls return 401. The full field reference lives in the API docs.
Legal & Usage Policy
Effective Date: July 1, 2026
1. Privacy Policy
What we store, and why:
- Your email address: Logging in works by magic link — you give us your email, we send you a sign-in link. We store that email server-side to operate your account. It is not sold or shared.
- Session cookie: After you open the login link, a session cookie keeps you logged in. It is HttpOnly and used only to authenticate you to your own account.
- API keys as hashes: API keys are shown to you exactly once, at creation. Server-side we store only a SHA-256 hash of each key — we cannot recover or display the key itself, so keep your copy safe.
- Prompts and images: This is a shared cache. Prompts you send are stored (with demand counts) to match requests and rank background generation, and generated images join the shared, openly licensed library. Do not put private or personal information in prompts.
- Local browser state: The playground's telemetry counters and session history live only in your browser and can be cleared any time from the Account page.
- Encrypted transit: All communication with wagmi.photos is encrypted via HTTPS.
2. Terms of Use & Data Licensing
By using wagmi.photos, you agree to comply with the terms of our backend caching logic and the licenses of our creative catalogs:
- Public Domain Data: wagmi.photos leverages the PD12M dataset from Spawning. This dataset is licensed under the CDLA-Permissive-2.0 agreement. You are permitted to copy, distribute, modify, and utilize all pre-seeded images for commercial or personal purposes without attribution.
- Fair Use: You agree not to abuse the cache endpoints through coordinated denial-of-service, scraping, or cache pollution. Misses are queued and generated in the background by the shared backend, ranked by demand; requests are rate-limited to keep that fair.