docs · api

Programmatic renders.

POST your screens, poll the job, download the zip. The API is HTTPS-only, authenticated with an X-API-Key header, and limited to Pro accounts. Free of vendor SDKs — anything that speaks HTTP works.

Quick start

1. Generate a key at /account/keys. Copy the ask_live_… string — you only see it once.

2. POST your PNGs as multipart/form-data:

curl https://api.appscreen.co/v1/render \
  -H "X-API-Key: $APPSCREEN_KEY" \
  -F 'theme=paper' \
  -F 'sizes=["ios-6.9"]' \
  -F 'langs=["en"]' \
  -F 'captions=[{"texts":{"Headline":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"Find people who share your taste."}]}]}}}]' \
  -F 'fields=[{"id":"Headline","label":"Headline"}]' \
  -F 'screens=@./shot1.png' \
  -F 'screens=@./shot2.png'

3. Poll the returned jobId until status === "done":

curl https://api.appscreen.co/v1/render/$JOB \
  -H "X-API-Key: $APPSCREEN_KEY"

4. GET the downloadUrl within 1 hour of the poll response — it's an HMAC-signed link served by AppScreen directly.

Authentication

Send your key as X-API-Key, or as Authorization: Bearer ask_live_… if your client only supports Bearer. Keys are per-account, never scoped to a single project.

Lost a key? Revoke it from /account/keys and create a new one. Revocation is immediate.

POST /v1/render

multipart/form-data with the following fields:

screensfile[]PNG screenshots, max 200 files × 10 MB.
themestringflat | paper | frame | card | glass | mesh | image
sizesjson stringJSON array, e.g. '["ios-6.9","play"]'. Allowed: ios-6.9, ios-6.7, ios-6.5, play.
langsjson stringJSON array of locale codes, e.g. '["en","de","tr"]'. Up to 15.
captionsjson stringPer-screen caption objects. See the captions schema below.
fieldsjson stringOptional caption field defs (id, label).
layoutstringdefault | fastlane | flutter | react-native | capacitor | kmm
roundedbooleanMarketing-asset mode (rounded canvas, alpha). Cannot combine with fastlane layouts.

Returns 202 Accepted with a job id:

{
  "jobId": "8c1c…-uuid",
  "status": "queued",
  "totalSteps": 4,
  "doneSteps": 0,
  "pollUrl": "/v1/render/8c1c…"
}

GET /v1/render/:jobId

Returns current job state. Poll every 2–5 s until status is done or failed. The signed downloadUrl is regenerated on every successful poll and expires in 1 hour.

{
  "jobId": "8c1c…",
  "status": "done",
  "doneSteps": 4,
  "totalSteps": 4,
  "downloadUrl": "https://api.appscreen.co/r/abc?exp=…&sig=…",
  "error": null
}

Idempotency

Pass a Idempotency-Key header (any string up to 200 chars). Retries with the same key within 24h return the original job — safe to retry network failures without re-paying render cost.

Limits & errors

screens / job200
renders / month500 (Pro)
request rate30 / min per key
max upload200 files × 10 MB
job timeout20 min (server-side)

Common error shapes:

401missing or revoked api key
402free plan, monthly cap reached, or size/lang outside Pro tier
413captions payload exceeds the per-screen size cap
429per-key rate limit; retry after Retry-After seconds

TypeScript SDK

A minimal TS client lives in the sdk/ directory of the repo. It wraps the multipart upload and polling loop:

import { Appscreen } from "./sdk";

const client = new Appscreen({ apiKey: process.env.APPSCREEN_KEY! });

const job = await client.render({
  theme: "paper",
  sizes: ["ios-6.9"],
  langs: ["en"],
  fields: [{ id: "Headline", label: "Headline" }],
  captions: [
    { texts: { Headline: docFromText("Find people who share your taste.") } },
  ],
  screens: [
    { name: "shot1.png", data: await readFile("./shot1.png") },
  ],
});

const done = await client.waitForCompletion(job.jobId);
console.log(done.downloadUrl);