Static Ads Lab
Concepts

Products

Products belong to a brand and group product variants and audiences for ad generation.

A product is a thing your brand sells. Products belong to exactly one brand and group product variants (SKUs) and target audiences.

Mental model

A product is the unit of "what this ad is selling". Every image ad generation request specifies a product_id. The product's name, description, and details inform the AI copy and creative direction.

ID prefix: prod_.

Fields

FieldTypeDescription
idstringprod_…
brand_idstringOwning brand (brand_…)
namestringProduct name
descriptionstring | nullLong-form description used to inform ad copy
detailsobject | nullFree-form product metadata (features, benefits, USPs)
duplicated_from_idstring | nullThe product this one was duplicated from, if any
created_at / updated_atstringISO timestamps

Endpoints

MethodPathPurpose
POST/v1/productsCreate a product
GET/v1/productsList products
GET/v1/products/:idGet a product
PATCH/v1/products/:idUpdate a product
DELETE/v1/products/:idDelete a product
POST/v1/products/:id/duplicateDuplicate a product

Duplicating

POST /v1/products/:id/duplicate creates an independent copy named "<name> - copy" under the same brand. Cascade defaults to true, so the copy arrives with the product's active variants and audiences; pass ?cascade=false for the product record alone.

Only the product is renamed — its variants keep their names. Variant images are shared rather than re-uploaded. Archived children are skipped, and an archived product still yields an active copy.

const response = await fetch(
  "https://api.staticadslab.com/v1/products/prod_.../duplicate",
  { method: "POST", headers: { "X-API-Key": "YOUR_API_KEY" } },
);

const { data, duplicated } = await response.json();
// data.name  → "Trail Runner Pro - copy"
// duplicated → { products: 0, product_variants: 4, audiences: 2, variant_images: 12 }

Common patterns

Create a product

const response = await fetch("https://api.staticadslab.com/v1/products", {
  method: "POST",
  headers: {
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    brand_id: "brand_YOUR_BRAND_ID",
    name: "Trail Runner Pro",
    description: "Lightweight trail-running shoes with carbon-plate stability.",
  }),
});
const { data } = await response.json();
console.log(data.id); // prod_...
curl -s -X POST https://api.staticadslab.com/v1/products \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "brand_id": "brand_YOUR_BRAND_ID",
    "name": "Trail Runner Pro",
    "description": "Lightweight trail-running shoes with carbon-plate stability."
  }'
import requests

response = requests.post(
    "https://api.staticadslab.com/v1/products",
    headers={"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"},
    json={
        "brand_id": "brand_YOUR_BRAND_ID",
        "name": "Trail Runner Pro",
        "description": "Lightweight trail-running shoes with carbon-plate stability.",
    },
)
print(response.json()["data"]["id"])

List a brand's products

const response = await fetch(
  `https://api.staticadslab.com/v1/products?brand_id=brand_YOUR_BRAND_ID`,
  { headers: { "X-API-Key": "YOUR_API_KEY" } },
);
const { data } = await response.json();

Pitfalls

  • The API will reject POST /v1/image-ads with 422 if the product_id doesn't belong to the brand_id you also passed — they must be linked.
  • Product description is used by the AI copy generator. Vague descriptions produce vague copy. Specific descriptions produce better ads.

Prompt for your agent

Read https://www.staticadslab.com/docs/resources/products.mdx and create three products under brand brand_YOUR_BRAND_ID with realistic names and descriptions.