Reference

API reference

Use the Developer API to work with your App profiles and automate listing tasks. Find request fields, response formats and examples for each supported endpoint below.

Base URL: https://api.applistinglab.com/api/v1. Send your API key on every request — see Authentication. The OpenAPI specification is available at https://api.applistinglab.com/api/v1/developer/openapi.json. Existing /api/v1/public/v1 URLs remain compatibility aliases with the same API-key authentication. New integrations should use /api/v1/developer.

List App profiles

Returns the App profiles your account owns, most recently updated first, with their store links. Check this before importing: every successful import creates another profile. A locked profile is over your plan's open-project limit and refuses work with 402 until you delete a project or upgrade.

GET/developer/apps
200
[
  {
    "appId": "665f0a2b9c1e4d0012ab34cd",
    "name": "Your App",
    "category": "Productivity",
    "artworkUrl": "https://…/icon.png",
    "iosUrl": "https://apps.apple.com/us/app/your-app/id1234567890",
    "androidUrl": null,
    "locked": false
  }
]

Create an App profile

Creates an App profile from your app's own details and returns an opaque appId. Send name and description — the main way in, and the only one for an app that is not released yet. For an app already in a store you can add its links to pull in the listing as a convenience; the fields you send always take priority. With name, an unreadable listing simply falls back to your details, and importedFrom lists the stores that were read. A link sent without name must open a published listing, otherwise 422 STORE_LISTING_UNAVAILABLE names the store and nothing is created. A malformed link returns 400 with the field's message.

POST/developer/apps
FieldTypeDescription
namestringThe app's name, max 100 characters. Required unless a store link is sent; always takes priority over the store's name.
descriptionstringWhat the app does and who it is for, in your words. Captions and ASO text are written from it; takes priority over the store description.
categorystringStore category, e.g. Health & Fitness.
iosUrlstringOptional, for an app already on the App Store: a link containing the app id, e.g. https://apps.apple.com/us/app/name/id1234567890. Keep the country path for an app not sold in the US.
androidUrlstringOptional, for an app already on Google Play: https://play.google.com/store/apps/details?id=<package>.
extraContextstringOptional context for the App profile, max 2000 characters.
cURL
curl -s 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
{
  "appId": "665f0a2b9c1e4d0012ab34cd",
  "name": "Your App",
  "category": "Productivity",
  "artworkUrl": "",
  "iosUrl": null,
  "androidUrl": null,
  "importedFrom": []
}

Read an App profile

Retrieve the imported profile summary using its appId. The response has the same fields as creation and is limited to your account. Invalid identifiers return 400; unavailable profiles return an error rather than revealing another account's data.

GET/developer/apps/{id}
cURL
curl -s "https://api.applistinglab.com/api/v1/developer/apps/$APP_ID" \
  -H "Authorization: Bearer $APP_LISTING_LAB_API_KEY"

Discover screenshot sizes

Returns the supported device identifiers, store, pixel dimensions and maximum number of screenshots per set. Use these identifiers for the screenshot routes below. These read endpoints require the same generate key scope as App profile creation.

GET/developer/screenshots/devices
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.

Response entry (read the full target array at runtime)
{
  "device": "iphone-67",
  "store": "apple",
  "width": 1290,
  "height": 2796,
  "maxScreenshots": 10
}

Owned source screenshots

Upload a sanitized PNG/JPEG/WebP capture with platform and dataUrl, then list opaque source IDs and measured dimensions. Source upload is distinct from paid rendering. See Sources & frame order for limits and Node.js input.

POST/developer/apps/{id}/screenshots
GET/developer/apps/{id}/screenshots

Feature graphic

Send appId, discovered designId/designVersion, one or two owned Android sourceIds, headline, optional subtitle and altText. A finished job returns kind feature-graphic and one artifact. See Feature graphics for field limits and the 1024 × 500 output format.

POST/developer/feature-graphics

Google Play publishing

Requires a publish-scoped key and an eligible connected App profile. Create an immutable session, stage the complete manifest, start once, then poll the dedicated session and read back text. Publishing & verification documents all required fields, review policy, image slots and recovery.

POST/developer/publishing/google/sessions
POST/developer/publishing/sessions/{id}/artifacts
POST/developer/publishing/sessions/{id}/icon
GET/developer/publishing/google/apps/{id}/icon
POST/developer/publishing/sessions/{id}/start
GET/developer/publishing/sessions/{id}
GET/developer/publishing/google/apps/{id}/listing

Suggest captions

Plans editable screenshot copy for an owned App profile without rendering images. The finished job returns one title/subtitle pair per screenshot to review before rendering.

POST/developer/screenshots/captions
FieldTypeDescription
appIdrequiredstringApp id returned by POST /developer/apps.
devicerequiredstringTarget size: iphone-69 | iphone-67 | iphone-65 | ipad-pro | android-phone | android-tablet | iphone-duo-outer | iphone-duo-inner | android-phone-landscape | android-phone-tall | android-tablet-10-portrait | android-tablet-10-landscape. See GET /developer/screenshots/devices.
countrequiredintegerScreenshots in the set, 1 up to the device's maxScreenshots (10 for Apple, 8 for Google Play).
captionStylestringWriting style, default aso-expert: aso-expert | search-intent | outcome | emoji | direct | friendly | inspire | persuasive.
captionLengthstringshort (default) or long.
Idempotency-KeyheaderOptional but recommended for safe retries. Create and persist a new value once per paid stage, before the first submission. 16–128 characters of letters, digits, '.', '_', ':' or '-'. Reuse it with the unchanged body to recover the original operation without another charge; a different body under the same key returns 409.
cURL
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": "'"$APP_ID"'", "device": "iphone-67", "count": 5 }'
201
{
  "jobId": "66a1f0c2b7e4d90012cd5678",
  "credits": { "cost": 5, "remaining": 195 }
}

Render screenshots

Produces finished store PNGs. Send captions to render your own or reviewed copy and skip AI text planning; omit them to plan and render in one operation.

POST/developer/screenshots
FieldTypeDescription
appIdrequiredstringApp id returned by POST /developer/apps.
devicerequiredstringiphone-69 | iphone-67 | iphone-65 | ipad-pro | android-phone | android-tablet | iphone-duo-outer | iphone-duo-inner | android-phone-landscape | android-phone-tall | android-tablet-10-portrait | android-tablet-10-landscape
countintegerRequired unless frames supplies the count. When both are sent, the values must match.
framesarrayOrdered sourceId/title/subtitle bindings. The count is derived from this array. Cannot be combined with captions; see Sources & frame order.
captionsarrayExactly count entries in display order, each { "title": string ≤ 100, "subtitle"?: string ≤ 160 }. A title must contain visible text; an empty subtitle means none.
captionStylestringUsed only when captions are omitted. Same values as for suggestions.
captionLengthstringUsed only when captions are omitted: short or long.
designIdstringOptional public identifier from GET /developer/screenshots/designs; omitted means automatic recommendation.
designVersionintegerOptional opaque positive safe integer returned with designId. Requires designId; pins that current revision.
Idempotency-KeyheaderOptional but recommended for safe retries. Create and persist a new value once per paid stage, before the first submission. 16–128 characters of letters, digits, '.', '_', ':' or '-'. Reuse it with the unchanged body to recover the original operation without another charge; a different body under the same key returns 409.
cURL
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": "'"$APP_ID"'",
    "device": "iphone-67",
    "count": 2,
    "captions": [
      { "title": "Plan meals in minutes", "subtitle": "Weekly menus that fit your diet" },
      { "title": "Shop smarter" }
    ]
  }'

Screenshot designs

GET /developer/screenshots/designs returns public IDs/current revisions, names, category/theme/features, supported device/count limits, text fields and illustrative raster previewUrls. It exposes no editor geometry. Always use returned values.

POST /developer/screenshots/prepare accepts the same body as rendering and returns { design, device, count }. It validates the owned profile and stored source compatibility without charging, AI calls, rendering or storage writes. It is optional, reserves nothing and does not verify remote bytes.

An unavailable design/revision returns 422 DESIGN_UNAVAILABLE; an incompatible device/count returns 422 DESIGN_INCOMPATIBLE, before charging. Accepted jobs pin the chosen revision; a retry recovers the original operation.

GET/developer/screenshots/designs
POST/developer/screenshots/prepare

Download a screenshot

Each finished screenshot carries a downloadUrl pointing here. Download it with your account’s API key and the generate scope before downloadExpiresAt. Downloads have their own per-account rate and concurrency limits.

On the Free plan screenshots download with a “Made with applistinglab.com” mark and the header X-AppListingLab-Watermark: free-plan; paid plans and feature graphics download without the mark. After upgrading, download the screenshot again before its link expires to get an unmarked copy.

GET/developer/artifacts/{id}/file
cURL
curl -s -o screenshot-1.png "$DOWNLOAD_URL" \
  -H "Authorization: Bearer $APP_LISTING_LAB_API_KEY"

Generate a store listing

Writes the final en-US listing fields for one store from an owned App profile. The listing is also saved to the App profile in Studio.

POST/developer/aso
FieldTypeDescription
appIdrequiredstringOwned App profile identifier.
storerequiredstringapple or google.
campaignFocusstringOptional focus for this listing, up to 1000 characters.
Idempotency-KeyheaderOptional but recommended for safe retries. Create and persist a new value once per paid stage, before the first submission. 16–128 characters of letters, digits, '.', '_', ':' or '-'. Reuse it with the unchanged body to recover the original operation without another charge; a different body under the same key returns 409.
cURL
curl -s -X POST "https://api.applistinglab.com/api/v1/developer/aso" \
  -H "Authorization: Bearer $APP_LISTING_LAB_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $ASO_KEY" \
  -d '{ "appId": "'"$APP_ID"'", "store": "apple" }'

Localize a store listing

Translates a completed en-US listing job into up to ten markets. Each target locale is charged as its own unit.

POST/developer/aso/localize
FieldTypeDescription
jobIdrequiredstringA finished POST /developer/aso job.
targetLocalesrequiredstring[]1–10 unique store locales other than en-US, for example de-DE, fr-FR, ja, pt-BR. The full supported list is the targetLocales item enum in this environment’s OpenAPI spec.
Idempotency-KeyheaderOptional but recommended for safe retries. Create and persist a new value once per paid stage, before the first submission. 16–128 characters of letters, digits, '.', '_', ':' or '-'. Reuse it with the unchanged body to recover the original operation without another charge; a different body under the same key returns 409.
cURL
curl -s -X POST "https://api.applistinglab.com/api/v1/developer/aso/localize" \
  -H "Authorization: Bearer $APP_LISTING_LAB_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $LOCALIZE_KEY" \
  -d '{ "jobId": "'"$ASO_JOB_ID"'", "targetLocales": ["de-DE", "ja"] }'

Retrieve an operation

Generation runs asynchronously: a submission answers with a jobId at once, and you poll this route every few seconds until status is done or error. pending covers accepted work that has not started yet, including time spent waiting for capacity; keep polling. Credits are charged when processing starts. Confirmed execution failures are compensated; an uncertain outcome may require support review before another submission.

GET/developer/jobs/{id}
FieldTypeDescription
idstringThe operation identifier.
statusstringpending, running, done or error.
resultobject | nullThe final output when status is done; its kind field names the shape below.
errorstring | nullA safe, human-readable failure message when status is error.
cURL
curl -s "https://api.applistinglab.com/api/v1/developer/jobs/$JOB_ID" \
  -H "Authorization: Bearer $APP_LISTING_LAB_API_KEY"
done: screenshot-captions
{
  "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
}
done: screenshot-set
{
  "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"
      }
    ]
  },
  "error": null
}
done: aso-listing (apple)
{
  "id": "66a1f5d1b7e4d90012cdbb02",
  "status": "done",
  "result": {
    "kind": "aso-listing",
    "listingId": "66a1f5e9b7e4d90012cdbb10",
    "appId": "665f0a2b9c1e4d0012ab34cd",
    "locale": "en-US",
    "store": "apple",
    "fields": {
      "name": "…",
      "subtitle": "…",
      "promotionalText": "…",
      "keywords": "…",
      "description": "…"
    }
  },
  "error": null
}

For google the fields are title, shortDescription and fullDescription. A localization finishes as aso-localization with sourceJobId and a listings array of listings in the same shape, one per target locale.

Refusals worth handling

  • 402: the account cannot pay for the request, counting work it already has waiting. Nothing is charged.
  • 409: the same Idempotency-Key with a different body, or an original submission still being confirmed. For an in-progress submission, retry with the original key and body. For a body mismatch, restore the original body to recover it, or use a new key only if you intend a new paid operation.
  • 429: a per-account or per-key limit, including the number of waiting operations and hourly/daily generation allowances. Honour Retry-After.
  • 503: generation is paused or its queue is full. No credits are charged; retry after Retry-After.
OpenAPI specification
Generate stable SDKs and agent tooling from https://api.applistinglab.com/api/v1/developer/openapi.json. Use the specification to check required fields and response formats when building your integration.