Developers

The StoreShot REST API

JSON over HTTPS at https://api.storeshot.art/v1, described by an OpenAPI 3.1 document. Every response carries an X-Request-Id; every error has the same shape.

Quickstart

  1. Sign in to the developer console and create a test key.
  2. Upload a raw screenshot with POST /uploads.
  3. Create a generation with POST /generations and Prefer: wait=60, or poll GET /generations/{id} every few seconds.
  4. Download result.image.url (signed for 15 minutes).

curl

export STORESHOT_API_KEY=ss_test_…   # free while you integrate

# 1. Upload a raw screenshot
UPLOAD=$(curl -sS -H "Authorization: Bearer $STORESHOT_API_KEY" \
  -F file=@home.png https://api.storeshot.art/v1/uploads | jq -r .id)

# 2. Generate a 1290×2796 App Store image (waits up to 60 s)
curl -sS https://api.storeshot.art/v1/generations \
  -H "Authorization: Bearer $STORESHOT_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: home-en-1' -H 'Prefer: wait=60' \
  -d '{"inputs":[{"uploadId":"'$UPLOAD'"}],"store":"app_store",
       "device":"app_store_1290x2796","app":{"name":"Trailmate"}}' \
  | jq '{status, url: .result.image.url}'

Node.js

import { readFile } from 'node:fs/promises';

const api = 'https://api.storeshot.art/v1';
const headers = { Authorization: `Bearer ${process.env.STORESHOT_API_KEY}` };

const form = new FormData();
form.append('file', new Blob([await readFile('home.png')]), 'home.png');
const upload = await (await fetch(`${api}/uploads`, { method: 'POST', headers, body: form })).json();

const res = await fetch(`${api}/generations`, {
  method: 'POST',
  headers: { ...headers, 'Content-Type': 'application/json',
    'Idempotency-Key': 'home-en-1', Prefer: 'wait=60' },
  body: JSON.stringify({
    inputs: [{ uploadId: upload.id }],
    store: 'app_store',
    device: 'app_store_1290x2796',
    app: { name: 'Trailmate' },
  }),
});
const generation = await res.json();
console.log(generation.status, generation.result?.image.url);

Python

import os, requests

api = "https://api.storeshot.art/v1"
h = {"Authorization": f"Bearer {os.environ['STORESHOT_API_KEY']}"}

upload = requests.post(f"{api}/uploads", headers=h,
                       files={"file": open("home.png", "rb")}).json()

generation = requests.post(
    f"{api}/generations",
    headers={**h, "Idempotency-Key": "home-en-1", "Prefer": "wait=60"},
    json={"inputs": [{"uploadId": upload["id"]}], "store": "app_store",
          "device": "app_store_1290x2796", "app": {"name": "Trailmate"}},
).json()
print(generation["status"], (generation["result"] or {}).get("image", {}).get("url"))

Authentication and test mode

Send your key as Authorization: Bearer ss_live_…. Keys are created and revoked in the console (or with POST /api-keys), are shown once, and are stored only as a hash.

Main endpoints

Paths are relative to https://api.storeshot.art/v1. The reference lists every operation, field and scope.

Generations

One screenshot in, one store-ready image out, at exactly the size the store requires.

  • POST /generations Create a generation
  • GET /generations/{id} Get a generation
  • GET /generations List generations
  • POST /generations/{id}/cancel Cancel a generation

Screenshot sets

A whole listing in one call: 1–10 screens on every device of one or both stores, plus an optional feature graphic, as a ZIP (Fastlane layout available).

  • POST /screenshot-sets Create a set (?dryRun=true quotes it)
  • GET /screenshot-sets/{id} Get a screenshot set
  • POST /screenshot-sets/{id}/retry Retry failed images
  • GET /screenshot-sets/{id}/archive Download as a ZIP

Uploads

PNG, JPEG or WebP up to 20 MiB, as multipart, from a URL, or with a presigned upload.

  • POST /uploads Upload an image
  • POST /uploads/presign Start a presigned upload
  • GET /uploads/{id} Get an upload
  • DELETE /uploads/{id} Delete an upload

Store helpers

Official screenshot sizes and rules per store, and brand palettes from a screenshot.

  • GET /devices List store screenshot sizes
  • GET /stores/{store}/requirements Store screenshot requirements
  • POST /palettes Extract a brand palette

Webhooks

Signed generation.succeeded, generation.failed, screenshot_set.completed and credits.low events.

  • POST /webhooks Create a webhook
  • POST /webhooks/{id}/test Send a test event
  • GET /webhooks/{id}/deliveries List deliveries

Account and billing

Keys, credit balance, usage, credit packs and monthly plans.

  • GET /me Who am I
  • POST /api-keys Create an API key
  • GET /credits Credit balance
  • GET /usage Generation usage
  • GET /billing/packs List credit packs
  • GET /billing/plans List plans

Credits, limits and errors

Machine-readable: OpenAPI JSON · llms.txt · this page as Markdown.

Start with a free test key.

Sample images at the exact store sizes, no credits spent, the same API as live.