Audiences
Target personas tied to a product. Audiences shape the ad copy and creative direction.
An audience is a target persona attached to a product — like "budget-conscious parents" or "millennial outdoor enthusiasts". When you generate an image ad, the audience steers the copy, tone, and creative direction.
Mental model
The same product, generated for two different audiences, produces two different ads. The audience's name and description are inputs to the AI copy and creative pipeline. Audiences are scoped to a product, not the brand — so a brand with three products has three independent audience pools.
ID prefix: aud_.
Fields
| Field | Type | Description |
|---|---|---|
id | string | aud_… |
product_id | string | Owning product (prod_…) |
name | string | Short persona name |
description | string | null | Long-form persona description; the more concrete, the better the output |
details | object | null | Free-form audience metadata (interests, pain points, jobs-to-be-done) |
duplicated_from_id | string | null | The audience this one was duplicated from, if any |
created_at / updated_at | string | ISO timestamps |
Endpoints
| Method | Path | Purpose |
|---|---|---|
POST | /v1/audiences | Create an audience |
GET | /v1/audiences | List audiences |
GET | /v1/audiences/:id | Get an audience |
PATCH | /v1/audiences/:id | Update an audience |
DELETE | /v1/audiences/:id | Delete an audience |
POST | /v1/audiences/:id/duplicate | Duplicate an audience |
Duplicating
POST /v1/audiences/:id/duplicate creates an independent copy named "<name> - copy" on the same product. An archived audience still yields an active copy.
To copy an audience onto a different product, create it directly and set duplicated_from_id yourself — that records the same lineage while choosing the destination:
await fetch("https://api.staticadslab.com/v1/audiences", {
method: "POST",
headers: { "X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json" },
body: JSON.stringify({
product_id: "prod_other_product",
name: "Technical Grapplers (18-40)",
description: "…",
duplicated_from_id: "aud_source",
}),
});Copies never sync. Editing either audience leaves the other unchanged, and duplicated_from_id keeps pointing at the source even after the source is deleted.
Common patterns
Create an audience
const response = await fetch("https://api.staticadslab.com/v1/audiences", {
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
product_id: "prod_YOUR_PRODUCT_ID",
name: "Millennial Outdoor Enthusiasts",
description:
"25–40 year olds who hike weekends, follow outdoor influencers on Instagram, and care about sustainable materials.",
}),
});
const { data } = await response.json();
console.log(data.id); // aud_...Generate ads for multiple audiences
The classic batch pattern: one product, many audiences, one ad per (product, audience) pair.
const audienceIds = ["aud_a", "aud_b", "aud_c"];
const ads = await Promise.all(
audienceIds.map((aud) =>
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_YOUR_PRODUCT_ID",
audience_id: aud,
}),
}).then((r) => r.json()),
),
);Then batch-poll the resulting IDs.
Pitfalls
- Vague descriptions produce generic ads. "People who like nature" is bad. "Weekend hikers in the Pacific Northwest who own at least one pair of trail shoes" is good.
- A product can have many audiences. There's no public quota, but each audience burns wallet on every generation — be deliberate.
Related
Prompt for your agent
Read https://www.staticadslab.com/docs/resources/audiences.mdx and create three distinct audiences for product prod_YOUR_PRODUCT_ID. Each should have a specific demographic, psychographic, and a clear pain point.