Static Ads Lab
Concepts

Ad copy

Meta ad copy (ad name, primary text, headline, description) written for each ad, and edited by hand when you want.

Each completed ad can carry Meta copy: the ad name, primary text, headline and description you paste into Ads Manager. Generate it in bulk, then adjust any field by hand. Every change is a new copy version (iacv_). Scopes: image_ads:write to generate or edit, image_ads:read to read.

Generate

POST /v1/image-ads/copy covers 1 to 20 completed ads and returns at once (202).

const { data } = await sal("/v1/image-ads/copy", {
  method: "POST",
  idempotencyKey: crypto.randomUUID(),
  body: {
    ads: [
      { image_ad_id: "ia_7e3c9a1b5d2f4068" },
      { image_ad_id: "ia_1f5b8d3a6c9e2047", additional_context: "Mention free returns." },
    ],
  },
});
// data.ads: [{ image_ad_id, status: "generating" | "skipped", reason?, version_id?, version_number? }]
  • additional_context adds facts for one ad. prompt (top level) replaces the copy instructions for this call.
  • An ad that isn't completed, or already has copy generating, is skipped with a reason and isn't charged.
  • Copy is usually ready in under a minute. Each ad that succeeds is charged its model cost plus 30%, rounded up to the cent; failures are free.

Read

GET /v1/image-ads/{id}/copy:

{
  "data": {
    "image_ad_id": "ia_7e3c9a1b5d2f4068",
    "status": "completed",
    "copy": {
      "id": "iacv_5a2c8e1f7b3d9046",
      "version_number": 1,
      "source": "generated",
      "ad_name": "Fleece hoodie · Warm commute · 4:5",
      "primary_text": "Cold mornings, handled. 400 gsm fleece that keeps you warm without the bulk of a coat.",
      "headline": "Warm without the bulk",
      "description": "Free returns on every order",
      "created_at": "2026-11-08T15:02:11.000Z"
    },
    "failure": null,
    "prompt": { "source": "default", "text": "…" }
  },
  "meta": { "request_id": "req_9b1d4f7a2c6e8035", "timestamp": "2026-11-08T15:02:30.000Z" }
}

status is none, generating, completed or failed. The current copy is also on the ad itself, as copy.

Edit by hand

PATCH /v1/image-ads/{id}/copy saves the fields you send as a new manual version; the rest keep their value. Free. It returns 409 AD_COPY_IN_PROGRESS while a generation is running.

await sal(`/v1/image-ads/${adId}/copy`, {
  method: "PATCH",
  body: { headline: "Warmth, minus the bulk" },
});