Skip to main content

Analytics API

GET /api/analytics/profile_username

Retrieves analytics data for a specified user profile across one or more social media platforms.


Method: GET

Endpoint URL: https://api.upload-post.com/api/analytics/profile_username

Description:

This endpoint provides key analytics metrics for a given social media profile associated with a user's account. It allows fetching data for multiple platforms in a single request. The system is designed to be extensible, with support for more platforms planned for the future.

Authentication:

A valid JSON Web Token (JWT) is required for authentication. The token must be included in the Authorization header as a Apikey token.

Authorization: Apikey <YOUR_JWT_TOKEN>

Parameters:

ParameterTypeLocationRequiredDescription
profile_usernamestringPathYesThe unique username of the profile for which you want to retrieve analytics.
platformsstringQueryYesA comma-separated list of platforms to fetch analytics for. E.g., ?platforms=instagram,youtube,threads,pinterest,reddit.
page_idstringQueryNoRequired for Facebook analytics. The ID of the Facebook Page.
daysnumberQueryNoFacebook only. Size of the insights window in days, 1365 (default 30). Metrics and time series are fetched live from Meta for exactly this range, so ?days=7, ?days=90 or any custom value returns actual impressions/reach for that period. Ranges over 90 days are fetched in chunks transparently.
page_urnstringQueryNoLinkedIn only. Organization/company page URN or numeric ID to fetch analytics for. LinkedIn analytics are available only for organization/company pages you administer — personal profiles are not supported, because LinkedIn's API does not expose member-level analytics. If omitted, the first administered organization page is used.

Supported Platforms:

Currently, the following platforms are supported:

  • instagram
  • tiktok
  • Linkedin
  • Facebook
  • X (Twitter)
  • youtube
  • threads
  • pinterest
  • reddit
  • bluesky

Support for additional platforms will be added in the future. If you request a platform that is not yet supported, the response will include a message indicating this for that specific platform.

Note: Discord, Telegram, and the credential-based channels (Slack, Mastodon, Nostr, Lemmy, Dev.to, Hashnode, WordPress, Whop, Listmonk) do not support analytics. Requesting analytics for any of them returns a graceful per-platform message (e.g. "Analytics are not supported for Discord.") rather than an error, so a mixed request for other platforms still succeeds.

Here is an example of how to call the endpoint to get analytics for the test profile on Instagram, YouTube, Threads, Pinterest, and Reddit.

curl 'https://api.upload-post.com/api/analytics/test?platforms=instagram,youtube,threads,pinterest,reddit' \
--header 'Authorization: Apikey XXX...'

Example Successful Response (200 OK):

The response is a JSON object where each key corresponds to a requested platform. The value is another object containing the specific analytics data for that platform.

{
"instagram": {
"followers": 47,
"reach": 1250,
"views": 3400,
"impressions": 3400,
"profileViews": 89,
"likes": 120,
"comments": 15,
"shares": 8,
"saves": 22,
"reach_timeseries": [
{
"date": "2025-07-04",
"value": 42
},
{
"date": "2025-07-05",
"value": 55
},
// ... more date entries
{
"date": "2025-08-02",
"value": 38
}
],
"follower_demographics": {
"age": { "25-34": 100, "35-44": 166, "45-54": 49 },
"gender": { "F": 74, "M": 36, "U": 24 },
"country": { "ES": 78, "CO": 13, "PE": 8 },
"city": { "Madrid, Comunidad de Madrid": 18, "Barcelona, Cataluña": 2 }
},
"engaged_audience_demographics": {
"age": { "25-34": 61, "35-44": 88, "45-54": 20 },
"gender": { "F": 44, "M": 21, "U": 9 },
"country": { "ES": 52, "CO": 7, "PE": 4 },
"city": { "Madrid, Comunidad de Madrid": 11, "Barcelona, Cataluña": 1 }
},
"metric_type": "reach"
}
}

Field Descriptions for Platform Analytics:

  • followers: Total number of followers.
  • reach: The number of unique accounts that have seen any of the profile's content.
  • views: Total content views (Instagram, YouTube, TikTok). For Instagram, this is the official "views" metric from the Instagram API, which replaced the deprecated "impressions" metric.
  • impressions: Alias for views on Instagram, YouTube, and TikTok. On other platforms (X, Pinterest, Threads), this represents content impressions. Kept for backwards compatibility.
  • profileViews: Total number of times the profile was viewed. For Instagram, this represents "Accounts Engaged" (unique accounts that interacted with the content).
  • likes: Total number of likes across the profile's content.
  • comments: Total number of comments across the profile's content.
  • shares: Total number of shares across the profile's content.
  • saves: Total number of saves across the profile's content.
  • watch_time_minutes (YouTube only): Total watch time in minutes over the last 30 days (YouTube Analytics estimatedMinutesWatched).
  • average_view_duration_seconds (YouTube only): Average view duration derived from watch time and views.
  • engagement (Bluesky only): Likes + reposts + replies + quotes received by the profile's own posts of the last 30 days. Bluesky has no impressions/reach API, so this is the headline metric and what reach_timeseries charts (by post date, metric_type: "engagement"). following, posts_count and quotes are also returned; shares are reposts and comments are replies.
  • pin_clicks: Total number of clicks on pins (Pinterest only).
  • outbound_clicks: Total number of clicks to external URLs from pins (Pinterest only).
  • reach_timeseries: An array of objects showing the daily reach or views value over the last 30 days (or, for Facebook, over the window selected with days). The dashboard filters this data client-side based on the selected date range.
  • impressions_timeseries (Facebook only): Array of { date, value } objects with the actual daily impressions for the requested window, suitable for charting. Same window as reach_timeseries.
  • period_days (Facebook only): Echo of the insights window actually used, in days.
  • follower_demographics (Instagram only): Audience breakdown of the profile's followers as { age, gender, country, city }, each a map of segment → follower count (gender values F/M/U; country as ISO codes). Sourced from the Instagram follower_demographics insight over the last 30 days. Only returned for accounts with 100+ followers — smaller accounts return {} (Meta restriction).
  • engaged_audience_demographics (Instagram only): Same shape as follower_demographics ({ age, gender, country, city }), but broken down by the accounts that engaged with the content rather than by followers. Sourced from the Instagram engaged_audience_demographics insight over the last 30 days. See the note below on when Meta populates it.
  • metric_type: Indicates what the reach_timeseries represents for this platform. Values: "reach" (Facebook, Instagram, LinkedIn), "views" (YouTube, TikTok, Threads), "impressions" (X, Pinterest), "score" (Reddit). Use this to avoid double-counting when aggregating across platforms.
  • primary_impressions_field: The field name used as the primary metric for aggregation on this platform (e.g., "reach" for Instagram, "impressions" for YouTube).
  • available_metrics: Array of available metric keys for this platform.
  • metric_labels: Object mapping metric keys to user-friendly labels for this platform.

Instagram Demographics (follower_demographics and engaged_audience_demographics):

Both objects have the same structure and are broken down by age, gender, country and city. They answer two different questions:

FieldPopulation measured
follower_demographicsEveryone who follows the account
engaged_audience_demographicsOnly the accounts that engaged with the account's content
Meta thresholds

These are Meta restrictions, not Upload-Post ones:

  • follower_demographics is only populated for accounts with 100+ followers.
  • engaged_audience_demographics is only populated once the engaged audience clears its own floor of roughly 100 accounts, and it lands with a lag of roughly 48 hours.

Below those thresholds Meta returns nothing, and the API surfaces that as empty objects ({"age": {}, "gender": {}, "country": {}, "city": {}} — or {}) rather than as an error. A brand-new or small account will therefore see empty demographics for a while; treat empty as "not enough data yet", not as a failure.

For a unified total impressions metric across platforms, see the Total Impressions section below.

Error Responses:

  • 400 Bad Request: The platforms query parameter is missing or invalid.
  • 401 Unauthorized: The JWT is missing, invalid, or expired.
  • 404 Not Found: The specified profile_username does not exist for the authenticated user.
  • 500 Internal Server Error: An unexpected error occurred on the server while fetching the data.


title: 'Total Impressions API'

GET /api/uploadposts/total-impressions/profile_username

Returns a unified "total impressions" metric for a profile, aggregated from daily analytics snapshots across all connected platforms.


Method: GET

Endpoint URL: https://api.upload-post.com/api/uploadposts/total-impressions/profile_username

Description:

This endpoint provides a single, deduplicated "total impressions" metric that intelligently combines reach and views data across platforms. Since different platforms report different types of impression metrics (Facebook and Instagram report "reach", YouTube and TikTok report "views"), this endpoint uses the most representative metric for each platform to avoid double-counting.

You can also request custom metrics aggregation by specifying which metrics to aggregate using the metrics parameter.

Snapshot semantics — not a daily sum for every platform

This endpoint aggregates the daily stored snapshots of each profile. For platforms whose snapshot stores a rolling 30-day total (Facebook is one), summing snapshots across a date range overstates the real value — each day's snapshot already contains the previous 30 days. For actual Facebook impressions over an exact date range (7/30/90 days or custom), use GET /api/analytics/<profile>?platforms=facebook&days=N instead, which queries Meta live and also returns a daily impressions_timeseries for charting.

Authentication:

A valid JSON Web Token (JWT) is required. Include it in the Authorization header:

Authorization: Apikey <YOUR_JWT_TOKEN>

Parameters:

ParameterTypeLocationRequiredDescription
profile_usernamestringPathYesThe unique username of the profile.
datestringQueryNoSingle date in YYYY-MM-DD format. If provided, returns impressions for that day only.
start_datestringQueryNoStart of date range in YYYY-MM-DD format. Defaults to 30 days ago.
end_datestringQueryNoEnd of date range in YYYY-MM-DD format. Defaults to today.
periodstringQueryNoShortcut for date range: last_day, last_week, last_month, last_3months, last_year. Overrides start_date/end_date.
platformstringQueryNoComma-separated list of platforms to filter by. E.g., ?platform=youtube,tiktok.
breakdownstringQueryNoSet to true to include per-platform and per-day breakdown in the response.
metricsstringQueryNoComma-separated list of metrics to aggregate. E.g., ?metrics=likes,comments,shares. Available: followers, reach, views, impressions, likes, comments, shares, saves, profileViews, video_count, following, pin_clicks, outbound_clicks. When provided, returns a metrics object instead of total_impressions.

Metric Selection per Platform (default mode):

PlatformMetric UsedReason
FacebookreachReports unique account reach
InstagramreachReports unique account reach. Note: Instagram renamed "impressions" to "views" in their API; both views and impressions fields are returned.
LinkedInreachReports unique impressions
YouTubeimpressions/viewsReports video view counts
TikTokimpressions/viewsReports video view counts
XimpressionsReports tweet impression counts
Threadsimpressions/viewsReports content view counts
PinterestimpressionsReports pin impression counts
Redditimpressions/scoreReports post score as impressions proxy

Example Request:

curl 'https://api.upload-post.com/api/uploadposts/total-impressions/myprofile?start_date=2026-01-01&end_date=2026-01-31&breakdown=true' \
--header 'Authorization: Apikey XXX...'

Example Response (200 OK):

{
"success": true,
"profile_username": "myprofile",
"start_date": "2026-01-01",
"end_date": "2026-01-31",
"total_impressions": 45230,
"per_platform": {
"instagram": 12500,
"youtube": 18730,
"tiktok": 8000,
"facebook": 6000
},
"per_day": {
"2026-01-01": 1200,
"2026-01-02": 1450,
"2026-01-03": 980
}
}

Example with Period Shortcut:

curl 'https://api.upload-post.com/api/uploadposts/total-impressions/myprofile?period=last_week' \
--header 'Authorization: Apikey XXX...'
{
"success": true,
"profile_username": "myprofile",
"start_date": "2026-02-13",
"end_date": "2026-02-20",
"total_impressions": 8523
}

Example with Custom Metrics:

curl 'https://api.upload-post.com/api/uploadposts/total-impressions/myprofile?period=last_month&metrics=likes,comments,shares&breakdown=true' \
--header 'Authorization: Apikey XXX...'
{
"success": true,
"profile_username": "myprofile",
"start_date": "2026-01-21",
"end_date": "2026-02-20",
"metrics": {
"likes": 4520,
"comments": 312,
"shares": 189
},
"per_platform": {
"likes": { "instagram": 2100, "youtube": 1200, "tiktok": 1220 },
"comments": { "instagram": 150, "youtube": 80, "tiktok": 82 },
"shares": { "instagram": 90, "youtube": 45, "tiktok": 54 }
},
"per_day": {
"likes": { "2026-01-21": 150, "2026-01-22": 160 },
"comments": { "2026-01-21": 10, "2026-01-22": 12 },
"shares": { "2026-01-21": 6, "2026-01-22": 8 }
}
}

Example with Single Date:

curl 'https://api.upload-post.com/api/uploadposts/total-impressions/myprofile?date=2026-02-15' \
--header 'Authorization: Apikey XXX...'
{
"success": true,
"profile_username": "myprofile",
"start_date": "2026-02-15",
"end_date": "2026-02-15",
"total_impressions": 1523
}

Example with Platform Filter:

curl 'https://api.upload-post.com/api/uploadposts/total-impressions/myprofile?platform=youtube,tiktok&breakdown=true' \
--header 'Authorization: Apikey XXX...'
{
"success": true,
"profile_username": "myprofile",
"start_date": "2026-01-20",
"end_date": "2026-02-19",
"total_impressions": 26730,
"platforms_filter": ["youtube", "tiktok"],
"per_platform": {
"youtube": 18730,
"tiktok": 8000
},
"per_day": {
"2026-01-20": 850,
"2026-01-21": 920
}
}

Error Responses:

  • 400 Bad Request: Invalid date format (must be YYYY-MM-DD) or invalid metric name.
  • 401 Unauthorized: The JWT is missing, invalid, or expired.
  • 500 Internal Server Error: An unexpected error occurred on the server.

GET /api/uploadposts/post-analytics/request_id

Returns analytics for a specific post across all platforms it was published to.


Method: GET

Endpoint URL: https://api.upload-post.com/api/uploadposts/post-analytics/request_id

Description:

This endpoint provides per-post analytics by looking up the upload record and cross-referencing with stored analytics snapshots. It returns the post metadata along with platform-specific metrics at the time of posting and the latest available metrics.

Authentication:

A valid JSON Web Token (JWT) is required. Include it in the Authorization header:

Authorization: Apikey <YOUR_JWT_TOKEN>

Parameters:

ParameterTypeLocationRequiredDescription
request_idstringPathYesThe request ID of the upload.
platformstringQueryNoFilter to a single platform (e.g., ?platform=x). When provided, only metrics for that platform are fetched, which is significantly faster than fetching all platforms.

Example Request:

curl 'https://api.upload-post.com/api/uploadposts/post-analytics/abc123-def456' \
--header 'Authorization: Apikey XXX...'

Example Request (single platform):

curl 'https://api.upload-post.com/api/uploadposts/post-analytics/abc123-def456?platform=youtube' \
--header 'Authorization: Apikey XXX...'

Example Response (200 OK):

{
"success": true,
"post": {
"request_id": "abc123-def456",
"profile_username": "myprofile",
"post_title": "My Video",
"post_caption": "Check this out!",
"media_type": "video",
"upload_timestamp": "2026-02-10 14:30:00"
},
"platforms": {
"youtube": {
"success": true,
"platform_post_id": "dQw4w9WgXcQ",
"post_url": "https://youtube.com/watch?v=dQw4w9WgXcQ",
"post_metrics": {
"views": 5200,
"likes": 120,
"comments": 8,
"favorites": 3
},
"post_metrics_source": "platform_api",
"profile_snapshot_at_post_date": {
"followers": 1500,
"impressions": 45000,
"likes": 320,
"comments": 15,
"shares": 8
},
"profile_snapshot_latest": {
"followers": 1650,
"impressions": 52000,
"likes": 410,
"comments": 22,
"shares": 12
},
"profile_snapshot_latest_date": "2026-02-20"
},
"tiktok": {
"success": true,
"platform_post_id": "7123456789",
"post_url": "https://tiktok.com/@user/video/7123456789",
"post_metrics_error": "TikTok video not found (ID: 7123456789). The token may need to be refreshed.",
"profile_snapshot_at_post_date": {
"followers": 800,
"impressions": 12000,
"likes": 500,
"comments": 30
},
"profile_snapshot_latest": {
"followers": 950,
"impressions": 18500,
"likes": 780,
"comments": 45
},
"profile_snapshot_latest_date": "2026-02-20"
}
}
}

Per-Platform Response Fields:

  • success: Whether the post was successfully published to this platform.
  • platform_post_id: The post's ID on the platform.
  • post_url: Direct URL to the published post.
  • post_metrics: Live metrics fetched from the platform's API for this specific post (views, likes, comments, shares, etc.).
  • post_metrics_source: Source of post metrics (currently "platform_api").
  • post_metrics_error: If post-level metrics could not be fetched, this field contains a human-readable error message explaining why.
  • profile_snapshot_at_post_date: Profile-level metrics snapshot from the day the post was published.
  • profile_snapshot_latest: Most recent profile-level metrics snapshot.
  • profile_snapshot_latest_date: Date of the latest snapshot.

Error Responses:

  • 401 Unauthorized: The JWT is missing, invalid, or expired.
  • 404 Not Found: No post found with the given request ID.
  • 500 Internal Server Error: An unexpected error occurred on the server.

GET /api/uploadposts/post-analytics?platform_post_id=

Returns analytics for any post (including organically published posts) using its native platform ID instead of a request ID.


Method: GET

Endpoint URL: https://api.upload-post.com/api/uploadposts/post-analytics?platform_post_id=XXXXX&platform=instagram&user=profile_username

Description:

This endpoint allows you to fetch live per-post analytics using the platform's native post ID (e.g., an Instagram media ID) rather than an Upload Post request_id. This is useful for retrieving metrics on organically published posts that were not uploaded through the API. You can obtain platform_post_id values from the GET /api/uploadposts/media endpoint.

tip

This endpoint queries the platform live, one post per call, and is limited to 100 requests per 5 minutes. To read metrics for thousands of posts, use GET /api/uploadposts/post-analytics/cached instead, which replays previously fetched results, paginated, and is not subject to that limit.

Authentication:

A valid JSON Web Token (JWT) is required. Include it in the Authorization header:

Authorization: Apikey <YOUR_JWT_TOKEN>

Parameters:

ParameterTypeLocationRequiredDescription
platform_post_idstringQueryYesThe native post ID on the platform (e.g., Instagram media ID).
platformstringQueryYesThe platform to query. One of: youtube, tiktok, instagram, facebook, linkedin, x, threads, pinterest, reddit.
userstringQueryYesThe profile_username of the profile that owns the social account.

Example Request:

curl 'https://api.upload-post.com/api/uploadposts/post-analytics?platform_post_id=18330983293218037&platform=instagram&user=myprofile' \
--header 'Authorization: Apikey XXX...'

Example Response (200 OK):

{
"success": true,
"post": {
"platform_post_id": "18330983293218037",
"platform": "instagram",
"profile_username": "myprofile",
"source": "organic"
},
"platforms": {
"instagram": {
"success": true,
"platform_post_id": "18330983293218037",
"post_metrics": {
"likes": 340,
"comments": 12,
"views": 8500,
"reach": 6200,
"impressions": 9100,
"saves": 45,
"shares": 28
},
"post_metrics_source": "platform_api",
"available_metrics": ["followers", "reach", "views", "impressions", "profileViews", "likes", "comments", "shares", "saves"],
"metric_labels": {
"reach": "Unique Reach",
"views": "Views",
"impressions": "Views",
"profileViews": "Accounts Engaged"
},
"primary_impressions_field": "reach"
}
}
}

Response Fields:

  • post.source: Either "organic" (post was not uploaded via the API) or "api_uploaded" (post was uploaded via the API and has an associated request_id).
  • post.request_id: Only present when source is "api_uploaded" — the original upload request ID.
  • platforms.<platform>.post_metrics: Live metrics fetched from the platform's API.
  • platforms.<platform>.post_metrics_source: Source of post metrics (currently "platform_api").
  • platforms.<platform>.post_metrics_error: If metrics could not be fetched, a human-readable error message.
  • platforms.<platform>.available_metrics: List of metrics available for this platform.

Error Responses:

  • 400 Bad Request: Missing or invalid query parameters.
  • 401 Unauthorized: The JWT is missing, invalid, or expired.
  • 404 Not Found: User or profile not found.
  • 500 Internal Server Error: An unexpected error occurred on the server.

GET /api/uploadposts/post-analytics/cached

Reads back, in bulk, per-post metrics that Upload-Post already fetched for you, instead of calling the social platforms again.


Method: GET

Endpoint URL: https://api.upload-post.com/api/uploadposts/post-analytics/cached

Description:

The live per-post endpoints (/api/uploadposts/post-analytics/{request_id} and /api/uploadposts/post-analytics?platform_post_id=) query the platform APIs on every call, one post at a time, and are therefore subject to the platform analytics rate limit of 100 requests per 5 minutes. Walking an account with thousands of posts through them is not practical.

This endpoint reads instead from a write-through cache: every time a post's metrics are fetched through one of the live endpoints, the result is stored. This endpoint replays those stored values, many posts per call, paginated, and is not subject to the 100 requests / 5 minutes platform analytics rate limit, because it never touches the platforms during the request. It is designed for re-reading a large back catalogue you have already fetched once.

There is no background refresh

This cache is filled as a side effect of live reads. Nothing updates it on its own. Three consequences:

  • A post appears here only after it has been fetched at least once through a live per-post endpoint. A post you have never queried live will not be here at all.
  • captured_at is the last time that post was fetched live — not "this morning". A post you last read a month ago will still show a month-old value.
  • To refresh a post, call the live endpoint for it. The cache updates as a side effect of that call.

So the pattern is: fetch live once (or whenever you want fresh numbers), then re-read as many times as you like from here for free. That is where the saving is — customers typically re-read the same post several times a day.

Authentication:

A valid JSON Web Token (JWT) is required. Include it in the Authorization header:

Authorization: Apikey <YOUR_JWT_TOKEN>

Parameters:

ParameterTypeLocationRequiredDescription
userstringQueryYesThe profile_username of the profile to read snapshots for.
platformstringQueryNoRestrict the result to a single platform. One of: instagram, tiktok, youtube, facebook, linkedin, threads, pinterest, reddit. When omitted, all platforms are returned and the response echoes "platform": null.
limitintegerQueryNoNumber of posts per page. Defaults to 50, maximum 200.
cursorstringQueryNoOpaque token identifying the next page. Pass back exactly what the previous response returned in next_cursor. Do not build or parse these tokens yourself — an invalid cursor returns 400.
sincestringQueryNoStart of the date range in YYYY-MM-DD format. Defaults to 30 days ago.
untilstringQueryNoEnd of the date range in YYYY-MM-DD format. Defaults to today.

Example Request:

curl 'https://api.upload-post.com/api/uploadposts/post-analytics/cached?user=influencersde&limit=50' \
--header 'Authorization: Apikey XXX...'

Example Response (200 OK):

{
"success": true,
"profile_username": "influencersde",
"platform": null,
"since": "2026-06-28",
"until": "2026-07-28",
"source": "snapshot_cache",
"posts": [
{
"post_id": "uAAYuyTX4P0",
"platform": "youtube",
"profile_username": "influencersde",
"date": "2026-07-28",
"captured_at": "2026-07-28T11:17:06.901000",
"metrics": {
"views": 412,
"likes": 3,
"comments": 0,
"favorites": 0
},
"post_url": "https://www.youtube.com/watch?v=uAAYuyTX4P0",
"media_type": "video",
"upload_timestamp": "2026-07-17T08:01:50.228000"
}
],
"limit": 50,
"next_cursor": "eyJkIjoiMjAyNi0wNy0yOCIsInAiOi...",
"has_more": true
}

Response Fields:

  • profile_username: The profile the snapshots belong to.
  • platform: The platform filter that was applied, or null when no platform was requested.
  • since / until: The effective date range covered by the response.
  • source: Always "snapshot_cache" — a marker that these numbers were replayed from the cache, not fetched from the platform during this request.
  • posts: Array of per-post snapshot rows (see below).
  • limit: The effective page size that was applied.
  • next_cursor: Token to pass as cursor on the next request. null when there are no more pages.
  • has_more: true when another page is available.

Per-Post Fields:

FieldTypeDescription
post_idStringThe post's native ID on the platform.
platformStringThe platform this row belongs to.
profile_usernameStringThe profile that owns the post.
dateStringSnapshot date (YYYY-MM-DD) this row belongs to.
captured_atStringISO 8601 timestamp of the last time this post was fetched live from the platform. Use this to judge freshness — nothing refreshes it in the background.
metricsObjectThe metrics captured for this post. Keys vary per platform — see below.
post_urlString/nullDirect URL to the published post.
media_typeString/nullType of media (e.g. video, image).
upload_timestampString/nullISO 8601 timestamp of when the post was originally published.
Metrics keys vary per platform

metrics mirrors what each platform exposes for a post. YouTube returns views, likes, comments, favorites plus, when the YouTube Analytics report is available, watch_time_minutes, average_view_duration_seconds and average_view_percentage; Bluesky (use the at:// URI returned on upload as platform_post_id) returns likes, reposts, replies, quotes and engagement; Instagram returns reach/saves/shares-style keys; TikTok, Pinterest and the rest each return their own set. Facebook posts return reactions, likes, comments, shares and — for Page posts where Meta serves post insights — reach (unique accounts, via post_total_media_view_unique with a fallback to the pre-2026 post_impressions_unique), so engagement rate can be computed per post. Read the keys present on each row rather than assuming a fixed schema, and treat a missing key as "not reported by that platform".

Paginating Through Everything:

API_KEY="XXX..."
CURSOR=""

while :; do
URL="https://api.upload-post.com/api/uploadposts/post-analytics/cached?user=influencersde&limit=200"
[ -n "$CURSOR" ] && URL="$URL&cursor=$CURSOR"

RESPONSE=$(curl -s "$URL" -H "Authorization: Apikey $API_KEY")
echo "$RESPONSE" | jq -r '.posts[] | "\(.platform) \(.post_id)"'

[ "$(echo "$RESPONSE" | jq -r '.has_more')" = "true" ] || break
CURSOR=$(echo "$RESPONSE" | jq -r '.next_cursor')
done

Live vs. Cached:

GET /api/uploadposts/post-analytics (live)GET /api/uploadposts/post-analytics/cached
Data sourcePlatform API, in real timeUpload-Post's write-through cache
FreshnessCurrentAs of your last live read (captured_at tells you)
Rate limit100 requests / 5 minutesNot subject to the platform analytics rate limit
Scope per callOne postUp to 200 posts, paginated
Covers a post published minutes agoYesOnly after you fetch it live once
Best forRefreshing a post's numbersRe-reading in bulk what you already fetched

Error Responses:

  • 400 Bad Request: Missing user, an invalid platform, a malformed since/until date, or an invalid/expired cursor.
  • 401 Unauthorized: The JWT is missing, invalid, or expired.
  • 404 Not Found: User or profile not found.
  • 500 Internal Server Error: An unexpected error occurred on the server.

GET /api/uploadposts/platform-metrics

Returns the available metrics configuration for all supported platforms.


Method: GET

Endpoint URL: https://api.upload-post.com/api/uploadposts/platform-metrics

Description:

This public endpoint returns the metrics configuration for each social platform, including which metrics are available and which field is used as the primary "impressions" metric for aggregation.

Example Response (200 OK):

{
"instagram": {
"primary_impressions_field": "reach",
"available_metrics": ["followers", "reach", "views", "impressions", "profileViews", "likes", "comments", "shares", "saves"],
"metric_labels": {
"reach": "Unique Reach",
"views": "Views",
"impressions": "Views",
"profileViews": "Accounts Engaged"
}
},
"youtube": {
"primary_impressions_field": "impressions",
"available_metrics": ["followers", "impressions", "likes", "comments", "shares"],
"metric_labels": {
"impressions": "Video Views",
"followers": "Subscribers"
}
}
}