Watchlists and webhooks
Put advertisers on a watchlist, receive signed advertiser.changes webhooks when ads start, stop or change, verify the signature and redeliver.
A watchlist is a list of advertisers we check on a schedule. After each check you receive one event per advertiser with the new, stopped and changed ads.
Create a watchlist
curl -X POST "https://api.adlibapi.com/v1/watchlists" \
-H "X-API-Key: $ADLIB_API_KEY" -H "Content-Type: application/json" \
-d '{"name": "Competitors",
"advertisers": ["meta:15087023444", "google:AR18378488041124659201"],
"webhook_url": "https://hooks.example.com/adlib",
"interval_hours": 24}'Find advertiser ids with resolve. The shortest interval and the number of advertisers depend on the plan:
| Plan | Advertisers | Shortest interval |
|---|---|---|
| Free | 1 | 24 h |
| Starter | 10 | 24 h |
| Growth | 50 | 12 h |
| Pro | 250 | 6 h |
| Business | 1,000 | 1 h |
The first check of an advertiser is the baseline: it records the current ads and sends no event.
The event
{
"event": "advertiser.changes",
"watchlist_id": "0b7c6a8e-1f2d-4c3b-9a8e-5d6f7a8b9c0d",
"advertiser_id": "meta:15087023444",
"crawled_at": "2026-10-27T08:00:00Z",
"summary": { "new": 2, "started": 0, "stopped": 1, "changed": 0 },
"new": [ { "type": "discovered", "at": "...", "ad_id": "meta:...", "ad": { ... } } ],
"started": [],
"stopped": [ ... ],
"changed": []
}Every request carries X-AdLib-Event, X-AdLib-Delivery (the delivery id) and X-AdLib-Signature.
Verify the signature
X-AdLib-Signature looks like t=1793102400,v1=5f2c…. v1 is the hex HMAC-SHA256 of "<t>.<raw body>" with your webhook secret (GET /v1/webhooks/secret):
import hashlib, hmac, time
def verify(secret: str, header: str, body: bytes, tolerance: int = 300) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
t, sig = parts["t"], parts["v1"]
expected = hmac.new(secret.encode(), f"{t}.".encode() + body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, sig) and abs(time.time() - int(t)) < toleranceUse the raw body as received, before parsing the JSON. Rotate the secret with POST /v1/webhooks/secret/rotate.
Test, inspect and redeliver
POST /v1/webhooks/testsends a signedwebhook.pingto a URL.GET /v1/webhooks/deliverieslists recent deliveries with status codes;GET /v1/webhooks/deliveries/{id}includes the payload.POST /v1/webhooks/deliveries/{id}/redeliverqueues a delivery again.
Failed deliveries are retried. Answer with a 2xx quickly and do the work afterwards.
Without webhooks
Leave out webhook_url and poll GET /v1/advertisers/{id}/changes?since= instead. The watchlist still records every ad.