Filtering
Filters are query parameters. Filtering server-side is always cheaper than fetching everything and filtering in your own code: it costs you fewer requests against your rate limit and returns faster.
Date ranges
Most endpoints that return time-based data accept a date range.
curl -G https://api.askylabs.com/v1/brands/b_7a3f.../visibility \
-H "Authorization: Bearer $ASKY_API_KEY" \
-d start_date=2026-07-01 \
-d end_date=2026-07-31| Parameter | Format | Notes |
|---|---|---|
start_date | YYYY-MM-DD | Inclusive |
end_date | YYYY-MM-DD | Inclusive |
Dates are calendar dates in UTC, not timestamps. A day is complete once the pipeline for that day has finished, so the current day is usually partial. For a stable daily sync, pull through yesterday.
Omit both and the endpoint uses its documented default window, typically the last 30 days. Ranges are capped per endpoint; asking for more returns 400 invalid_request with the maximum in the message rather than silently truncating.
Repeated parameters
Multi-value filters repeat the parameter. Values within one filter are OR’d, and different filters are AND’d.
curl -G https://api.askylabs.com/v1/brands/b_7a3f.../visibility \
-H "Authorization: Bearer $ASKY_API_KEY" \
-d start_date=2026-07-01 \
-d end_date=2026-07-31 \
-d engine=chatgpt \
-d engine=perplexity \
-d country=USThat reads: ChatGPT or Perplexity, and United States.
Common filters
Availability varies by endpoint; each endpoint documents what it accepts.
| Parameter | Values | Notes |
|---|---|---|
topic_id | Topic id | From GET /v1/brands/{id}/topics. Repeatable. |
engine | Engine slug | chatgpt, perplexity, aio, and others. From GET /v1/brands/{id}/models. Repeatable. |
country | ISO 3166-1 alpha-2, uppercase | US, GB, SE. Repeatable. |
tag_id | Tag id | From GET /v1/brands/{id}/tags. Repeatable. |
tag_match | any, all | How multiple tags combine. Defaults to any. |
search | Free text | Substring match on the endpoint’s primary text field. |
Get filter values from their listing endpoints rather than hardcoding them. Engines in particular change as AI search platforms come and go, and a hardcoded slug becomes a silently empty result rather than an error.
Unknown parameters are rejected
A parameter we do not recognise returns 400 invalid_request naming it.
This is deliberate. Silently ignoring a misspelled filter is how an integration ends up reporting on far more data than intended, with no signal that anything is wrong. A typo in engnie=chatgpt should be a failed request, not a year of unfiltered numbers in your dashboard.
Incremental sync
To pull only what is new since your last run, advance the date window rather than storing a cursor.
run at 2026-08-12: start_date=2026-08-10 end_date=2026-08-11
run at 2026-08-13: start_date=2026-08-11 end_date=2026-08-12Overlap the window by a day and upsert on the natural key. Late-arriving data does get written to a day after that day has closed, so a non-overlapping window will miss records.
Sorting
Where an endpoint supports sorting, it documents sort and sort_direction with the fields it accepts. Keep both constant while paginating, since changing either invalidates your cursor.
Combining filters efficiently
Narrow with the cheapest dimension first. Date range usually eliminates the most data, then topic, then engine and country.
If you need several cuts of the same underlying data, fetch the narrowest superset once and aggregate locally rather than issuing one request per cut. It is fewer requests and gives consistent numbers across the cuts, because they all came from one read.