← StoreShots · Get a key / buy credits

StoreShots API

Base URL: https://storeshots.qaimos.co.uk/api.php. Every endpoint is ?action=<name>, and JSON responses use {"error": "…"} on failure.

Authentication

Send your key as X-API-Key: ss_… or Authorization: Bearer ss_…. Get a free key on the account page or via the API:

curl -X POST -d email=you@example.com "https://storeshots.qaimos.co.uk/api.php?action=signup"
# → 201 {"apiKey":"ss_…","keyPrefix":"ss_AbCdEfG","freeGenerationsPerMonth":3,"note":"Store this key now…"}

The key is shown once, and only its SHA-256 hash is stored. Each email address can hold one key.

Credits, free tier & limits

Generate screenshots

POST?action=generate (multipart/form-data)

FieldDescription
screenshots[]Required. 1–5 image files (PNG/JPEG/WebP, ≤10 MB each). One slide per file.
styleglow (default), midnight, sunset, mint, trailing
deviceiphone, iphone-duo, android, ipad. Omit to use each target's default.
targetsComma list or JSON array: ios-6.9 (1320×2868), ios-6.5 (1242×2688), android-phone (1080×1920), ipad-13 (2064×2752). Default: ios-6.9,ios-6.5,android-phone
headline[], caption[]Text per slide, in the same order as the screenshots
appNameUsed in file names
gradFrom, gradTo, bgColor, bgMode, headlineColor, captionColor, frameColor, textAlign, screenFitOptional theme overrides (hex colours; bgMode gradient|solid; screenFit auto|cover|contain)
payloadAlternatively, all of the above as one JSON string: {"style":"mint","targets":["android-phone"],"slides":[{"headline":"…","caption":"…"}],"theme":{…}}
curl -H "X-API-Key: $STORESHOTS_API_KEY" \
  -F style=midnight -F device=iphone -F targets=ios-6.9,ios-6.5 -F appName="Habit Loop" \
  -F "headline[]=Build habits that stick" -F "caption[]=One-tap daily check-ins" \
  -F "headline[]=See your progress"       -F "caption[]=Clear weekly insights" \
  -F "screenshots[]=@home.png" -F "screenshots[]=@stats.png" \
  "https://storeshots.qaimos.co.uk/api.php?action=generate"

Response 201:

{
  "jobId": "20260929-a1b2c3d4e5", "style": "midnight", "device": "iphone", "watermark": false, "billing": "credit",
  "targets": [{ "id": "ios-6.9", "size": "1320x2868", "device": "iphone",
                "files": [{ "path": "ios-6.9/habit-loop-01-1320x2868.png", "url": "…?action=file&id=…&path=…" }] }],
  "zip": "habit-loop-storeshots.zip",
  "links": { "self": "…?action=job&id=…", "zip": "…?action=zip&id=…" },
  "balance": { "credits": 41, "free": { "limit": 3, "used": 1, "remaining": 2 } },
  "warnings": []
}

Outputs are private to your key and are deleted after 24 hours. Download them with zip / file (send the same API key).

All endpoints

EndpointAuthDescription
GEThealthnoServer status and capabilities
POSTsignupnoemail (form or JSON) → new API key (shown once). 5 signups/hour per IP
GETpacksnoCredit packs, prices and free-tier size
GETbalancekeyCredits, free sets left, reset date and what the next call will cost
GETusagekeyLast 50 events (signup, generate, purchase)
POSTcheckoutkeypack (starter = 10 sets $3, pro = 20 sets $5) → {"checkoutUrl": "https://buy.stripe.com/…?client_reference_id=…"}. Open the Stripe payment link to pay; credits are added automatically by webhook
GETstyleskeyStyles with colours/layouts
GETdeviceskeyDevices and output targets
POSTgeneratekeySee above
GETjob&id=keyJob manifest
GETzip&id=keyZIP of all PNGs
GETfile&id=&path=keyA single PNG
POSTstripe-webhookStripe signatureInternal: Stripe calls this after payment

MCP server (Cursor, Claude, …)

{
  "mcpServers": {
    "storeshots": {
      "command": "npx",
      "args": ["-y", "storeshots-api-mcp"],
      "env": { "STORESHOTS_API_KEY": "ss_your_key" }
    }
  }
}

Tools: list_styles, list_devices, generate_screenshots (local paths or URLs, with optional auto-download), get_output, get_balance, buy_credits. Set STORESHOTS_API_URL to point at a self-hosted api.php.

Self-hosting

api.php runs on ordinary PHP 8.1+ hosting with GD/FreeType (php-zip for ZIPs). Credit packs use Stripe Payment Links plus a signed webhook, so no Stripe secret key or curl is needed. Deploy is flat: every file sits next to index.php, no folders. Accounts are kept in one JSON file (storeshots-data.json, auto-created, locked with flock(), written atomically), so no database or pdo_sqlite is needed. Job outputs go to the PHP temp dir (storeshots-jobs, auto-created) and are deleted after 24 hours. See DEPLOY.md for the exact upload list.

Errors

StatusMeaning
400Invalid input (message says which field)
401Missing, invalid or revoked API key
402Free tier used up and no credits left. Buy a pack
404Unknown action, or the job doesn't exist, has expired or isn't yours
409Email already registered
413File or request too large
429Rate limited. See Retry-After
503Feature not configured on this server (e.g. payments)