Credits and billing
What a generation costs, refunds, the free trial credits, checking your balance and usage, and the plans and credit packs.
Live API keys (ss_live_…) spend credits; test keys (ss_test_…) never do
(Test mode).
What things cost
| What | Credits |
|---|---|
| One generation (one image) with a live key | 1 |
| A screenshot set with a live key | 1 per image (screens × devices, plus the feature graphic) |
| Anything with a test key | 0 |
| Uploads, palettes, store requirements, webhooks, reads | 0 |
Your first API key comes with 4 free credits for live images (once per account).
- A credit is charged when the generation or set is created (
creditsCharged), all at once for a set: without enough credits the request is402 INSUFFICIENT_CREDITS(details.requiredCredits,details.availableCredits,details.topUpUrl) and nothing is created. - Quote a set first with
POST /screenshot-sets?dryRun=true: it answerscreditsand whether your balance issufficient, and charges nothing. - A generation that fails, or that you cancel before it starts, is refunded automatically
(
creditsRefunded). Retrying failed images of a set charges only the images it retries. - Credits are spent from your monthly plan first, then from trial credits, then from purchased packs. Plan credits reset every month (they do not roll over); purchased credits do not expire.
Check the balance and usage
GET /credits and GET /usage need the usage:read scope. Usage covers live generations of the
whole account (every key and surface) per UTC day, per API key (groupBy=key) or per source
(groupBy=source), for a range of up to 366 days (from inclusive, to exclusive, YYYY-MM-DD).
curl
curl -sS https://api.storeshot.art/v1/credits \
-H "Authorization: Bearer $STORESHOT_API_KEY" | jq .
curl -sS 'https://api.storeshot.art/v1/usage?from=2026-10-01&to=2026-11-01&groupBy=key' \
-H "Authorization: Bearer $STORESHOT_API_KEY" \
| jq -r '.data[] | "\(.key) generations=\(.generations) credits=\(.creditsUsed)"'Node.js
const api = 'https://api.storeshot.art/v1';
const headers = { Authorization: `Bearer ${process.env.STORESHOT_API_KEY}` };
const credits = await (await fetch(`${api}/credits`, { headers })).json();
console.log('credits left:', credits.total, credits.balances);
const usage = await (
await fetch(`${api}/usage?from=2026-10-01&to=2026-11-01&groupBy=source`, { headers })
).json();
for (const bucket of usage.data) console.log(bucket.key, bucket.generations, bucket.creditsUsed);Python
import os, requests
api = "https://api.storeshot.art/v1"
headers = {"Authorization": f"Bearer {os.environ['STORESHOT_API_KEY']}"}
credits = requests.get(f"{api}/credits", headers=headers).json()
print("credits left:", credits["total"], credits["balances"])
usage = requests.get(
f"{api}/usage", headers=headers, params={"from": "2026-10-01", "to": "2026-11-01"}
).json()
for day in usage["data"]:
if day["generations"]:
print(day["key"], day["generations"], day["creditsUsed"])A webhook with the credits.low event tells you when a charge takes the live
balance below a threshold you choose.
Monthly plans
| Plan | Price | Credits / month | Per credit | Requests / min (key · account) | Concurrent | Daily credits |
|---|---|---|---|---|---|---|
| Pro | $12 / month | 60 | $0.20 | 120 · 240 | 4 | 200 |
| Agency | $29 / month | 150 | $0.19 | 120 · 240 | 6 | 500 |
| Scale | $79 / month | 430 | $0.18 | 300 · 600 | 10 | 1000 |
| No plan | $0 | packs only | — | 60 · 120 | 3 | 100 |
Credit packs
| Pack | Price | Per credit |
|---|---|---|
| 15 credits | $3.99 | $0.27 |
| 50 credits | $11.99 | $0.24 |
Buy a plan or a pack in the developer console; the
pricing page compares them. Checkouts through the API (POST /billing/checkout) need
a live key with billing:write or a console session; test keys never buy.