# StoreShot: store-ready screenshots from an API call, or just tell your agent

> HTML version: https://storeshot.art/

StoreShot turns raw app screenshots into App Store and Google Play marketing images at exactly the
sizes the stores require. Use the REST API (`https://api.storeshot.art/v1`), let an AI coding agent drive it, manage
keys and billing in the developer console, or use the iOS and Android apps.

- Get an API key: https://console.storeshot.art/ (4 free credits on your first key, test keys are free)
- API overview: https://storeshot.art/developers.md
- Use it from an AI agent: https://storeshot.art/agents.md
- Pricing: https://storeshot.art/pricing.md
- Docs hub: https://storeshot.art/docs/index.md
- Mobile apps: https://storeshot.art/app/ (App Store: https://apps.apple.com/app/id6783987939, Google Play: https://play.google.com/store/apps/details?id=com.draggable.storeshot)

## How it works

1. Upload the raw screenshots you already have (`POST /uploads`).
2. Generate one image (`POST /generations`) or a whole listing (`POST /screenshot-sets`).
3. Download the PNGs or a ZIP in fastlane folders, or receive a signed webhook.

## Quickstart

### curl

```sh
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

```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

```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"))
```
