Image ads
The core API output — Meta-ready PNGs generated from a reference ad, brand, product, and audience.
An image ad is the API output. You combine a reference ad image with a brand, product, and audience, and the API generates a Meta-ready PNG asynchronously. Every image ad is editable.
Mental model
The API analyzes reference_ad_url, creates a new Perfect Ad, rebuilds it as editable layers in a JSON tree, and renders the final ad from that tree. You get a PNG plus the tree. See Editable image ads.
- Price: $2.00 per ad (SKU
editable_image_ad), including 1 generated image asset, plus $0.50 for each additional generated image asset. Only successful generations count; retries and failures are free. Billed once, when the ad completes. - Time: up to about 20 minutes.
- Shape: the ad follows the reference ad's aspect ratio (
1:1,4:5or9:16). - Editing: a plain-English instruction or your own design script via design edits, or a full-tree
PATCH.
ID prefix: ia_.
Fields
| Field | Type | Description |
|---|---|---|
id | string | ia_… |
reference_ad_url / brand_id / product_id / audience_id | string | Inputs |
design_template_id | string | null | Historical template source for legacy rows. New rows return null |
product_variant_id | string | null | Optional variant override |
prompt | string | null | Free-form creative direction |
options | object | null | Reserved for legacy/internal rows. New public requests omit it |
editable | boolean | Response only. true for every new ad |
sku_code | enum | editable_image_ad for new ads. Ads from before every ad was editable may show flat_image_ad |
status | enum | processing | completed | failed |
progress | object | null | { step, message, percentage } while processing |
image_url | string | null | Meta-ready PNG (when complete) |
width / height | number | null | Pixel dimensions |
current_json_tree | object | null | The ad's editable JSON tree (null until the ad completes) |
editor_supported | boolean | Whether the ad can be edited: true for completed ads from the current pipeline. Some older ads keep current_json_tree but are not supported for editing |
tree_revision / rendered_tree_revision / render_status | number / number / enum | Edit and render state. See Editable image ads |
figma_render_url / initial_figma_render_url | string | null | Figma sync renders |
error | object | null | { code, message } when failed |
duration_ms | number | null | Worker wall-clock time |
batch_id | string | null | Set when generated as part of a batch |
created_at / completed_at | string | ISO timestamps |
Lifecycle
stateDiagram-v2
[*] --> processing: POST /v1/image-ads (202)
processing --> completed: image_url ready
processing --> failed: error populated
completed --> [*]
failed --> [*]You're billed only on completed. failed jobs do not deduct from your wallet.
Endpoints
| Method | Path | Purpose |
|---|---|---|
POST | /v1/image-ads | Generate an image ad |
GET | /v1/image-ads | List image ads (supports ids=, status=, batch_id=) |
GET | /v1/image-ads/:id | Get an image ad |
PATCH | /v1/image-ads/:id | Update the JSON tree |
POST | /v1/image-ads/:id/edits | Edit with an instruction or script |
GET | /v1/image-ads/:id/edits | List design edits |
GET | /v1/image-ads/:id/outline | Layer outline for targeting edits |
GET | /v1/image-ads/:id/render-status | Render status, without the tree |
DELETE | /v1/image-ads/:id | Delete an image ad |
POST | /v1/image-ads/sync | Sync from Figma |
GET | /v1/image-ads/:id/versions | List versions |
GET | /v1/image-ads/:id/versions/:versionId | Get a version |
Common patterns
Generate an ad
const response = await fetch("https://api.staticadslab.com/v1/image-ads", {
method: "POST",
headers: { "X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json" },
body: JSON.stringify({
reference_ad_url: "https://cdn.example.com/reference-ad.png",
brand_id: "brand_...",
product_id: "prod_...",
audience_id: "aud_...",
}),
});
const { data } = await response.json();
// data.id, data.status === "processing"Batch poll
When generating many ads, poll them in one request rather than N:
const ids = ["ia_a", "ia_b", "ia_c"].join(",");
const response = await fetch(
`https://api.staticadslab.com/v1/image-ads?ids=${ids}`,
{ headers: { "X-API-Key": "YOUR_API_KEY" } },
);
const { data } = await response.json();
const stillProcessing = data.filter((d) => d.status === "processing");See Batch generation and Async jobs.
Pitfalls
product_idandbrand_idmust be linked. Using a product that doesn't belong to the brand returns422.reference_ad_urlmust be a publicly accessible image URL.- Don't poll faster than every 2 seconds. 4 seconds is the recommended interval for image ads.
current_json_treeisnulluntil generation completes — wait forstatus: "completed"before reading it.- Don't send
editable. Every ad is editable and the field returns400 VALIDATION_ERROR. - Generation takes up to about 20 minutes. Cap your polling at 25 minutes or more, not a few minutes.
Related
Prompt for your agent
Read https://www.staticadslab.com/docs/resources/image-ads.mdx and write generateAd({ referenceAdUrl, brandId, productId, audienceId }) that creates an ad, polls every 4 seconds (for up to 25 minutes) until completed, and returns the result. Throw on failed.Design packs
Named collections of swipe file designs you can reuse across campaigns, and hand to Studio in one mention.
Editable image ads
Every image ad is editable. PNG plus a structured JSON tree you can change by instruction, script or PATCH; the PNG re-renders in the background. Versioned and Figma-syncable.