Guides

Screenshot generation

Create store screenshots from your App profile: choose a size and design, review the captions, then generate and download the PNGs. Follow the job ID returned by each generation request to get its result.

1. Create an App profile

Add your app details or import a published store listing. Use the appId from the response in your later requests.

Check the profile's source screenshots in Studio before rendering. Store listings may contain finished marketing images with captions or device frames; importing them does not turn them into clean app captures. Upload clean captures in the App profile when needed to avoid placing an existing frame inside another frame. Use the source upload API to add clean captures and retain their opaque IDs.

All fields and values: API reference → Create an App profile

Request
curl -s -X POST "https://api.applistinglab.com/api/v1/developer/apps" \
  -H "Authorization: Bearer $APP_LISTING_LAB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Your App","description":"What your app does and who it is for.","category":"Productivity"}'
201 Created
{
  "appId": "665f0a2b9c1e4d0012ab34cd",
  "name": "Your App",
  "category": "Productivity",
  "artworkUrl": "",
  "iosUrl": null,
  "androidUrl": null,
  "importedFrom": []
}

2. Pick a device

device takes one of the targets listed below. Its maxScreenshots caps count. The same list is returned by GET /developer/screenshots/devices, so a client must read it at runtime. Studio offers additional editable/export sizes that are not necessarily Developer API targets. Duo targets require a capture from the matching outer or inner display, with measured dimensions in the App profile. Choose source screens from the matching store, phone/tablet family and orientation; incompatible sources are rejected. Duo PNG generation does not imply automatic store publishing. The legacy android-tablet target remains 1280 × 800; the new 10-inch targets are separate IDs.

All fields and values: API reference → Discover screenshot sizes

devicestorewidth × heightmaxScreenshotsOrientation
iphone-69apple1320 × 286810Portrait
iphone-67apple1290 × 279610Portrait
iphone-65apple1242 × 268810Portrait
ipad-proapple2048 × 273210Portrait
android-phonegoogle1080 × 19208Portrait
android-tabletgoogle1280 × 8008Landscape
iphone-duo-outerapple1398 × 203410Portrait
iphone-duo-innerapple2007 × 285310Portrait
android-phone-landscapegoogle1920 × 10808Landscape
android-phone-tallgoogle1080 × 21608Portrait
android-tablet-10-portraitgoogle1440 × 25608Portrait
android-tablet-10-landscapegoogle2560 × 14408Landscape

These are supported API export sizes, not a checklist of required store slots. Check the current Apple screenshot specifications and Google Play screenshot requirements before submission.

Duo sizes are PNG export canvases. AppListingLab does not currently map them to an App Store Connect upload slot. Generating a screenshot does not publish it to a store.

Request
curl -s "https://api.applistinglab.com/api/v1/developer/screenshots/devices" \
  -H "Authorization: Bearer $APP_LISTING_LAB_API_KEY"
200 OK (excerpt: one target)
[
  {
    "device": "iphone-69",
    "store": "apple",
    "width": 1320,
    "height": 2868,
    "maxScreenshots": 10
  }
]

3. Suggest captions, or bring your own

Caption suggestions are text only and do not render or upload images. Skip this step when you or your agent already wrote the copy: a title up to 100 characters and an optional subtitle up to 160 per screenshot. Use [[highlighted words]] inside title to request emphasis where the selected design has an accent style; the brackets are not printed and count toward the length limit. Optional captionStyle (default aso-expert) and captionLength (short or long) steer the writing; see the API reference.

Create and persist a separate idempotency key for each paid stage before sending it. Keep that value for retries; do not generate a new key on a retry. The request is accepted at once. The response carries the jobId to poll, its quoted credit cost and the projected spendable balance. The numbers below are illustrative, not a pricing formula.

All fields and values: API reference → Suggest captions

Initialize once per new workflow; retain for retries
export CAPTIONS_KEY="captions-$(uuidgen)"
export RENDER_KEY="render-$(uuidgen)"
Request
curl -s -X POST "https://api.applistinglab.com/api/v1/developer/screenshots/captions" \
  -H "Authorization: Bearer $APP_LISTING_LAB_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $CAPTIONS_KEY" \
  -d '{ "appId": "665f0a2b9c1e4d0012ab34cd", "device": "iphone-67", "count": 2 }'
201 Created
{
  "jobId": "66a1f0c2b7e4d90012cd5678",
  "credits": { "cost": 5, "remaining": 195 }
}

4. Poll the operation

Poll every few seconds with the jobId until status is done or error. pending also covers time waiting for capacity, so keep polling rather than resubmitting. A finished caption job returns the editable captions array.

All fields and values: API reference → Retrieve an operation

Request
curl -s "https://api.applistinglab.com/api/v1/developer/jobs/66a1f0c2b7e4d90012cd5678" \
  -H "Authorization: Bearer $APP_LISTING_LAB_API_KEY"
200 OK, while waiting
{
  "id": "66a1f0c2b7e4d90012cd5678",
  "status": "pending",
  "result": null,
  "error": null
}
200 OK, when finished
{
  "id": "66a1f0c2b7e4d90012cd5678",
  "status": "done",
  "result": {
    "kind": "screenshot-captions",
    "appId": "665f0a2b9c1e4d0012ab34cd",
    "device": "iphone-67",
    "count": 2,
    "captions": [
      { "title": "Plan meals in minutes", "subtitle": "Weekly menus that fit your diet" },
      { "title": "Shop smarter", "subtitle": "One list for every store" }
    ]
  },
  "error": null
}

Optional: discover or select a design

The backend automatically recommends a compatible design. To choose explicitly, read GET /developer/screenshots/designs and use its designId and optional designVersion. Versions are opaque content revisions; discover them rather than inventing a number.

POST /developer/screenshots/prepare accepts the normal render body and returns { design, device, count } without charging, rendering or calling an AI provider. This step is optional and does not reserve credits or capacity or verify remote image bytes.

All fields and values: API reference → Screenshot designs

5. Render the approved copy

Edit the captions if needed and send exactly count of them in display order. Supplied copy is rendered as written, without AI text planning. Omit captions to plan and render in one operation instead. Changing the copy starts a new, separately charged render. Poll the new jobId as in step 4.

For exact source/copy ordering, use the frames workflow: each frame binds a sourceId to its title and subtitle. Do not send both frames and captions. Pin the current design revision when repeating a release workflow.

All fields and values: API reference → Render screenshots

Request
curl -s -X POST "https://api.applistinglab.com/api/v1/developer/screenshots" \
  -H "Authorization: Bearer $APP_LISTING_LAB_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $RENDER_KEY" \
  -d '{
    "appId": "665f0a2b9c1e4d0012ab34cd",
    "device": "iphone-67",
    "count": 2,
    "captions": [
      { "title": "Plan meals in minutes", "subtitle": "Weekly menus that fit your diet" },
      { "title": "Shop smarter" }
    ]
  }'
201 Created
{
  "jobId": "66a1f3e0b7e4d90012cd9abc",
  "credits": { "cost": 4, "remaining": 191 }
}
GET /developer/jobs/66a1f3e0b7e4d90012cd9abc, when finished
{
  "id": "66a1f3e0b7e4d90012cd9abc",
  "status": "done",
  "result": {
    "kind": "screenshot-set",
    "device": "iphone-67",
    "screenshots": [
      {
        "artifactId": "66a1f41fb7e4d90012cdaa01",
        "index": 0,
        "device": "iphone-67",
        "width": 1290,
        "height": 2796,
        "format": "png",
        "fileName": "screenshot-1-1290x2796.png",
        "downloadExpiresAt": "2026-10-16T12:00:00.000Z",
        "downloadUrl": "https://api.applistinglab.com/api/v1/developer/artifacts/66a1f41fb7e4d90012cdaa01/file"
      },
      {
        "artifactId": "66a1f41fb7e4d90012cdaa02",
        "index": 1,
        "device": "iphone-67",
        "width": 1290,
        "height": 2796,
        "format": "png",
        "fileName": "screenshot-2-1290x2796.png",
        "downloadExpiresAt": "2026-10-16T12:00:00.000Z",
        "downloadUrl": "https://api.applistinglab.com/api/v1/developer/artifacts/66a1f41fb7e4d90012cdaa02/file"
      }
    ]
  },
  "error": null
}

6. Download the PNGs

Fetch each downloadUrl with a valid generate-scoped API key belonging to the same account before its downloadExpiresAt. The response is the PNG itself.

Free-plan screenshot downloads include a small “Made with applistinglab.com” mark, just like exports from Studio. The response includes X-AppListingLab-Watermark: free-plan. Paid plans download screenshots without the mark. After upgrading, download again using the same downloadUrl while it is still valid to get an unmarked copy.

All fields and values: API reference → Download a screenshot

Request
curl -s -o screenshot-1-1290x2796.png \
  "https://api.applistinglab.com/api/v1/developer/artifacts/66a1f41fb7e4d90012cdaa01/file" \
  -H "Authorization: Bearer $APP_LISTING_LAB_API_KEY"
200 OK
Content-Type: image/png
Content-Disposition: attachment; filename="applistinglab-screenshot-66a1f41fb7e4d90012cdaa01.png"

<PNG bytes>

If something goes wrong

A finished job with status: "error" carries a safe message in error. Confirmed execution failures are compensated; if the message says the outcome needs review, contact support with the job ID before submitting again. Requests can also be refused before any charge:

  • 402: not enough credits, counting work already waiting.
  • 409: the same Idempotency-Key with a different body.
  • 429: an account or key limit; wait for Retry-After.
  • 503: generation is paused or its queue is full; retry after Retry-After.

All fields and values: API reference → Refusals worth handling

Retries and charges

Send an Idempotency-Key with each paid submission, a separate one per stage. Retrying with the same key and unchanged body returns the original jobId without another charge. Credits are charged when processing starts, not while a job waits.

Full field reference
Every request field, result shape and refusal is in the API reference.