curl --request GET \
--url https://app.sideshift.app/api/v1/analytics/videos \
--header 'x-api-key: <api-key>'import requests
url = "https://app.sideshift.app/api/v1/analytics/videos"
headers = {"x-api-key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-api-key': '<api-key>'}};
fetch('https://app.sideshift.app/api/v1/analytics/videos', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.sideshift.app/api/v1/analytics/videos",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://app.sideshift.app/api/v1/analytics/videos"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://app.sideshift.app/api/v1/analytics/videos")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.sideshift.app/api/v1/analytics/videos")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"data": [
{
"id": "<string>",
"title": "<string>",
"platform": "<string>",
"views": 123,
"likes": 123,
"comments": 123,
"shares": 123,
"bookmarks": 123,
"engagementRate": 123,
"totalEngagement": 123,
"earnings": 123,
"paid": true,
"contractorName": "<string>",
"uploadedAt": 123
}
],
"page": 123,
"limit": 123,
"total": 123,
"totalPages": 123,
"summary": {
"totalVideos": 123,
"totalViews": 123,
"totalLikes": 123,
"totalComments": 123,
"totalShares": 123,
"totalBookmarks": 123,
"totalEngagement": 123,
"averageEngagementRate": 123,
"totalEarnings": 123,
"paidVideos": 123,
"unpaidVideos": 123,
"platformBreakdown": {}
}
}List all tracked videos with analytics
Retrieve all tracked videos/posts with comprehensive analytics and filtering.
Includes engagement metrics, sorting, and detailed statistics for each video.
Agency accounts can pass scope=agency to aggregate tracked videos
across the parent agency and every subaccount.
curl --request GET \
--url https://app.sideshift.app/api/v1/analytics/videos \
--header 'x-api-key: <api-key>'import requests
url = "https://app.sideshift.app/api/v1/analytics/videos"
headers = {"x-api-key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-api-key': '<api-key>'}};
fetch('https://app.sideshift.app/api/v1/analytics/videos', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.sideshift.app/api/v1/analytics/videos",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://app.sideshift.app/api/v1/analytics/videos"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://app.sideshift.app/api/v1/analytics/videos")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.sideshift.app/api/v1/analytics/videos")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"data": [
{
"id": "<string>",
"title": "<string>",
"platform": "<string>",
"views": 123,
"likes": 123,
"comments": 123,
"shares": 123,
"bookmarks": 123,
"engagementRate": 123,
"totalEngagement": 123,
"earnings": 123,
"paid": true,
"contractorName": "<string>",
"uploadedAt": 123
}
],
"page": 123,
"limit": 123,
"total": 123,
"totalPages": 123,
"summary": {
"totalVideos": 123,
"totalViews": 123,
"totalLikes": 123,
"totalComments": 123,
"totalShares": 123,
"totalBookmarks": 123,
"totalEngagement": 123,
"averageEngagementRate": 123,
"totalEarnings": 123,
"paidVideos": 123,
"unpaidVideos": 123,
"platformBreakdown": {}
}
}Authorizations
API key for authentication. Get yours from Settings → Integrations. A key created by a team member acts as that member and follows their current team permissions; a request outside those permissions returns 403 { "error": "insufficient_scope", "scope": "<required>" }.
Query Parameters
Data scope. company (default) returns only the authenticated
company's own data. agency returns the union of the parent agency
plus every subaccount — use this to pull analytics across all brands.
scope=agency requires an API key belonging to a parent agency
account (an account with isAgency=true and no parent). Passing it with
a non-agency or subaccount key returns 403.
company, agency x <= 100Field to sort by
uploadedAt, views, likes, engagement asc, desc Free-text query matched against the tracked posts.
Filter by campaign. Repeat the parameter for several. program is the legacy alias and is only consulted when programId is absent.
Legacy alias for programId. Ignored when programId is present.
Filter by platform. Repeat the parameter for several. Use twitter rather than x, which is only the display name - this filter matches the stored value literally and does not resolve aliases. An unrecognised platform is not rejected; it simply matches nothing.
tiktok, instagram, youtube, snapchat, facebook, twitter, linkedin Filter by creator. Repeat the parameter for several. creator is the legacy alias and is only consulted when creatorId is absent.
Legacy alias for creatorId. Ignored when creatorId is present.
Restrict to campaigns in this state. Unrecognised values are ignored.
active, all, archived Inclusive start of the date window, YYYY-MM-DD, interpreted at 00:00:00Z.
Inclusive end of the date window, YYYY-MM-DD, interpreted at 23:59:59Z.
Whether unclaimed (ghost) handles are counted. Defaults to all.
all, include, exclude Pass true to drop posts that have since been deleted. Any other value is false.
Restrict to posts in this review state.
all, approved, rejected, unreviewed Only include posts with at least this many views. A value of 0 is a no-op.
x >= 0Only include posts with at most this many views. A value of 0 is a no-op.
x >= 0Restrict to creators in these account groups. Repeat for several. Intersected with creatorId, so passing both with no overlap matches nothing.
Accepted but ignored. This API has no paid filter; the value is pinned to all internally regardless of what is sent.
true, false, all