Link a whole brand
Get a link for every product of a brand, then keep them up to date with a nightly run. About 40 requests for a 2,000-product brand.
1. Find the brand
Terminal
curl "https://api.stilo.io/v1/brands?q=nars" \
-H "Authorization: Bearer $STILO_API_KEY"Each brand's id is its slug, for example nars.
2. List its products, 100 at a time
Terminal
curl "https://api.stilo.io/v1/products?brand=nars&limit=100" \
-H "Authorization: Bearer $STILO_API_KEY"Keep requesting with cursor=<next_cursor> until next_cursor is null. Each product already says whether you have a link to it (link) and what you earn (commission; null means nothing to earn).
3. Create the links in batches
Terminal
curl https://api.stilo.io/v1/links/batch \
-H "Authorization: Bearer $STILO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"items": [{"product_id": "prd_..."}, {"product_id": "prd_..."}]}'Up to 100 items per call. Each result says created, existing or error, in the same order you sent them.
4. Run it every night
Because you get one link per product, running the same script again returns the same links, never duplicates. To pick up only what changed, pass updated_since with the time of your last run:
Terminal
curl "https://api.stilo.io/v1/products?brand=nars&updated_since=2026-11-04T03:00:00Z&limit=100" \
-H "Authorization: Bearer $STILO_API_KEY"A product that no longer appears in the list was removed or sold out. Its link keeps working; hide it on your site if you like.
Full example (Python)
sync_brand.py
import os
import requests
API = "https://api.stilo.io/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['STILO_API_KEY']}"}
def products(brand, updated_since=None):
params = {"brand": brand, "limit": 100}
if updated_since:
params["updated_since"] = updated_since
while True:
page = requests.get(f"{API}/products", headers=HEADERS, params=params, timeout=30).json()
yield from page["data"]
if not page["next_cursor"]:
return
params["cursor"] = page["next_cursor"]
def sync(brand, updated_since=None):
todo = [p for p in products(brand, updated_since) if p["commission"] and not p["link"]]
links = {}
for start in range(0, len(todo), 100):
chunk = todo[start:start + 100]
body = {"items": [{"product_id": p["id"]} for p in chunk]}
result = requests.post(f"{API}/links/batch", headers=HEADERS, json=body, timeout=60).json()
for product, item in zip(chunk, result["data"]):
if item["link"]:
links[product["id"]] = item["link"]["short_url"]
else:
print("skipped", product["name"], item["error"]["type"])
return links
if __name__ == "__main__":
for product_id, url in sync("nars").items():
print(product_id, url)Tips
- Respect
Retry-Afteron a429; the limits are generous, so honest scripts rarely hit them. - A store link (the retailer's whole store) is
{"retailer_id": "ret_..."}. - To pin a link to a variant (a color, a size), send
variant_idwith theproduct_id, or paste a store URL that names the variant.