Your first search
Find posts by keyword and read the response.
Every other recipe starts here. A search returns posts from across the platforms Zelf indexes, newest first, wrapped in the same envelope every endpoint uses.
You need an API key, and API access has to be enabled on your Zelf account.
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.
Send your API key
Every request carries the key in the x-api-key header. Start with the usage endpoint: it reports your quota, it is not itself rate limited, and it confirms which brand the key belongs to.
pip install zelf-sdkimport os
from zelf import ZelfAPIClient
client = ZelfAPIClient(api_key=os.environ["ZELF_API_KEY"])
result = client.usage.retrieve()
print(result)A bad key returns 401 with error.code INVALID_API_KEY, EXPIRED_API_KEY or REVOKED_API_KEY. If you get one of those, check that API access is turned on for the brand.
Search the last 90 days
search runs over the caption, the transcript, the AI summary and the hashtags. Two words mean both words. posted_within_days sets the window.
searchstring | Full text over caption, transcript, summary and hashtags. Several words are combined with AND. |
|---|---|
posted_within_daysinteger | Last N days, 1 to 365. With no date filter at all the window is the last 7 days. |
page_sizeinteger | Rows per page, up to 30. 30 is also the default. |
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,
page_size=30,
)
print(result)A content request must be scoped. Send at least one of search, creator_id, creator_username, brand_id or external_id, or the call returns 400 VALIDATION_ERROR.
Read the envelope
Every successful response has the same shape. results is always a list, even for an endpoint that returns a single object. next and previous are page numbers, not URLs, and are null at the ends.
log_idstring | Request id. Quote it when you report a problem, it is how the request is found in the logs. |
|---|---|
item_countinteger | Rows on this page, not the size of the whole match set. For that total use the statistics endpoint. |
next, previousinteger or null | Page numbers. next is null on the last page. |
applied_filtersobject | What the server actually filtered on, including defaults it filled in for you. Only on the content list and statistics endpoints. |
results[].idstring | The content id, prefixed con_. This is what detection and the other endpoints take. |
results[].brand_id and the fields under itnull | Brand fields stay null unless you scoped the request with brand_id. See the brand monitoring recipe. |
{
"log_id": "6f1c0a2e-6c4a-4a6f-9f6e-0b7f6b2d1a44",
"timestamp": "2026-10-07T09:14:22.481293Z",
"applied_filters": {
"search": "running shoes",
"posted_within_days": 90,
"brand_id": null
},
"results": [
{
"id": "con_8Qd2Vx7mLp",
"platform": "instagram",
"content_form": "VIDEO",
"posted_at": "2026-09-28T17:02:11Z",
"view_count": 184203,
"like_count": 9120,
"comment_count": 212,
"share_count": 341,
"total_engagement": 9673,
"engagement_rate": 0.0525,
"media_duration": 41.2,
"earned_media_value_cents": 412000,
"language": "en",
"caption": "Broke in the new running shoes on a 10k",
"transcript": "right so these are the ones everybody keeps asking about",
"ai_summary": "A runner reviews a new pair of running shoes after a 10k.",
"hashtags": ["running", "10k"],
"platform_url": "https://www.instagram.com/reel/Cx12ab34cd/",
"thumbnail_url": "https://cdn.hellozelf.com/thumb/8Qd2Vx7mLp.jpg",
"creator": {
"id": "cr_4Tz9Hs1k",
"username": "milesandmornings",
"name": "Miles and Mornings",
"platform": "instagram",
"platform_url": "https://www.instagram.com/milesandmornings",
"follower_count": 128400,
"active_content_count": 612
},
"brand_id": null,
"is_owned": null,
"is_tagged": null,
"is_influencer": null,
"mention_type": null,
"net_promoter_score": null
}
],
"item_count": 1,
"page": 1,
"next": 2,
"previous": null
}Walk the pages
Ask for the next page by number. Pages hold 30 rows and stop at page 100, so one query reaches 3000 posts. If you need more than that, split the date range and run the query once per range. The clients can also walk the pages for you: auto_paging in Python and Ruby, autoPaging in TypeScript, AutoPaging in Go, collect_all in Rust and AutoPagingAsync in C#.
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,
page=2,
)
print(result)Content responses are cached for an hour, so repeating the same query costs you little and returns the same rows.