# Test mode

> HTML version: https://storeshot.art/docs/test-mode/

A test key (`ss_test_…`) runs the whole API exactly like a live key (validation, uploads, the
queue, statuses, idempotency, signed result URLs, screenshot sets, archives and webhooks) but
never spends credits and never runs an image model. Every generation returns a sample image of
exactly the requested size, so your code, your file handling and your fastlane setup can be
finished before you pay for anything.

## What is different

| | Test key (`ss_test_…`) | Live key (`ss_live_…`) |
|---|---|---|
| Credits | never charged (`creditsCharged: 0`) | 1 per image |
| Result image | a sample image of exactly the requested size | your generated marketing image |
| Caption | yours, or `Sample caption (test mode)` when you send none | yours, or written from the screenshot |
| Generation caps | not counted (in progress, per UTC day) | counted (see [Rate limits](/docs/rate-limits/)) |
| Screenshot sets in progress | at most 3 at once | count as one generation each |
| Results kept | deleted 30 days after they finish | until you delete them |
| Usage reports | not counted in `GET /usage` | counted |
| Requests per minute | counted like live keys | counted |

The two environments are separate: a test key sees and uses only test uploads, generations, sets
and webhooks, and a live key only live ones. Using a test upload with a live key (or the other way
round) is `400 INVALID_INPUT`.

## Try it

Upload a screenshot, then ask for a Google Play phone image by size instead of a device id. The
answer is the finished generation (test generations take a second or two), and the sample image
has exactly the size you asked for.

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

GENERATION=$(curl -sS https://api.storeshot.art/v1/generations \
  -H "Authorization: Bearer $STORESHOT_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: test-mode-try-1' -H 'Prefer: wait=60' \
  -d '{"inputs":[{"uploadId":"'"$UPLOAD"'"}],"store":"google_play",
       "size":{"width":1080,"height":1920},"app":{"name":"Trailmate"}}')
echo "$GENERATION" | jq '{status, environment, creditsCharged, caption: .result.caption,
  size: {width: .result.image.width, height: .result.image.height}}'

# Download the sample image (the URL is signed for 15 minutes)
curl -sS -o sample.png "$(echo "$GENERATION" | jq -r .result.image.url)"
```

## Going live

1. Create a key with the **Live** environment in the console and use it instead of the test key.
   Uploads, generations and webhooks of the test environment stay where they are; create them
   again with the live key.
2. Make sure the account has credits: `GET /credits`. Your first API key brings 4 free credits;
   plans and packs are on the [pricing page](/pricing/). Without enough credits a generation or set
   answers `402 INSUFFICIENT_CREDITS` and nothing is created or charged.
3. Quote screenshot sets with `?dryRun=true` before you create them
   ([Screenshot sets](/docs/screenshot-sets/#quote-first)).
