SocialHz Engineering · 26 October 2026 · Requested by a customer
One search endpoint, seven platforms, one post schema
GET /api/v1/search · GET /api/v1/search/platforms
What shipped
GET /api/v1/search takes a platform and a query and returns posts from x, instagram, facebook, youtube, tiktok, reddit or linkedin. Every post has the same fields on every platform. When a platform doesn't give a value, the field is null, never a made-up false or 0.
Why
An insights team was pulling posts from each platform separately and spending hours mapping columns before any analysis. They asked for one request shape and one response shape.
Request
GET /api/v1/search?platform=tiktok&query=electric+vehicles
&start_date=2026-10-20&end_date=2026-10-25&sort_by=engagement&pages=2
X-API-Key: <your key>The post schema
Every post carries every field below. A table in the API reference lists which platform fills which field, measured on real results.
- id, url, platform, title, text, published_at (ISO 8601, UTC), language, content_type
- author_id, author_username, author_name, author_profile_url, author_verified, author_followers
- like_count, comments_count, share_count, save_count, view_count, impression_count
- hashtags, mentions, and media[] with url, type, width, height and duration_seconds
- metrics_captured_at: when the counts were read, so you know how fresh each number is
Filters, and what a platform can't do
sort_by (recent, relevance, engagement), region, language and start_date/end_date go to the platform where it supports them. Where it doesn't, the posts on each page are filtered instead, and filters.notes says so. A filter that can't be applied at all is listed in filters.ignored. Nothing is dropped without telling you.
On top of that: author, exclude_author, content_type, has_media, verified_only, hashtags and min_likes, min_comments, min_shares, min_views, min_followers. Because filtering can leave a page short, page_size (1 to 200) keeps fetching pages until it has that many posts.
Paging
- has_more and next_cursor. Send the cursor back as cursor with the same parameters.
- The cursor is sealed to that search and that workspace. A cursor that doesn't fit is refused with 400 invalid_cursor before anything is charged.
- A post shown on one page is never shown again on a later page of the same search.
- Searches have no total: no platform says how many posts match, so progress.expected_total is null for search. Page until has_more is false.
A summary with every answer
summary is worked out from the posts in that answer: posts per_day, engagement totals and averages (with known, the number of posts that had the value), top_posts, top_authors, top_hashtags, content_types and languages. Send summary=false to leave it out.
Request a feature
Tell us what you need on the updates page. The engineering team reads every request.