Content

Search, list, and aggregate content (posts, videos, images) across the platforms Zelf tracks. Supports rich filtering by metrics, platform, language, date window, and creator, plus optional brand context.

List Content

GET/api/v1/content/content.list

Returns a paginated list of content. Every request must scope what it covers: supply at least one of creator_id, creator_username, search, brand_id, or external_id, otherwise the request is rejected with VALIDATION_ERROR. By default results are ordered by posted_at descending (most recently posted first); override with order_by.

Every response echoes the effective defaults in applied_filters (the resolved date window, page, page_size, and brand_id), so an empty results set can be explained.

Dates

Every request covers a time window. Four parameters define it.

ParameterTypeDefines
posted_aftertimestampStart of the window
posted_within_hoursinteger, 1 to 8760Start of the window, counted back from the current time
posted_within_daysinteger, 1 to 365Start of the window, counted back from the current time
posted_beforetimestampEnd of the window

A request with no date parameter covers the last 7 days. applied_filters reports this as posted_within_days: 7.

Three parameters define the start of the window, so a request may carry more than one. Such a request is valid. The API applies the first parameter present in this order and ignores the rest:

  1. posted_after
  2. posted_within_hours
  3. posted_within_days

applied_filters contains only the parameter that was applied, so it identifies the window that produced a response.

posted_before defines the end of the window and combines with any of the three. On its own it covers the 366 days before it. With posted_within_hours or posted_within_days the window is counted back from posted_before instead of from the current time, so posted_before=2026-09-01T00:00:00Z with posted_within_hours=24 covers 2026-08-31T00:00:00Z to 2026-09-01T00:00:00Z.

Two limits apply to every window. posted_after and posted_before may be at most 366 days apart, and a longer period is read as consecutive requests. Content posted before 2025-01-01 is not available.

A value outside the ranges in the table returns VALIDATION_ERROR. Such values are rejected, not clamped: posted_within_days=400 is an error rather than 365.

Results are paginated: page defaults to 1 and page_size to 30, which is also the maximum (larger values are reduced to 30). item_count is the number of rows in the returned page, not the size of the whole match set, and next is non-null while further pages remain. For the total number of matching posts, call content.statistics with the same query and read post_count.

When brand_id is omitted, the brand-specific fields (brand_id, is_owned, is_tagged, is_influencer, mention_type, net_promoter_score) are returned as null, and the brand-only filters and sorts return BRAND_ID_REQUIRED. Supply brand_id (one or more values, comma-separated) to populate those fields and enable the brand-only filters. Each row's id is the value to use for content.details and for the comments.list content_id.

Examples

  • Full-text search over the last 7 days (brand fields null): GET /api/v1/content/?search=running+shoes
  • Brand content over an explicit window: GET /api/v1/content/?brand_id=brd_123&posted_after=2026-01-01T00:00:00Z&posted_before=2026-06-30T23:59:59Z
  • Most-viewed first: add &order_by=view_count. Sort direction is inverted, so a bare key sorts descending and a - prefix ascending.

Parameters

brand_idType: string

One or more brand ids, comma-separated, as returned by brands.list. Scopes the query to those brands, populates the brand-specific fields, and enables the brand-only filters and sorts. Any id you cannot access returns 403, and a malformed value returns INVALID_ID.

creator_idType: string

Limit results to a single creator by id (from /api/v1/creator/).

creator_usernameType: string

Creator username substring. Case-insensitive.

external_idType: string

Platform-side post id. Matched exactly.

platformType: enum[]unique items true

Platforms to include, comma-separated.

Show values
unique items
true
instagramtiktokyoutube
posted_afterType: string(date-time)

When the post was published (UTC, ISO 8601). (Inclusive Lower Bound)

posted_beforeType: string(date-time)

When the post was published (UTC, ISO 8601). (Inclusive Upper Bound)

posted_within_hoursType: integerminimum 1 · maximum 8760

Start of the window, counted back from the current time, in hours (1-8760). Takes precedence over posted_within_days. Counted back from posted_before when that is also supplied.

minimum
1
maximum
8760
posted_within_daysType: integerminimum 1 · maximum 365

Start of the window, counted back from the current time, in days (1-365). Defaults to 7 when no date parameter is supplied. posted_after and posted_within_hours take precedence over it.

minimum
1
maximum
365
order_byType: enum[]unique items true

Sort the results. Any of: posted_at, view_count, like_count, comment_count, share_count, engagement_rate, total_engagement, earned_media_value_cents, net_promoter_score, relevance_score. A bare key sorts descending; prefix with - to sort ascending.

Sort direction is inverted: order_by=field sorts descending and order_by=-field sorts ascending. Comma-separate to sort by multiple fields.

Show values
unique items
true
posted_at-posted_atview_count-view_countlike_count-like_countcomment_count-comment_countshare_count-share_countengagement_rate-engagement_ratetotal_engagement-total_engagementearned_media_value_cents-earned_media_value_centsnet_promoter_score-net_promoter_scorerelevance_score-relevance_score
comment_countType: integer

Number of comments on the post.

content_formType: enum

Content medium. Case-sensitive; values are stored and returned in uppercase.

Show values
VIDEOPHOTO
creator_follower_countType: integer

Follower count of the post's creator.

earned_media_value_centsType: integer

Estimated earned media value, in cents.

engagement_rateType: number(float)

Engagement as a fraction of views (for example, 0.05 = 5%).

is_influencerType: boolean

Limit results to the brand's influencer content, or exclude it with false. Requires brand_id.

is_ownedType: boolean

Limit results to content owned by the brand. Requires brand_id.

is_taggedType: boolean

Limit results to content where the brand is tagged. Requires brand_id.

languageType: string[]

Language codes to include, comma-separated (for example, en, es).

like_countType: integer

Number of likes on the post.

media_durationType: number(float)

Length of the media in seconds.

mention_typeType: enum[]unique items true

Limit results to these mention kinds, comma-separated. Requires brand_id.

Show values
unique items
true
contentcomment
mention_type_notType: enum[]unique items true

Exclude these mention kinds, comma-separated. Requires brand_id.

Show values
unique items
true
contentcomment
net_promoter_scoreType: integer

Brand net promoter score for the content. Requires brand_id.

postedType: string(date-time)

When the post was published (UTC, ISO 8601).

share_countType: integer

Number of shares of the post.

total_engagementType: integer

Total engagement (likes plus comments plus shares).

view_countType: integer

Number of views on the post.

comment_count_maxType: integer

Number of comments on the post. (Inclusive Upper Bound)

comment_count_minType: integer

Number of comments on the post. (Inclusive Lower Bound)

creator_follower_count_maxType: integer

Follower count of the post's creator. (Inclusive Upper Bound)

creator_follower_count_minType: integer

Follower count of the post's creator. (Inclusive Lower Bound)

earned_media_value_cents_maxType: integer

Estimated earned media value, in cents. (Inclusive Upper Bound)

earned_media_value_cents_minType: integer

Estimated earned media value, in cents. (Inclusive Lower Bound)

engagement_rate_maxType: number(float)

Engagement as a fraction of views (for example, 0.05 = 5%). (Inclusive Upper Bound)

engagement_rate_minType: number(float)

Engagement as a fraction of views (for example, 0.05 = 5%). (Inclusive Lower Bound)

like_count_maxType: integer

Number of likes on the post. (Inclusive Upper Bound)

like_count_minType: integer

Number of likes on the post. (Inclusive Lower Bound)

media_duration_maxType: number(float)

Length of the media in seconds. (Inclusive Upper Bound)

media_duration_minType: number(float)

Length of the media in seconds. (Inclusive Lower Bound)

net_promoter_score_maxType: integer

Brand net promoter score for the content. Requires brand_id. (Inclusive Upper Bound)

net_promoter_score_minType: integer

Brand net promoter score for the content. Requires brand_id. (Inclusive Lower Bound)

share_count_maxType: integer

Number of shares of the post. (Inclusive Upper Bound)

share_count_minType: integer

Number of shares of the post. (Inclusive Lower Bound)

total_engagement_maxType: integer

Total engagement (likes plus comments plus shares). (Inclusive Upper Bound)

total_engagement_minType: integer

Total engagement (likes plus comments plus shares). (Inclusive Lower Bound)

view_count_maxType: integer

Number of views on the post. (Inclusive Upper Bound)

view_count_minType: integer

Number of views on the post. (Inclusive Lower Bound)

Returns Content

idType: stringread-only

Unique identifier for this piece of content. Use it to retrieve the content anywhere a content id is accepted.

platform_post_idType: string

The post's identifier on its platform. This is the value at the end of the post's URL.

Examples:

  • Instagram: https://instagram.com/reel/abcd -> abcd
  • TikTok: https://www.tiktok.com/@username/video/12345678 -> 12345678
platformType: string

The platform the content was published on: instagram, tiktok or youtube.

content_formType: stringor null

Whether the content is a video or an image.

thumbnail_urlType: stringor null

URL of the content's thumbnail image.

posted_atType: string(date-time)or null

Time the content was originally published on its platform (UTC).

view_countType: integeror null

Total number of times the content has been viewed.

like_countType: integeror null

Total number of likes the content has received.

comment_countType: integeror null

Total number of comments on the content.

share_countType: integeror null

Total number of times the content has been shared.

total_engagementType: integeror null

Sum of the likes, comments, and shares the content has received.

languageType: stringor null

ISO 639 code of the content's primary language.

media_durationType: number(double)or null

Length of the media in seconds. Null when not known.

engagement_rateType: number(double)or nullread-only

Engagement per view (likes plus comments plus shares, divided by views). Null when the content has no recorded views.

earned_media_value_centsType: integeror nullread-only

Estimated marketing value of the content, in US cents.

creatorType: ContentCreatorread-only

The creator who published the content.

Show child attributes
creator.idType: stringread-only

Unique identifier for the creator.

creator.usernameType: stringor null

The creator's username or handle on the platform (without an @).

creator.nameType: stringor null

The creator's display name on the platform.

creator.platformType: stringor null

The platform the creator publishes on. One of instagram, tiktok, youtube.

creator.platform_handleType: stringor null

The platform-side identifier of the creator's account.

creator.platform_urlType: stringor null

Direct URL to the creator's profile on the platform.

creator.profile_picture_urlType: stringor null

URL of the creator's profile picture.

creator.profile_bioType: stringor null

The creator's profile bio as it appears on the platform.

creator.follower_countType: integeror null

The creator's follower count as of the most recent observation.

creator.active_content_countType: integeror null

Number of active content items attributed to the creator.

brand_idType: stringor nullread-only

Identifier of the brand that the brand-specific signals on this row (is_owned, is_tagged, is_influencer, mention_type, net_promoter_score) are scoped to. Returned as null when the request omits brand_id.

net_promoter_scoreType: integeror nullread-only

Net promoter score for the content from the perspective of the scoped brand. Returned as null when the request omits brand_id.

is_ownedType: booleanor nullread-only

Whether the scoped brand owns the content; that is, whether it was published by an account the brand controls. Returned as null when the request omits brand_id.

is_taggedType: booleanor nullread-only

Whether the post tags the scoped brand on the platform. Returned as null when the request omits brand_id.

is_influencerType: booleanor nullread-only

Whether the scoped brand counts the content as influencer content: it matches the brand's influencer terms, comes from an account on its influencer list, was reported as branded content by the platform, or was marked by hand. Content the brand owns is never influencer content. Returned as null when the request omits brand_id.

mention_typeType: stringor nullread-only

How the scoped brand is mentioned in the content. One of content or comment, or null when the brand is not mentioned. Returned as null when the request omits brand_id.

captionType: string

Short caption or title of the post (the primary user-visible text).

descriptionType: string

Long-form description of the post.

transcriptType: stringor null

Transcribed speech from the content's audio, when available.

platform_urlType: string

Direct URL to the post on its platform.

Examples:

  • https://instagram.com/reel/abcd
  • https://www.tiktok.com/@username/video/12345678
last_keywordType: stringor null

What the content was most recently collected under: a hashtag, a creator handle, a search term, or a brand identifier. Null when the content did not arrive through a collection task.

ai_summaryType: stringor null

Short AI-generated summary of the content.

hashtagsType: string[]

Hashtags used in the post, normalized to lowercase and without the leading #.

Responses

Content

idType: stringread-only

Unique identifier for this piece of content. Use it to retrieve the content anywhere a content id is accepted.

platform_post_idType: string

The post's identifier on its platform. This is the value at the end of the post's URL.

Examples:

  • Instagram: https://instagram.com/reel/abcd -> abcd
  • TikTok: https://www.tiktok.com/@username/video/12345678 -> 12345678
platformType: string

The platform the content was published on: instagram, tiktok or youtube.

content_formType: stringor null

Whether the content is a video or an image.

thumbnail_urlType: stringor null

URL of the content's thumbnail image.

posted_atType: string(date-time)or null

Time the content was originally published on its platform (UTC).

view_countType: integeror null

Total number of times the content has been viewed.

like_countType: integeror null

Total number of likes the content has received.

comment_countType: integeror null

Total number of comments on the content.

share_countType: integeror null

Total number of times the content has been shared.

total_engagementType: integeror null

Sum of the likes, comments, and shares the content has received.

languageType: stringor null

ISO 639 code of the content's primary language.

media_durationType: number(double)or null

Length of the media in seconds. Null when not known.

engagement_rateType: number(double)or nullread-only

Engagement per view (likes plus comments plus shares, divided by views). Null when the content has no recorded views.

earned_media_value_centsType: integeror nullread-only

Estimated marketing value of the content, in US cents.

creatorType: ContentCreatorread-only

The creator who published the content.

Show child attributes
creator.idType: stringread-only

Unique identifier for the creator.

creator.usernameType: stringor null

The creator's username or handle on the platform (without an @).

creator.nameType: stringor null

The creator's display name on the platform.

creator.platformType: stringor null

The platform the creator publishes on. One of instagram, tiktok, youtube.

creator.platform_handleType: stringor null

The platform-side identifier of the creator's account.

creator.platform_urlType: stringor null

Direct URL to the creator's profile on the platform.

creator.profile_picture_urlType: stringor null

URL of the creator's profile picture.

creator.profile_bioType: stringor null

The creator's profile bio as it appears on the platform.

creator.follower_countType: integeror null

The creator's follower count as of the most recent observation.

creator.active_content_countType: integeror null

Number of active content items attributed to the creator.

brand_idType: stringor nullread-only

Identifier of the brand that the brand-specific signals on this row (is_owned, is_tagged, is_influencer, mention_type, net_promoter_score) are scoped to. Returned as null when the request omits brand_id.

net_promoter_scoreType: integeror nullread-only

Net promoter score for the content from the perspective of the scoped brand. Returned as null when the request omits brand_id.

is_ownedType: booleanor nullread-only

Whether the scoped brand owns the content; that is, whether it was published by an account the brand controls. Returned as null when the request omits brand_id.

is_taggedType: booleanor nullread-only

Whether the post tags the scoped brand on the platform. Returned as null when the request omits brand_id.

is_influencerType: booleanor nullread-only

Whether the scoped brand counts the content as influencer content: it matches the brand's influencer terms, comes from an account on its influencer list, was reported as branded content by the platform, or was marked by hand. Content the brand owns is never influencer content. Returned as null when the request omits brand_id.

mention_typeType: stringor nullread-only

How the scoped brand is mentioned in the content. One of content or comment, or null when the brand is not mentioned. Returned as null when the request omits brand_id.

captionType: string

Short caption or title of the post (the primary user-visible text).

descriptionType: string

Long-form description of the post.

transcriptType: stringor null

Transcribed speech from the content's audio, when available.

platform_urlType: string

Direct URL to the post on its platform.

Examples:

  • https://instagram.com/reel/abcd
  • https://www.tiktok.com/@username/video/12345678
last_keywordType: stringor null

What the content was most recently collected under: a hashtag, a creator handle, a search term, or a brand identifier. Null when the content did not arrive through a collection task.

ai_summaryType: stringor null

Short AI-generated summary of the content.

hashtagsType: string[]

Hashtags used in the post, normalized to lowercase and without the leading #.

Request

string
string
string
from zelf import ZelfAPIClient

client = ZelfAPIClient(api_key="<your-api-key>")

result = client.content.list()
print(result)
Response
{
  "log_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "timestamp": "2026-01-01T00:00:00Z",
  "applied_filters": {
    "search": "zelfai",
    "order_by": [
      "timestamp",
      "id"
    ],
    "posted_within_days": 7,
    "brand_id": null,
    "page": 1,
    "page_size": 30
  },
  "results": [
    {
      "id": "con_DZaWwnKo5HThZ9bu",
      "platform_post_id": "7376543210987654321",
      "platform": "instagram",
      "content_form": "VIDEO",
      "thumbnail_url": "https://cdn.hellozelf.com/thumbnails/zelfai-launch.png",
      "posted_at": "2026-05-12T16:00:00Z",
      "view_count": 184230,
      "like_count": 12840,
      "comment_count": 932,
      "share_count": 415,
      "total_engagement": 14187,
      "language": "en",
      "media_duration": 42,
      "engagement_rate": 0.077,
      "earned_media_value_cents": 248000,
      "creator": {
        "id": "cr_pfqPv0FLsBRimHfi",
        "username": "zelfai",
        "name": "Zelf",
        "platform": "instagram",
        "platform_handle": "zelfai",
        "platform_url": "https://www.instagram.com/zelfai",
        "profile_picture_url": "https://cdn.hellozelf.com/avatars/zelfai.png",
        "profile_bio": "Creator and content intelligence for modern brands.",
        "follower_count": 53120,
        "active_content_count": 217
      },
      "brand_id": "brd_Lw6ZZmNYhW0P9k0x",
      "net_promoter_score": 1,
      "is_owned": true,
      "is_tagged": true,
      "is_influencer": true,
      "mention_type": "content",
      "caption": "Behind the scenes at Zelf.",
      "description": "How Zelf turns social signals into creator insights.",
      "transcript": "We walk through how Zelf ranks creators by brand fit.",
      "platform_url": "https://www.instagram.com/zelfai",
      "last_keyword": "zelf creators",
      "ai_summary": "A product walkthrough of Zelf creator analytics.",
      "hashtags": [
        "zelfai",
        "creatoreconomy"
      ]
    }
  ],
  "item_count": 1,
  "page": 1,
  "next": null,
  "previous": null
}

Get Content Statistics

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

Returns a single aggregate of reach, engagement, value, and creator counts over the same content set that content.list would return for an identical query. The post_count is the number of posts in that whole set, across every page the list would return, and each other total is the sum over those same posts. content.list never counts the full set: its item_count is only the number of rows in the page it returned, so post_count here is the only total available.

This accepts every filter content.list accepts and applies the same defaults and requirements: every request must scope what it covers with at least one of creator_id, creator_username, search, brand_id, or external_id (else VALIDATION_ERROR); brand-only filters and sorts still require brand_id. order_by is validated the same as in content.list (brand-only sorts still require brand_id) but has no effect on the aggregated totals. Returns a single totals object (item_count: 1), not paginated, and echoes the resolved date window and brand_id in applied_filters.

Dates

content.statistics takes the same four date parameters as content.list and applies them identically. posted_after, posted_within_hours (1 to 8760) and posted_within_days (1 to 365) define the start of the window; posted_before defines the end.

A request with no date parameter covers the last 7 days. A request carrying more than one start parameter is valid, and the first present in the order posted_after, posted_within_hours, posted_within_days is applied; applied_filters reports that one. posted_after and posted_before may be at most 366 days apart.

Both endpoints apply these parameters identically, so one set of dates covers the same posts on each. post_count is therefore the size of the set content.list pages through.

Supply brand_id (one or more values, comma-separated) to scope the totals the same way the list does. Each piece of content is counted once even when several brand_id values match it.

Examples

  • Totals for a search over the last 7 days: GET /api/v1/content/statistics/?search=running+shoes
  • Brand totals over an explicit window: GET /api/v1/content/statistics/?brand_id=brd_123&posted_after=2026-01-01T00:00:00Z&posted_before=2026-06-30T23:59:59Z
  • Totals for a single platform: add &platform=tiktok.

Parameters

brand_idType: string

One or more brand ids, comma-separated, as returned by brands.list. Scopes the query to those brands, populates the brand-specific fields, and enables the brand-only filters and sorts. Any id you cannot access returns 403, and a malformed value returns INVALID_ID.

creator_idType: string

Limit results to a single creator by id (from /api/v1/creator/).

creator_usernameType: string

Creator username substring. Case-insensitive.

external_idType: string

Platform-side post id. Matched exactly.

platformType: enum[]unique items true

Platforms to include, comma-separated.

Show values
unique items
true
instagramtiktokyoutube
posted_afterType: string(date-time)

When the post was published (UTC, ISO 8601). (Inclusive Lower Bound)

posted_beforeType: string(date-time)

When the post was published (UTC, ISO 8601). (Inclusive Upper Bound)

posted_within_hoursType: integerminimum 1 · maximum 8760

Start of the window, counted back from the current time, in hours (1-8760). Takes precedence over posted_within_days. Counted back from posted_before when that is also supplied.

minimum
1
maximum
8760
posted_within_daysType: integerminimum 1 · maximum 365

Start of the window, counted back from the current time, in days (1-365). Defaults to 7 when no date parameter is supplied. posted_after and posted_within_hours take precedence over it.

minimum
1
maximum
365
order_byType: enum[]unique items true

Sort the results. Any of: posted_at, view_count, like_count, comment_count, share_count, engagement_rate, total_engagement, earned_media_value_cents, net_promoter_score, relevance_score. A bare key sorts descending; prefix with - to sort ascending.

Sort direction is inverted: order_by=field sorts descending and order_by=-field sorts ascending. Comma-separate to sort by multiple fields.

Show values
unique items
true
posted_at-posted_atview_count-view_countlike_count-like_countcomment_count-comment_countshare_count-share_countengagement_rate-engagement_ratetotal_engagement-total_engagementearned_media_value_cents-earned_media_value_centsnet_promoter_score-net_promoter_scorerelevance_score-relevance_score
comment_countType: integer

Number of comments on the post.

content_formType: enum

Content medium. Case-sensitive; values are stored and returned in uppercase.

Show values
VIDEOPHOTO
creator_follower_countType: integer

Follower count of the post's creator.

earned_media_value_centsType: integer

Estimated earned media value, in cents.

engagement_rateType: number(float)

Engagement as a fraction of views (for example, 0.05 = 5%).

is_influencerType: boolean

Limit results to the brand's influencer content, or exclude it with false. Requires brand_id.

is_ownedType: boolean

Limit results to content owned by the brand. Requires brand_id.

is_taggedType: boolean

Limit results to content where the brand is tagged. Requires brand_id.

languageType: string[]

Language codes to include, comma-separated (for example, en, es).

like_countType: integer

Number of likes on the post.

media_durationType: number(float)

Length of the media in seconds.

mention_typeType: enum[]unique items true

Limit results to these mention kinds, comma-separated. Requires brand_id.

Show values
unique items
true
contentcomment
mention_type_notType: enum[]unique items true

Exclude these mention kinds, comma-separated. Requires brand_id.

Show values
unique items
true
contentcomment
net_promoter_scoreType: integer

Brand net promoter score for the content. Requires brand_id.

postedType: string(date-time)

When the post was published (UTC, ISO 8601).

share_countType: integer

Number of shares of the post.

total_engagementType: integer

Total engagement (likes plus comments plus shares).

view_countType: integer

Number of views on the post.

comment_count_maxType: integer

Number of comments on the post. (Inclusive Upper Bound)

comment_count_minType: integer

Number of comments on the post. (Inclusive Lower Bound)

creator_follower_count_maxType: integer

Follower count of the post's creator. (Inclusive Upper Bound)

creator_follower_count_minType: integer

Follower count of the post's creator. (Inclusive Lower Bound)

earned_media_value_cents_maxType: integer

Estimated earned media value, in cents. (Inclusive Upper Bound)

earned_media_value_cents_minType: integer

Estimated earned media value, in cents. (Inclusive Lower Bound)

engagement_rate_maxType: number(float)

Engagement as a fraction of views (for example, 0.05 = 5%). (Inclusive Upper Bound)

engagement_rate_minType: number(float)

Engagement as a fraction of views (for example, 0.05 = 5%). (Inclusive Lower Bound)

like_count_maxType: integer

Number of likes on the post. (Inclusive Upper Bound)

like_count_minType: integer

Number of likes on the post. (Inclusive Lower Bound)

media_duration_maxType: number(float)

Length of the media in seconds. (Inclusive Upper Bound)

media_duration_minType: number(float)

Length of the media in seconds. (Inclusive Lower Bound)

net_promoter_score_maxType: integer

Brand net promoter score for the content. Requires brand_id. (Inclusive Upper Bound)

net_promoter_score_minType: integer

Brand net promoter score for the content. Requires brand_id. (Inclusive Lower Bound)

share_count_maxType: integer

Number of shares of the post. (Inclusive Upper Bound)

share_count_minType: integer

Number of shares of the post. (Inclusive Lower Bound)

total_engagement_maxType: integer

Total engagement (likes plus comments plus shares). (Inclusive Upper Bound)

total_engagement_minType: integer

Total engagement (likes plus comments plus shares). (Inclusive Lower Bound)

view_count_maxType: integer

Number of views on the post. (Inclusive Upper Bound)

view_count_minType: integer

Number of views on the post. (Inclusive Lower Bound)

Returns ContentStatistics

post_countType: integer

Number of unique pieces of content in the filtered set.

total_viewsType: integer

Total views across the filtered set.

total_likesType: integer

Total likes across the filtered set.

total_commentsType: integer

Total comments across the filtered set.

total_sharesType: integer

Total shares across the filtered set.

total_engagementType: integer

Total engagement (likes + comments + shares) across the filtered set.

total_earned_media_value_centsType: integer

Total estimated marketing value across the filtered set, in US cents. Each piece of content contributes once even when multiple brand contexts match it through brand_id.

total_media_durationType: number(double)

Total media length in seconds across the filtered set.

engagement_rateType: number(double)or null

Total engagement divided by total views across the filtered set. Null when the filtered set has no recorded views.

unique_creator_countType: integer

Number of distinct creators represented in the filtered set.

Responses

ContentStatistics

post_countType: integer

Number of unique pieces of content in the filtered set.

total_viewsType: integer

Total views across the filtered set.

total_likesType: integer

Total likes across the filtered set.

total_commentsType: integer

Total comments across the filtered set.

total_sharesType: integer

Total shares across the filtered set.

total_engagementType: integer

Total engagement (likes + comments + shares) across the filtered set.

total_earned_media_value_centsType: integer

Total estimated marketing value across the filtered set, in US cents. Each piece of content contributes once even when multiple brand contexts match it through brand_id.

total_media_durationType: number(double)

Total media length in seconds across the filtered set.

engagement_rateType: number(double)or null

Total engagement divided by total views across the filtered set. Null when the filtered set has no recorded views.

unique_creator_countType: integer

Number of distinct creators represented in the filtered set.

Request

string
string
string
from zelf import ZelfAPIClient

client = ZelfAPIClient(api_key="<your-api-key>")

result = client.content.statistics()
print(result)
Response
{
  "log_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "timestamp": "2026-01-01T00:00:00Z",
  "applied_filters": {
    "search": "zelfai",
    "order_by": [
      "timestamp",
      "id"
    ],
    "posted_within_days": 7,
    "brand_id": null
  },
  "results": [
    {
      "post_count": 1280,
      "total_views": 4500000,
      "total_likes": 320000,
      "total_comments": 18000,
      "total_shares": 9500,
      "total_engagement": 347500,
      "total_earned_media_value_cents": 12500000,
      "total_media_duration": 53400,
      "engagement_rate": 0.077,
      "unique_creator_count": 412
    }
  ],
  "item_count": 1,
  "page": 1,
  "next": null,
  "previous": null
}

Create Content Discovery

POST/api/v1/content/discovery/content.discover

Starts an asynchronous job that indexes fresh content matching a search term across the requested platforms. Use it to ingest content Zelf does not yet cover.

The response describes the job, not the content itself. Once the job completes, query content.list to retrieve the indexed content. An identical term requested again within the deduplication window reuses the in-flight job and returns dispatched: false instead of starting a new one.

Request body

search_termType: stringRequiredmin length 1

The term to index content for (for example, nike running). Matching content is indexed asynchronously.

min length
1
platformsType: enum[]default instagram,tiktok,youtube

Platforms to index (instagram, tiktok, youtube). Defaults to all platforms when omitted.

Show values
default
instagram,tiktok,youtube
instagramtiktokyoutube

Returns ContentDiscovery

idType: stringread-only

Identifier of the discovery job. Use it to track the job's status.

search_termType: string

The search term the discovery job was started for.

created_atType: string(date-time)

When the discovery job was created (UTC, ISO 8601).

updated_atType: string(date-time)

Time of the most recent change to the discovery job (UTC, ISO 8601).

platformsType: string[]or null

Platforms the indexing job was dispatched to.

statusType: stringread-only

Status of the discovery job. One of PENDING, IN_PROGRESS, COMPLETED, FAILED, CANCELLED.

dispatchedType: booleanread-only

Whether a new indexing job was dispatched. Returns false when an identical search term was already requested within the recent deduplication window, in which case the in-flight job is reused.

Responses

ContentDiscovery

idType: stringread-only

Identifier of the discovery job. Use it to track the job's status.

search_termType: string

The search term the discovery job was started for.

created_atType: string(date-time)

When the discovery job was created (UTC, ISO 8601).

updated_atType: string(date-time)

Time of the most recent change to the discovery job (UTC, ISO 8601).

platformsType: string[]or null

Platforms the indexing job was dispatched to.

statusType: stringread-only

Status of the discovery job. One of PENDING, IN_PROGRESS, COMPLETED, FAILED, CANCELLED.

dispatchedType: booleanread-only

Whether a new indexing job was dispatched. Returns false when an identical search term was already requested within the recent deduplication window, in which case the in-flight job is reused.

Request

stringRequired
platformsenum[]
from zelf import ZelfAPIClient

client = ZelfAPIClient(api_key="<your-api-key>")

result = client.content.discover(
    search_term="zelf creators",
    platforms=["instagram", "tiktok"],
)
print(result)
Response
{
  "log_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "timestamp": "2026-01-01T00:00:00Z",
  "results": [
    {
      "id": "sas_rVCYR6uQsQNCDRnY",
      "search_term": "zelf creators",
      "created_at": "2026-05-12T14:30:00Z",
      "updated_at": "2026-05-12T15:00:00Z",
      "platforms": [
        "instagram",
        "tiktok"
      ],
      "status": "COMPLETED",
      "dispatched": true
    }
  ],
  "item_count": 1,
  "page": 1,
  "next": null,
  "previous": null
}

Transcribe Content

POST/api/v1/content/transcribe/content.transcribe

Transcribes the speech in the content's audio or video into text. Returns 202 with status: PENDING when a run starts. Call again to follow it: PENDING while it runs, COMPLETED once the content has a transcription, FAILED if all 3 tries failed.

Request body

content_idType: stringRequiredmin length 1

Identifier of the content, as returned by content.list.

min length
1

Returns ContentActionResponse

content_idType: string

Identifier of the content.

statusType: string

PENDING when the work was queued, COMPLETED when the content already has the result.

Responses

COMPLETED: the result is ready. PENDING: the run is still going. FAILED: all 3 tries failed.

ContentActionResponse

content_idType: string

Identifier of the content.

statusType: string

PENDING when the work was queued, COMPLETED when the content already has the result.

Request

stringRequired
from zelf import ZelfAPIClient

client = ZelfAPIClient(api_key="<your-api-key>")

result = client.content.transcribe(
    content_id="con_DZaWwnKo5HThZ9bu",
)
print(result)
Response
{
  "log_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "timestamp": "2026-01-01T00:00:00Z",
  "results": [
    {
      "content_id": "con_DZaWwnKo5HThZ9bu",
      "status": "COMPLETED"
    }
  ],
  "item_count": 1,
  "page": 1,
  "next": null,
  "previous": null
}

AI Summarize Content

POST/api/v1/content/ai_summarize/content.ai_summarize

Writes a short AI summary of what the content is about. Returns 202 with status: PENDING when a run starts. Call again to follow it: PENDING while it runs, COMPLETED once the content has a summary, FAILED if all 3 tries failed.

Request body

content_idType: stringRequiredmin length 1

Identifier of the content, as returned by content.list.

min length
1

Returns ContentActionResponse

content_idType: string

Identifier of the content.

statusType: string

PENDING when the work was queued, COMPLETED when the content already has the result.

Responses

COMPLETED: the result is ready. PENDING: the run is still going. FAILED: all 3 tries failed.

ContentActionResponse

content_idType: string

Identifier of the content.

statusType: string

PENDING when the work was queued, COMPLETED when the content already has the result.

Request

stringRequired
from zelf import ZelfAPIClient

client = ZelfAPIClient(api_key="<your-api-key>")

result = client.content.ai_summarize(
    content_id="con_DZaWwnKo5HThZ9bu",
)
print(result)
Response
{
  "log_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "timestamp": "2026-01-01T00:00:00Z",
  "results": [
    {
      "content_id": "con_DZaWwnKo5HThZ9bu",
      "status": "COMPLETED"
    }
  ],
  "item_count": 1,
  "page": 1,
  "next": null,
  "previous": null
}

Get Content

GET/api/v1/content/{id}/content.details

Returns a single piece of content identified by id.

Supply brand_id to additionally require the content to exist under that brand and to populate the brand-specific fields. If the content does not exist under that brand, the response is an empty result set rather than a 404. When brand_id is omitted, the brand-specific fields are returned as null.

Parameters

idType: stringRequired
brand_idType: string

Optional brand id. When supplied, the content must exist under that brand, otherwise the response is an empty result set. Populates the brand-specific response fields.

Returns Content

idType: stringread-only

Unique identifier for this piece of content. Use it to retrieve the content anywhere a content id is accepted.

platform_post_idType: string

The post's identifier on its platform. This is the value at the end of the post's URL.

Examples:

  • Instagram: https://instagram.com/reel/abcd -> abcd
  • TikTok: https://www.tiktok.com/@username/video/12345678 -> 12345678
platformType: string

The platform the content was published on: instagram, tiktok or youtube.

content_formType: stringor null

Whether the content is a video or an image.

thumbnail_urlType: stringor null

URL of the content's thumbnail image.

posted_atType: string(date-time)or null

Time the content was originally published on its platform (UTC).

view_countType: integeror null

Total number of times the content has been viewed.

like_countType: integeror null

Total number of likes the content has received.

comment_countType: integeror null

Total number of comments on the content.

share_countType: integeror null

Total number of times the content has been shared.

total_engagementType: integeror null

Sum of the likes, comments, and shares the content has received.

languageType: stringor null

ISO 639 code of the content's primary language.

media_durationType: number(double)or null

Length of the media in seconds. Null when not known.

engagement_rateType: number(double)or nullread-only

Engagement per view (likes plus comments plus shares, divided by views). Null when the content has no recorded views.

earned_media_value_centsType: integeror nullread-only

Estimated marketing value of the content, in US cents.

creatorType: ContentCreatorread-only

The creator who published the content.

Show child attributes
creator.idType: stringread-only

Unique identifier for the creator.

creator.usernameType: stringor null

The creator's username or handle on the platform (without an @).

creator.nameType: stringor null

The creator's display name on the platform.

creator.platformType: stringor null

The platform the creator publishes on. One of instagram, tiktok, youtube.

creator.platform_handleType: stringor null

The platform-side identifier of the creator's account.

creator.platform_urlType: stringor null

Direct URL to the creator's profile on the platform.

creator.profile_picture_urlType: stringor null

URL of the creator's profile picture.

creator.profile_bioType: stringor null

The creator's profile bio as it appears on the platform.

creator.follower_countType: integeror null

The creator's follower count as of the most recent observation.

creator.active_content_countType: integeror null

Number of active content items attributed to the creator.

brand_idType: stringor nullread-only

Identifier of the brand that the brand-specific signals on this row (is_owned, is_tagged, is_influencer, mention_type, net_promoter_score) are scoped to. Returned as null when the request omits brand_id.

net_promoter_scoreType: integeror nullread-only

Net promoter score for the content from the perspective of the scoped brand. Returned as null when the request omits brand_id.

is_ownedType: booleanor nullread-only

Whether the scoped brand owns the content; that is, whether it was published by an account the brand controls. Returned as null when the request omits brand_id.

is_taggedType: booleanor nullread-only

Whether the post tags the scoped brand on the platform. Returned as null when the request omits brand_id.

is_influencerType: booleanor nullread-only

Whether the scoped brand counts the content as influencer content: it matches the brand's influencer terms, comes from an account on its influencer list, was reported as branded content by the platform, or was marked by hand. Content the brand owns is never influencer content. Returned as null when the request omits brand_id.

mention_typeType: stringor nullread-only

How the scoped brand is mentioned in the content. One of content or comment, or null when the brand is not mentioned. Returned as null when the request omits brand_id.

captionType: string

Short caption or title of the post (the primary user-visible text).

descriptionType: string

Long-form description of the post.

transcriptType: stringor null

Transcribed speech from the content's audio, when available.

platform_urlType: string

Direct URL to the post on its platform.

Examples:

  • https://instagram.com/reel/abcd
  • https://www.tiktok.com/@username/video/12345678
last_keywordType: stringor null

What the content was most recently collected under: a hashtag, a creator handle, a search term, or a brand identifier. Null when the content did not arrive through a collection task.

ai_summaryType: stringor null

Short AI-generated summary of the content.

hashtagsType: string[]

Hashtags used in the post, normalized to lowercase and without the leading #.

Responses

Content

idType: stringread-only

Unique identifier for this piece of content. Use it to retrieve the content anywhere a content id is accepted.

platform_post_idType: string

The post's identifier on its platform. This is the value at the end of the post's URL.

Examples:

  • Instagram: https://instagram.com/reel/abcd -> abcd
  • TikTok: https://www.tiktok.com/@username/video/12345678 -> 12345678
platformType: string

The platform the content was published on: instagram, tiktok or youtube.

content_formType: stringor null

Whether the content is a video or an image.

thumbnail_urlType: stringor null

URL of the content's thumbnail image.

posted_atType: string(date-time)or null

Time the content was originally published on its platform (UTC).

view_countType: integeror null

Total number of times the content has been viewed.

like_countType: integeror null

Total number of likes the content has received.

comment_countType: integeror null

Total number of comments on the content.

share_countType: integeror null

Total number of times the content has been shared.

total_engagementType: integeror null

Sum of the likes, comments, and shares the content has received.

languageType: stringor null

ISO 639 code of the content's primary language.

media_durationType: number(double)or null

Length of the media in seconds. Null when not known.

engagement_rateType: number(double)or nullread-only

Engagement per view (likes plus comments plus shares, divided by views). Null when the content has no recorded views.

earned_media_value_centsType: integeror nullread-only

Estimated marketing value of the content, in US cents.

creatorType: ContentCreatorread-only

The creator who published the content.

Show child attributes
creator.idType: stringread-only

Unique identifier for the creator.

creator.usernameType: stringor null

The creator's username or handle on the platform (without an @).

creator.nameType: stringor null

The creator's display name on the platform.

creator.platformType: stringor null

The platform the creator publishes on. One of instagram, tiktok, youtube.

creator.platform_handleType: stringor null

The platform-side identifier of the creator's account.

creator.platform_urlType: stringor null

Direct URL to the creator's profile on the platform.

creator.profile_picture_urlType: stringor null

URL of the creator's profile picture.

creator.profile_bioType: stringor null

The creator's profile bio as it appears on the platform.

creator.follower_countType: integeror null

The creator's follower count as of the most recent observation.

creator.active_content_countType: integeror null

Number of active content items attributed to the creator.

brand_idType: stringor nullread-only

Identifier of the brand that the brand-specific signals on this row (is_owned, is_tagged, is_influencer, mention_type, net_promoter_score) are scoped to. Returned as null when the request omits brand_id.

net_promoter_scoreType: integeror nullread-only

Net promoter score for the content from the perspective of the scoped brand. Returned as null when the request omits brand_id.

is_ownedType: booleanor nullread-only

Whether the scoped brand owns the content; that is, whether it was published by an account the brand controls. Returned as null when the request omits brand_id.

is_taggedType: booleanor nullread-only

Whether the post tags the scoped brand on the platform. Returned as null when the request omits brand_id.

is_influencerType: booleanor nullread-only

Whether the scoped brand counts the content as influencer content: it matches the brand's influencer terms, comes from an account on its influencer list, was reported as branded content by the platform, or was marked by hand. Content the brand owns is never influencer content. Returned as null when the request omits brand_id.

mention_typeType: stringor nullread-only

How the scoped brand is mentioned in the content. One of content or comment, or null when the brand is not mentioned. Returned as null when the request omits brand_id.

captionType: string

Short caption or title of the post (the primary user-visible text).

descriptionType: string

Long-form description of the post.

transcriptType: stringor null

Transcribed speech from the content's audio, when available.

platform_urlType: string

Direct URL to the post on its platform.

Examples:

  • https://instagram.com/reel/abcd
  • https://www.tiktok.com/@username/video/12345678
last_keywordType: stringor null

What the content was most recently collected under: a hashtag, a creator handle, a search term, or a brand identifier. Null when the content did not arrive through a collection task.

ai_summaryType: stringor null

Short AI-generated summary of the content.

hashtagsType: string[]

Hashtags used in the post, normalized to lowercase and without the leading #.

Request

stringRequired
string
from zelf import ZelfAPIClient

client = ZelfAPIClient(api_key="<your-api-key>")

result = client.content.details("<id>")
print(result)
Response
{
  "log_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "timestamp": "2026-01-01T00:00:00Z",
  "results": [
    {
      "id": "con_DZaWwnKo5HThZ9bu",
      "platform_post_id": "7376543210987654321",
      "platform": "instagram",
      "content_form": "VIDEO",
      "thumbnail_url": "https://cdn.hellozelf.com/thumbnails/zelfai-launch.png",
      "posted_at": "2026-05-12T16:00:00Z",
      "view_count": 184230,
      "like_count": 12840,
      "comment_count": 932,
      "share_count": 415,
      "total_engagement": 14187,
      "language": "en",
      "media_duration": 42,
      "engagement_rate": 0.077,
      "earned_media_value_cents": 248000,
      "creator": {
        "id": "cr_pfqPv0FLsBRimHfi",
        "username": "zelfai",
        "name": "Zelf",
        "platform": "instagram",
        "platform_handle": "zelfai",
        "platform_url": "https://www.instagram.com/zelfai",
        "profile_picture_url": "https://cdn.hellozelf.com/avatars/zelfai.png",
        "profile_bio": "Creator and content intelligence for modern brands.",
        "follower_count": 53120,
        "active_content_count": 217
      },
      "brand_id": "brd_Lw6ZZmNYhW0P9k0x",
      "net_promoter_score": 1,
      "is_owned": true,
      "is_tagged": true,
      "is_influencer": true,
      "mention_type": "content",
      "caption": "Behind the scenes at Zelf.",
      "description": "How Zelf turns social signals into creator insights.",
      "transcript": "We walk through how Zelf ranks creators by brand fit.",
      "platform_url": "https://www.instagram.com/zelfai",
      "last_keyword": "zelf creators",
      "ai_summary": "A product walkthrough of Zelf creator analytics.",
      "hashtags": [
        "zelfai",
        "creatoreconomy"
      ]
    }
  ],
  "item_count": 1,
  "page": 1,
  "next": null,
  "previous": null
}