Skip to main content
GET
/
api
/
v1
/
videos
/
{id}
Get Video
curl --request GET \
  --url https://api.example.com/api/v1/videos/{id} \
  --header 'X-API-Key: <x-api-key>'
{
  "id": "<string>",
  "job_id": "<string>",
  "video_link": "<string>",
  "platform": "<string>",
  "status": "<string>",
  "monitoring_started": "<string>",
  "monitoring_duration_days": 123,
  "days_remaining": 123,
  "is_deleted": true,
  "current_metadata": {},
  "snapshots": [
    {
      "id": "<string>",
      "snapshot_id": "<string>",
      "snapshot_time": "<string>",
      "views": "<string>",
      "likes": "<string>",
      "comments": "<string>",
      "shares": "<string>",
      "saves": "<string>",
      "provider": "<string>"
    }
  ],
  "created_at": "<string>",
  "last_updated": "<string>"
}

Endpoint

GET https://contentstats.io/api/v1/videos/{id}
Retrieve complete data for a tracked video, including all hourly snapshots.

Authentication

X-API-Key
string
required
Your API key from the dashboard

Path Parameters

id
string
required
The video ID returned from Track VideoExample: cm5abc123def

Response

id
string
Video identifier
job_id
string
External job ID
Original video URL
platform
string
Platform: tiktok, youtube, instagram, twitter
status
string
Current status: monitoring, completed, paused, error, cancelled
monitoring_started
string
When tracking started (ISO 8601)
monitoring_duration_days
integer
Total tracking duration
days_remaining
number
Days left in tracking period
is_deleted
boolean
Whether video was deleted
current_metadata
object
Latest video metadata (title, creator, etc.)
snapshots
array
Array of hourly snapshots
created_at
string
When tracking started
last_updated
string
Last data update timestamp

Code Examples

curl "https://contentstats.io/api/v1/videos/cm5abc123def" \
  -H "X-API-Key: cs_live_YOUR_KEY"

Response Example

{
  "id": "cm5abc123def",
  "job_id": "job_xyz789",
  "video_link": "https://www.tiktok.com/@user/video/7234567890",
  "platform": "tiktok",
  "status": "monitoring",
  "monitoring_started": "2024-01-29T10:00:00.000Z",
  "monitoring_duration_days": 7,
  "days_remaining": 5.5,
  "is_deleted": false,
  "current_metadata": {
    "title": "Viral Dance Challenge",
    "creator": "@user",
    "description": "Join the trend!"
  },
  "snapshots": [
    {
      "id": "snap_001",
      "snapshot_id": "external_snap_123",
      "snapshot_time": "2024-01-29T10:00:00.000Z",
      "views": "1250000",
      "likes": "185000",
      "comments": "4200",
      "shares": "12500",
      "saves": "8900",
      "provider": "render"
    },
    {
      "id": "snap_002",
      "snapshot_id": "external_snap_124",
      "snapshot_time": "2024-01-29T11:00:00.000Z",
      "views": "1298000",
      "likes": "189000",
      "comments": "4350",
      "shares": "12800",
      "saves": "9100",
      "provider": "render"
    }
  ],
  "created_at": "2024-01-29T10:00:00.000Z",
  "last_updated": "2024-01-29T11:00:00.000Z"
}

Use Cases

Build Growth Chart

function buildGrowthData(video) {
  return video.snapshots.map((snapshot, index) => {
    const hoursSinceStart = index;
    
    return {
      hour: hoursSinceStart,
      time: snapshot.snapshot_time,
      views: parseInt(snapshot.views),
      likes: parseInt(snapshot.likes),
      comments: parseInt(snapshot.comments)
    };
  });
}

const chartData = buildGrowthData(video);
// Use with Chart.js, Recharts, etc.

Calculate Engagement Rate

def calculate_engagement_rate(snapshot):
    views = int(snapshot['views'])
    likes = int(snapshot['likes'])
    comments = int(snapshot['comments'])
    
    total_engagement = likes + comments
    
    if views == 0:
        return 0
    
    return (total_engagement / views) * 100

latest = video['snapshots'][-1]
rate = calculate_engagement_rate(latest)
print(f"Engagement rate: {rate:.2f}%")

Export to CSV

function exportToCSV(video) {
  const headers = ['Time', 'Views', 'Likes', 'Comments', 'Shares', 'Saves'];
  const rows = video.snapshots.map(s => [
    s.snapshot_time,
    s.views,
    s.likes,
    s.comments,
    s.shares || '0',
    s.saves || '0'
  ]);
  
  const csv = [headers, ...rows]
    .map(row => row.join(','))
    .join('\n');
  
  return csv;
}

const csv = exportToCSV(video);
console.log(csv);

Detect Viral Moments

function detectViralMoments(snapshots, threshold = 1.5) {
  const moments = [];
  
  for (let i = 1; i < snapshots.length; i++) {
    const current = snapshots[i];
    const previous = snapshots[i - 1];
    
    const currentViews = parseInt(current.views);
    const previousViews = parseInt(previous.views);
    const growth = currentViews - previousViews;
    
    // Calculate average hourly growth
    const avgGrowth = previousViews / i;
    
    // Detect if growth is threshold times above average
    if (growth > avgGrowth * threshold) {
      moments.push({
        time: current.snapshot_time,
        growth: growth,
        multiplier: (growth / avgGrowth).toFixed(2)
      });
    }
  }
  
  return moments;
}

const viral = detectViralMoments(video.snapshots);
console.log('Viral moments:', viral);

Polling Best Practices

Snapshots are collected hourly, so don’t poll faster:
// ❌ Don't poll every minute
setInterval(() => fetchVideo(id), 60 * 1000);

// ✅ Poll hourly (after first snapshot)
setInterval(() => fetchVideo(id), 60 * 60 * 1000);
Cache and only fetch when updated:
let lastUpdated = null;

async function fetchIfUpdated(id) {
  const video = await fetchVideo(id);
  
  if (video.last_updated === lastUpdated) {
    console.log('No updates');
    return null;
  }
  
  lastUpdated = video.last_updated;
  return video;
}
Subscribe to events instead of polling:
// Coming soon!
await webhook.subscribe({
  event: 'snapshot.created',
  video_id: 'cm5abc123',
  url: 'https://yourapp.com/webhook'
});

Error Responses

404 Not Found

{
  "error": "Video not found"
}
Invalid video ID or accessing another organization’s video.

401 Unauthorized

{
  "error": "API key required"
}
Missing or invalid API key.

403 Forbidden

{
  "error": "Access denied"
}
Video belongs to a different organization.

Next Steps