GET /v1/videos/by-external-id/

Look up a video by its platform-specific external_video_id (e.g. a TikTok shortcode, a YouTube video ID, an Instagram media ID) and return its full record, latest stats, and 30-day stats history.

The same path is also served by PATCH /v1/videos/by-external-id/{external_video_id} for editable metadata updates — this page covers GET only.

The external_video_id is path-encoded; URLs that contain / or other reserved characters must be percent-encoded.

📋 Overview

Property Value
Method GET
Endpoint https://api.influtics.com/v1/videos/by-external-id/{external_video_id}
Auth Required ✅

🔐 Headers

Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

📝 Path Parameter

Parameter Type Required Description
external_video_id string ✅ The platform-specific video ID (e.g. 7489443966908189959 for TikTok, dQw4w9WgXcQ for YouTube).

📝 Query Parameters

None.

Example Request

curl -X GET https://api.influtics.com/v1/videos/by-external-id/7489443966908189959 \
  -H "Authorization: Bearer YOUR_API_KEY"

✅ Response (200 OK)

{
    "success": true,
    "data": {
        "data": {
            "video_id": "77168374-dd2c-496a-b1ae-3d4944f48ccb",
            "external_video_id": "7489443966908189959",
            "stats": {
                "likes":     { "2025-06-30 08:26:03.730104+00": 56500 },
                "views":     { "2025-06-30 08:26:03.730104+00": 1900000 },
                "reposts":   { "2025-06-30 08:26:03.730104+00": 6472 },
                "comments":  { "2025-06-30 08:26:03.730104+00": 483 }
            },
            "views": 2000000,
            "likes": 56501,
            "comments": 526,
            "reposts": 6892,
            "platform": "tiktok",
            "created_at": "2025-06-30T08:25:29.97727+00:00",
            "title": "Untitled",
            "thumbnail_url": "https://p16-sign-sg.tiktokcdn.com/...",
            "cpm": 0,
            "er": 3.339736842105263,
            "stats_last_updated": "2025-06-30T08:26:03.730104+00:00",
            "deleted_at": null,
            "deleted_reason": null
        }
    },
    "meta": {
        "request_id": "9f1b7e7e-1c36-49a9-8521-7b9180d8a1a8",
        "processing_time_ms": 437
    }
}

📊 GET Response Fields

Field Type Description
data.data.video_id string Internal video UUID
data.data.external_video_id string Platform-specific video ID
data.data.stats object Map of metric name → { "ISO-8601 timestamp": value }. Metrics include likes, views, reposts, comments.
data.data.views / likes / comments / reposts int | null Latest recorded value of each metric
data.data.platform string Platform name (e.g. tiktok, instagram, youtube)
data.data.created_at string When the video was first seen (ISO 8601)
data.data.title string Video title / caption (if available)
data.data.thumbnail_url string Video thumbnail URL (if available)
data.data.cpm number Cost per mille (if available)
data.data.payouts number | null Estimated creator payout. Capped at budget. null when no budget is set. See Payouts.
data.data.er number Engagement rate (if available)
data.data.stats_last_updated string When stats were last updated (ISO 8601)
data.data.campaign string | null Campaign name
data.data.notes string | null Free-form notes
data.data.budget number | null Total per-video budget
data.data.ecpm number | null Effective cost per mille (how much to pay the creator for 1k views)
data.data.status string | null Workflow-state. One of to do, running, ended.
data.data.video_status string | null Tracking-state. One of tracking, paused, deleted.
data.data.deleted_at string | null When the video was detected as deleted (ISO 8601). null while the video is healthy. See Deletion state.
data.data.deleted_reason object | null Why the video was detected as deleted. null unless a reason was recorded. See Deletion state.
meta.request_id string Unique request identifier
meta.processing_time_ms number Time taken to process the request (ms)

Metadata fields are named exactly as they are written on POST /v1/videos/track and PATCH .../by-external-id — a value you set can be read back with the same key. ecpm is returned in the same unit it is accepted in; cpm above is a separate, platform-computed figure.


Deletion state

Two read-only fields describe why a video stopped producing stats. Neither is writable — no endpoint on this API sets them.

Field Meaning
deleted_at ISO 8601 timestamp of the first detection. null while the video is healthy.
deleted_reason null, or an object explaining the cause.
{
  "video_status": "deleted",
  "deleted_at": "2026-10-18T09:12:44+00:00",
  "deleted_reason": {
    "code": "not_found",
    "message": "video not exist",
    "raw": { "statusCode": 10204, "statusMsg": "video not exist" }
  }
}
deleted_reason key Type Description
code string Stable enum: not_found, private, classified, user_banned, geofence_blocked, or unavailable.
message string | null The platform's own wording, verbatim. Never rewritten.
raw object | null The untouched provider payload, for debugging.

The reason does not repeat the platform — it is already on the video's own platform field.

code is inferred, message is authoritative. code is derived from the platform's numeric status code, which can be ambiguous — VK's blanket ACCESS_DENIED (15) becomes private, but the platform never says "private". Prefer message in anything user-facing or a model-facing summary.

Coverage is partial. Today only TikTok and VK record a reason. On every other platform deleted_reason is null even when video_status is deleted — that means the provider reported no cause, not that the video was healthy. Do not treat a null reason as "not deleted"; branch on deleted_at.

The two fields are independent of video_status. A video can carry a deleted_reason while video_status stays tracking — this is deliberate for content the platform has suppressed but may restore (TikTok classified/private posts stay retryable so stats reappear if the block lifts). Read deleted_at / deleted_reason, not video_status, to reason about deletion.

Deletion is reversible. A video that becomes fetchable again clears both fields to null on the next successful refresh. Poll rather than cache a deleted verdict permanently.


⚠️ Error Responses

All errors share the standard envelope { success: false, error: { code, message, request_id, ... } }. The table below lists every documented code for GET.

Status code Trigger Additional error fields
401 INVALID_API_KEY / MISSING_AUTH Missing or invalid Authorization header —
402 PAID_PLAN_REQUIRED Free-tier API key attempted the call upgrade_url
404 VALIDATION_ERROR No video with that external_video_id exists for the authenticated org (returns this code rather than NOT_FOUND due to a worker-side quirk). —
500 INTERNAL_ERROR Server-side error —

GET 404 envelope note — due to a known worker-side quirk, the GET endpoint returns a 400 VALIDATION_ERROR-shaped envelope on 404 (the code field is missing; only message and request_id are populated). If your client switches on code, fall back to status === 404. A follow-up PR will align this with PATCH's canonical envelope.

🎯 Use Cases

  • Single-video lookup — fetch the current stats snapshot and metadata for a video you already know the ID of.
  • Dashboard deep-links — open the dashboard directly on a known video without first listing the org's tracked set.
  • Health checks — confirm a video is still being tracked and that stats are flowing.

Related: POST /v1/videos/track → · PATCH /v1/videos/by-external-id/ → · Get Video Stats → · View Usage →