Playbook

Your first search

Find posts by keyword and read the response.

5 min 4 steps

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.

  1. 01Send your API key
  2. 02Search the last 90 days
  3. 03Read the envelope
  4. 04Walk the pages

Send your API key

GET/api/v1/usage/usage_retrieve

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-sdk
import 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.

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_idstringRequest id. Quote it when you report a problem, it is how the request is found in the logs.
item_countintegerRows on this page, not the size of the whole match set. For that total use the statistics endpoint.
next, previousinteger or nullPage numbers. next is null on the last page.
applied_filtersobjectWhat the server actually filtered on, including defaults it filled in for you. Only on the content list and statistics endpoints.
results[].idstringThe content id, prefixed con_. This is what detection and the other endpoints take.
results[].brand_id and the fields under itnullBrand fields stay null unless you scoped the request with brand_id. See the brand monitoring recipe.
Response
{
  "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

GET/api/v1/content/?page=2content.list

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-sdk
import 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.