Static Ads Lab
Reference

Pagination

How list endpoints paginate using the starting_after cursor pattern.

Static Ads Lab list endpoints return a fixed-size page plus a has_more flag. Pagination is cursor-based via the starting_after query parameter.

The list response shape

{
  "data": [
    { "id": "ia_a1b2c3d4e5f67890", "...": "..." },
    { "id": "ia_b2c3d4e5f6789012", "...": "..." }
  ],
  "has_more": true,
  "meta": {
    "request_id": "req_abc123",
    "timestamp": "2026-04-30T14:30:00.000Z"
  }
}
  • data is always an array.
  • has_more is true if more items exist after this page.
  • Default limit is 20; max is 100.

Cursor-based pagination with starting_after

Pass the last item's id as starting_after= to get the next page.

async function listAll(url, headers) {
  const all = [];
  let startingAfter;
  while (true) {
    const params = new URLSearchParams();
    if (startingAfter) params.set("starting_after", startingAfter);
    params.set("limit", "100");
    const r = await fetch(`${url}?${params}`, { headers });
    const { data, has_more } = await r.json();
    all.push(...data);
    if (!has_more) break;
    startingAfter = data[data.length - 1].id;
  }
  return all;
}

const allBrands = await listAll(
  "https://api.staticadslab.com/v1/brands",
  { "X-API-Key": process.env.SAL_API_KEY },
);

Filter parameters

Most list endpoints accept resource-specific filters in addition to starting_after and limit:

EndpointCommon filters
/v1/productsbrand_id
/v1/product-variantsproduct_id
/v1/audiencesproduct_id
/v1/imagesproduct_id, image_type (product, lifestyle, logo, background, other)
/v1/design-templatesstatus, industry, ad_format, deleted, ids
/v1/image-adsstatus, brand_id, product_id, product_variant_id, design_template_id, batch_id, editable, sku_code, ids

See each endpoint's API reference page for the full filter list.

Batch reading by IDs

For image ads and design templates, you can read up to N specific resources in one call without iterating, by passing a comma-separated ids= parameter. When ids= is provided, cursor pagination is ignored.

GET /v1/image-ads?ids=ia_a,ia_b,ia_c
GET /v1/design-templates?ids=dt_a,dt_b

This is the recommended pattern for batch polling. See Async jobs.

Pitfalls

  • Don't use data.length === limit as a stop condition — the API may return fewer items than limit even when has_more is true. Always trust has_more.
  • starting_after is the ID of an item you've already received. Don't synthesize cursors client-side.
  • Parallel cursor requests aren't supported — paginate serially.
  • Some legacy patterns refer to cursor — the actual parameter is starting_after.