Skip to main content
POST
/
api
/
v1
/
videos
/
{id}
/
stop
Stop Video
curl --request POST \
  --url https://api.example.com/api/v1/videos/{id}/stop \
  --header 'X-API-Key: <x-api-key>'
{
  "success": true,
  "id": "<string>",
  "job_id": "<string>",
  "video_link": "<string>",
  "previous_status": "<string>",
  "new_status": "<string>"
}

Endpoint

POST https://contentstats.io/api/v1/videos/{id}/stop
Stop tracking a video before the scheduled duration ends. Useful when you’ve collected enough data or want to save credits.
All collected snapshots are preserved. You only pay for snapshots already collected.

Authentication

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

Path Parameters

id
string
required
The video ID from Track VideoExample: cm5abc123def

Response

success
boolean
Whether operation succeeded
id
string
Video identifier
job_id
string
External job ID
Video URL
previous_status
string
Status before stopping (usually monitoring)
new_status
string
New status (always completed)

Code Examples

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

Response Example

{
  "success": true,
  "id": "cm5abc123def",
  "job_id": "job_xyz789",
  "video_link": "https://www.tiktok.com/@user/video/7234567890",
  "previous_status": "monitoring",
  "new_status": "completed"
}

When to Stop Early

You’ve collected sufficient data for your analysis:
async function stopIfEnoughData(videoId, minSnapshots = 24) {
  const video = await getVideo(videoId);
  
  if (video.snapshots.length >= minSnapshots) {
    await stopVideo(videoId);
    console.log('Stopped: Collected', video.snapshots.length, 'snapshots');
  }
}
Platform removed the video:
async function stopIfDeleted(videoId) {
  const video = await getVideo(videoId);
  
  if (video.is_deleted) {
    await stopVideo(videoId);
    console.log('Stopped: Video was deleted');
  }
}
Conserve credits for other videos:
async function stopLowPriorityVideos() {
  const videos = await listVideos({ status: 'monitoring' });
  
  // Stop videos with low engagement
  for (const video of videos.videos) {
    if (video.snapshots.length >= 24) {
      const latest = video.snapshots[video.snapshots.length - 1];
      const engagementRate = calculateEngagement(latest);
      
      if (engagementRate < 0.01) { // Less than 1%
        await stopVideo(video.id);
        console.log('Stopped low-engagement video:', video.id);
      }
    }
  }
}

Cost Savings

function calculateSavings(video) {
  const snapshotsCollected = video.snapshots.length;
  const totalPlanned = video.monitoring_duration_days * 24;
  const snapshotsSaved = totalPlanned - snapshotsCollected;
  const costSaved = snapshotsSaved * 0.015;
  
  return {
    collected: snapshotsCollected,
    planned: totalPlanned,
    saved: snapshotsSaved,
    costSaved: costSaved.toFixed(2)
  };
}

// Example: Stopped after 3 days of 7-day tracking
const savings = calculateSavings({
  snapshots: new Array(72), // 3 days × 24 hours
  monitoring_duration_days: 7
});

console.log(`Saved ${savings.saved} snapshots ($${savings.costSaved})`);
// Output: Saved 96 snapshots ($1.44)

Batch Stop

Stop multiple videos at once:
async function batchStopVideos(videoIds) {
  const results = await Promise.all(
    videoIds.map(id => 
      fetch(`https://contentstats.io/api/v1/videos/${id}/stop`, {
        method: 'POST',
        headers: { 'X-API-Key': apiKey }
      }).then(r => r.json())
    )
  );
  
  const stopped = results.filter(r => r.success).length;
  console.log(`Stopped ${stopped}/${videoIds.length} videos`);
  
  return results;
}

// Stop videos with low remaining time
const videos = await listVideos();
const toStop = videos.videos
  .filter(v => v.status === 'monitoring')
  .filter(v => v.days_remaining < 0.5)
  .map(v => v.id);

await batchStopVideos(toStop);

What Happens After Stopping

  1. Status Changes: monitoringcompleted
  2. Data Preserved: All snapshots remain accessible
  3. No Future Charges: No more snapshots collected
  4. Billing: Only charged for snapshots already collected
  5. API Access: Video data still accessible via Get Video
// After stopping, data is still accessible
const stoppedVideo = await getVideo('cm5abc123def');

console.log('Status:', stoppedVideo.status); // "completed"
console.log('Snapshots:', stoppedVideo.snapshots.length); // All preserved

Error Responses

404 Not Found

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

400 Bad Request

{
  "error": "Video is not being monitored"
}
Video status is not monitoring. Cannot stop videos that are already completed, paused, or cancelled.

403 Forbidden

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

Resume vs. Restart

Cannot Resume: Once stopped, tracking cannot be resumed. To track again, create a new tracking job with Track Video.
// ❌ Cannot do this
await stopVideo('cm5abc123');
await resumeVideo('cm5abc123'); // No resume endpoint

// ✅ Must create new tracking job
await stopVideo('cm5abc123');
const newJob = await trackVideo({
  video_link: originalUrl,
  duration_days: 7
}); // New ID, fresh tracking

Best Practices

Add confirmation for user-initiated stops:
async function stopWithConfirmation(videoId) {
  const video = await getVideo(videoId);
  const savings = calculateSavings(video);
  
  const confirmed = confirm(
    `Stop tracking ${video.video_link}?\n` +
    `Collected: ${savings.collected} snapshots\n` +
    `Remaining: ${savings.saved} snapshots ($${savings.costSaved} saved)`
  );
  
  if (confirmed) {
    await stopVideo(videoId);
  }
}
Track why videos were stopped:
async function stopWithReason(videoId, reason) {
  const result = await stopVideo(videoId);
  
  // Log to your database
  await db.stoppedVideos.create({
    videoId,
    reason,
    stoppedAt: new Date(),
    snapshotsCollected: result.snapshots_count
  });
  
  return result;
}

await stopWithReason('cm5abc123', 'Low engagement detected');
Alert users when videos are auto-stopped:
async function autoStopAndNotify(videoId, reason) {
  await stopVideo(videoId);
  
  // Send email notification
  await sendEmail({
    to: user.email,
    subject: 'Video tracking stopped',
    body: `Tracking stopped for ${video.video_link}. Reason: ${reason}`
  });
}

Next Steps