Complicated searches
Operators, exact date windows, filters and sorting.
The search box takes operators, so one request can cover several spellings of a brand and rule out the words that produce false matches.
Everything here stacks with the filters below it. The query narrows what matched, the filters narrow which posts come back, and order_by decides what you see first.
Every step shows the same call in all six Zelf clients and in cURL. Pick a language and the install line above the snippet switches with it. Each client reads your key from ZELF_API_KEY.
- 01Write the query
- 02Pick an exact window
- 03Narrow the result set
- 04Sort the results
- 05Collect a long history
Write the query
Operators are evaluated over the caption, transcript, summary and hashtags together. OR and NOT are case sensitive and have to be uppercase.
nike runningAND | Several words mean all of them. This is the default. |
|---|---|
nike OR adidasOR | Either term matches. |
running NOT marathonNOT | Drops posts that contain the second term. |
"summer collection"phrase | Quoted words match in that order, next to each other. NOT "out of stock" negates a phrase. |
(nike OR adidas) runninggrouping | Parentheses group a clause before it is combined with the rest. |
apple ONEAR/2 watchproximity | Both words within 2 words of each other, in that order. ONEAR binds more tightly than AND and OR. |
pip install zelf-sdkimport os
from zelf import ZelfAPIClient
client = ZelfAPIClient(api_key=os.environ["ZELF_API_KEY"])
result = client.content.list(
search="(nike OR \"air force 1\") running NOT marathon",
posted_within_days=90,
)
print(result)Pick an exact window
posted_within_days covers the common case. For a fixed period, send posted_after and posted_before as UTC timestamps. Use one or the other, not both styles at once.
posted_afterdate-time | ISO 8601 UTC, for example 2026-01-01T00:00:00Z. Must not be in the future. |
|---|---|
posted_beforedate-time | ISO 8601 UTC. Sent on its own, the window starts 366 days before it. |
posted_within_daysinteger | 1 to 365, counted back from now. The simpler form of the same thing. |
pip install zelf-sdkimport os
from datetime import datetime, timezone
from zelf import ZelfAPIClient
client = ZelfAPIClient(api_key=os.environ["ZELF_API_KEY"])
result = client.content.list(
search="running shoes",
posted_after=datetime(2026, 1, 1, tzinfo=timezone.utc),
posted_before=datetime(2026, 6, 30, 23, 59, 59, tzinfo=timezone.utc),
)
print(result)A window wider than 366 days is refused with 400 VALIDATION_ERROR. Split a longer range into consecutive ranges and run one request per range.
Narrow the result set
Filters combine with AND. Every numeric filter has a _min and a _max form, and both bounds are inclusive.
platforminstagram, tiktok | Comma separated. Leave it out to cover every platform Zelf indexes. |
|---|---|
content_formVIDEO, IMAGE | Uppercase. Detection only accepts VIDEO. |
languagestring | Comma separated ISO 639-1 codes, for example en,es. |
view_count_min, view_count_maxinteger | Same pattern for like_count, comment_count, share_count and total_engagement. |
engagement_rate_minfloat | A fraction, not a percentage. 0.05 is five percent. |
media_duration_min, media_duration_maxfloat | Seconds. media_duration_max=5400 drops anything detection cannot take. |
creator_follower_count_mininteger | Filters on the creator behind the post rather than the post itself. |
creator_usernamestring | Partial, case insensitive. Also satisfies the scope rule on its own. |
pip install zelf-sdkimport os
from zelf import ZelfAPIClient
client = ZelfAPIClient(api_key=os.environ["ZELF_API_KEY"])
result = client.content.list(
search="running shoes",
posted_within_days=90,
platform=["instagram", "tiktok"],
content_form="VIDEO",
language=["en"],
view_count_min=10000,
engagement_rate_min=0.03,
media_duration_max=5400.0,
)
print(result)Sort the results
order_by takes a comma separated list. The direction is inverted compared with most APIs: a bare key sorts descending, and a minus prefix sorts ascending. The default is posted_at descending.
order_by=view_countdescending | Most viewed first. A bare key is always descending. |
|---|---|
order_by=-posted_atascending | Oldest first. The minus prefix flips to ascending. |
order_by=view_count,-posted_atmultiple | Applied left to right. Available keys: posted_at, view_count, like_count, comment_count, share_count, engagement_rate, total_engagement, earned_media_value_cents, net_promoter_score. |
pip install zelf-sdkimport os
from zelf import ZelfAPIClient
client = ZelfAPIClient(api_key=os.environ["ZELF_API_KEY"])
result = client.content.list(
search="running shoes",
posted_within_days=90,
order_by=["view_count"],
)
print(result)net_promoter_score only sorts when the request is scoped with brand_id. Without it the request is refused with 400 BRAND_ID_REQUIRED.
Collect a long history
A single query reaches 3000 posts: 30 rows a page, 100 pages. To go past that, run the query once per date range and follow next within each one. Narrower ranges also keep each request fast.
pip install zelf-sdkimport os
from datetime import datetime, timezone
from zelf import ZelfAPIClient
client = ZelfAPIClient(api_key=os.environ["ZELF_API_KEY"])
result = client.content.list(
search="running shoes",
posted_after=datetime(2026, 7, 1, tzinfo=timezone.utc),
posted_before=datetime(2026, 9, 30, 23, 59, 59, tzinfo=timezone.utc),
page=1,
)
print(result)Over the limit you get 429 RATE_LIMIT_EXCEEDED with error.details.retry_after_seconds and the scopes that blocked. Wait that long and continue. Failed requests do not count against your quota.