Playbook

Run an AI analysis on a search term

Size the set, start the run, poll it, read the result.

15 min 5 steps

An AI analysis reads the posts your content_filters match and reports on a topic: sentiment, price, quality, competitors and products. You name the topic and hand it the same filters you would send to content.list.

It is a background job. Create it, poll it, then download the result from a signed link. A run can take an hour or more, so poll at a calm interval.

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. 01Count what you are about to analyse
  2. 02Start the analysis
  3. 03Wait for it to finish
  4. 04Download the result
  5. 05See the posts it used

Count what you are about to analyse

GET/api/v1/content/statistics/content.statistics

The statistics endpoint takes every content filter and returns one row of totals for the whole match set. Run it first: post_count is the only place that count exists, and it tells you whether the filters are too wide or too narrow before you spend a run on them.

post_countintegerPosts matching the filters. The number the analysis will draw from.
unique_creator_countintegerHow many creators those posts come from.
total_views, total_engagementintegerTotals over the whole set. total_earned_media_value_cents and total_media_duration come back too.
pip install zelf-sdk
import os

from zelf import ZelfAPIClient

client = ZelfAPIClient(api_key=os.environ["ZELF_API_KEY"])

result = client.content.statistics(
    search="running shoes",
    posted_within_days=90,
    content_form="VIDEO",
)
print(result)

An analysis reads up to 500 posts, or the limit configured for your workspace. If post_count is far above that, tighten the window or add a view_count_min so the run sees the posts you care about.

Start the analysis

POST/api/v1/ai_analysis/ai_analysis.create

The same filters go in the body as JSON under content_filters, with one difference: platform, language and order_by are arrays here rather than comma separated strings. topic names what the report is about.

namestring, requiredYour label for the run. It comes back on every read.
topicstring, requiredWhat the report is about: a brand, product, person or event, in a few words. For example Running shoes. Not a question: every run covers sentiment, price, quality, competitors and products anyway. Narrow the posts with content_filters.
analysis_scopearray, optionalCONTENT, COMMENT, or both. Defaults to ["CONTENT"]. Each scope becomes one run with its own status and result.
content_filtersobject, requiredMust be scoped, same rule as a search: one of search, creator_id, creator_username, brand_id or external_id.
pip install zelf-sdk
import os

from zelf import ZelfAPIClient

client = ZelfAPIClient(api_key=os.environ["ZELF_API_KEY"])

result = client.ai_analysis.create(
    name="Running shoes, Q3",
    topic="Running shoes",
    analysis_scope=["CONTENT"],
    content_filters={
        "search": "running shoes",
        "posted_within_days": 90,
        "content_form": "VIDEO",
        "platform": ["instagram", "tiktok"],
        "language": ["en"],
        "view_count_min": 10000,
        "order_by": ["view_count"],
    },
)
print(result)
Response
{
  "id": "anl_7Km3Qx9pLt",
  "analysis_type": "AI_ANALYSIS",
  "name": "Running shoes, Q3",
  "topic": "Running shoes",
  "created_at": "2026-10-07T09:20:03Z",
  "modified_at": "2026-10-07T09:20:03Z",
  "analyses": [
    { "id": "anr_2Bq8Zt4v", "scope": "CONTENT", "status": "IN_PROGRESS" }
  ]
}

Wait for it to finish

GET/api/v1/ai_analysis/?id={analysis_id}ai_analysis.list

Read the analysis back by id. Each entry under analyses carries its own status. Poll every minute or two, not every second: the ai_analysis quota is 10 requests a second and 1000 an hour, and a tight loop will spend it on nothing.

IN_PROGRESSnot finalStill running. Keep polling.
COMPLETEDfinalFinished with a result to download.
EMPTY_RESULTfinalFinished, but the filters matched nothing worth analysing. Widen the window or loosen the filters.
FAILEDfinalFinished without a result.
pip install zelf-sdk
import os

from zelf import ZelfAPIClient

client = ZelfAPIClient(api_key=os.environ["ZELF_API_KEY"])

result = client.ai_analysis.list(
    id="anl_7Km3Qx9pLt",
)
print(result)

Polling is the simple option, not the best one. Subscribe to the ai_analysis.completed webhook and Zelf tells you the moment a run lands, then you fetch the result once.

Download the result

GET/api/v1/ai_analysis/results/?analysis_id={analysis_id}ai_analysis.results

The result is not inline. Each finished run carries a signed link that expires, so fetch it when you are ready to read it rather than storing the link. Ask by analysis_id for every run, or by id for one.

analysis_idstringReturns every run under the analysis. Send this or id, not both.
idstringReturns one run.
result.download_urlstring or nullSigned link to the payload. Null until the run has produced one.
result.expires_atintegerUnix seconds. Re-read the endpoint for a fresh link after it passes.
pip install zelf-sdk
import os

from zelf import ZelfAPIClient

client = ZelfAPIClient(api_key=os.environ["ZELF_API_KEY"])

result = client.ai_analysis.results(
    analysis_id="anl_7Km3Qx9pLt",
)
print(result)
Response
{
  "results": [
    {
      "id": "anr_2Bq8Zt4v",
      "analysis_id": "anl_7Km3Qx9pLt",
      "scope": "CONTENT",
      "status": "COMPLETED",
      "created_at": "2026-10-07T09:20:03Z",
      "modified_at": "2026-10-07T10:48:51Z",
      "result": {
        "download_url": "https://storage.googleapis.com/...",
        "expires_at": 1791455331,
        "format": "json"
      }
    }
  ],
  "item_count": 1,
  "page": 1,
  "next": null,
  "previous": null
}

See the posts it used

GET/api/v1/ai_analysis/contents/?analysis_id={analysis_id}ai_analysis.contents

When an answer looks wrong, the usual cause is the input rather than the analysis. These two read back exactly the posts the run drew from, so you can check the filters did what you meant. The contents endpoint pages like any other list.

pip install zelf-sdk
import os

from zelf import ZelfAPIClient

client = ZelfAPIClient(api_key=os.environ["ZELF_API_KEY"])

result = client.ai_analysis.contents(
    analysis_id="anl_7Km3Qx9pLt",
    page=1,
)
print(result)

Summary

StepRequestInputOutput
1GET /api/v1/content/statistics/content filterspost_count
2POST /api/v1/ai_analysis/name, topic, content_filtersanalysis id (anl_...)
3GET /api/v1/ai_analysis/?id=analysis idstatus per run
4GET /api/v1/ai_analysis/results/analysis idsigned download_url
5GET /api/v1/ai_analysis/contents/analysis idthe posts it read