GET /v1/profile/posts
A page of a profile's recent posts, newest first, with an opaque cursor. One page is one charge.
This is the original generic endpoint, and it is still supported. It returns one normalized shape across every platform. The product now leads with named APIs (
/v1/tiktok/postsand/v1/instagram/posts), which answer in each platform’s own vocabulary. Nothing here is deprecated; the named APIs are simply what the rest of the docs use.
Request
GET /v1/profile/posts
Authorization: Bearer sv_live_…
| Parameter | Type | Required | Notes |
|---|---|---|---|
url |
string | one of | Profile URL |
platform + username |
string | one of | Alternative to url |
cursor |
string | no | From next_cursor of the previous page |
limit |
int | no | 1–50, default 20 |
Cost: per page, regardless of limit: 1 credit on TikTok and X, 4 on
Instagram.
Fetching 50 in one page costs the same as fetching 10, so use a larger limit
when you know you want the volume.
Example
curl https://api.sourcevine.io/v1/profile/posts \
-H "Authorization: Bearer $SOURCEVINE_API_KEY" \
--data-urlencode "url=https://www.tiktok.com/@atlas.makes" \
--data-urlencode "limit=20" -G
{
"items": [
{
"id": "sd_post_1c7be04a92f3d558",
"platform": "tiktok",
"resource_type": "post",
"platform_resource_id": "7042118893001",
"author": { "platform_resource_id": "6789432100", "username": "atlas.makes" },
"url": "https://www.tiktok.com/@atlas.makes/video/7042118893001",
"caption": "the jig that finally worked",
"media_type": "video",
"published_at": "2026-08-20T09:00:00Z",
"metrics": {
"views": 412000, "likes": 38400, "comments": 921,
"shares": 2140, "saves": 6630
}
}
],
"next_cursor": "eyJvIjoyMH0",
"availability": { "status": "available", "reason": null },
"fetched_at": "2026-08-27T09:41:02Z",
"cache_age_seconds": 0,
"freshness": "fresh"
}
Paginating
next_cursor is opaque. Do not parse it, construct it, or store it long term.
It is null on the last page.
cursor, posts = None, []
while True:
r = client.get("/v1/profile/posts",
params={"url": url, "limit": 50, "cursor": cursor}).json()
posts += r["items"]
cursor = r.get("next_cursor")
if not cursor:
break
Each iteration is a separate billable page. A profile with 600 posts is 12 pages
at limit=50, so 24 credits. Plan for that before you loop over a list of
creators.
Notes
- Newest first, always.
- Pinned posts may appear out of chronological order on platforms that
support pinning. Sort by
published_atif strict ordering matters. - Depth varies by platform. The available history depends on the platform and resource. Sourcevine returns the history available for that lookup.
- A cursor can go stale. If the profile posts while you are paginating, a
later page may shift. For exact snapshots, record
fetched_atper page.
Last updated 4 October 2026