Skip to content

Overview

Building an application that aggregates live streaming data across YouTube, Twitch, and TwitCasting means dealing with three completely different APIs. Each has its own authentication scheme, rate limiting model, data format, and URL structure.

YouTube Data API v3Twitch Helix APITwitCasting API v2
AuthAPI Key (query parameter)OAuth2 Client CredentialsBasic Auth (base64)
Rate LimitingQuota-based (10,000 units/day)Token bucket (header-driven)Token bucket (60 req/60s)
Cost ModelPer-endpoint cost (1–100 units)Flat (1 req = 1 token)Flat (1 req = 1 token)
Live vs. ArchiveSame video IDDifferent video IDsSame movie ID
Channel IDUC... prefix, @handleLogin nameUser ID
  • YouTube quota — The daily 10,000-unit quota runs out fast. A single search.list call costs 100 units. Without local tracking, you’ll get silent 403 errors mid-day.
  • Twitch OAuth — Tokens expire and must be refreshed before expiry. Missing a refresh means 401 errors in production.
  • TwitCasting rate limits — Only 60 requests per minute. Without a proper token bucket, you’ll hit 429 errors under any moderate load.
  • Different data models — A “video” on YouTube, a “VOD” on Twitch, and a “movie” on TwitCasting are conceptually the same thing but have completely different JSON shapes and field names.
import { UnifiedClient } from "@unified-live/core";
import { createYouTubePlugin } from "@unified-live/youtube";
import { createTwitchPlugin } from "@unified-live/twitch";
import { createTwitCastingPlugin } from "@unified-live/twitcasting";
const client = UnifiedClient.create({
plugins: [
createYouTubePlugin({ apiKey: process.env.YOUTUBE_API_KEY! }),
createTwitchPlugin({
clientId: process.env.TWITCH_CLIENT_ID!,
clientSecret: process.env.TWITCH_CLIENT_SECRET!,
}),
createTwitCastingPlugin({
clientId: process.env.TWITCASTING_CLIENT_ID!,
clientSecret: process.env.TWITCASTING_CLIENT_SECRET!,
}),
],
});
// One interface — the SDK handles auth, rate limits, and data normalization
const yt = await client.resolve("https://www.youtube.com/watch?v=abc123");
const tw = await client.resolve("https://www.twitch.tv/videos/123456");
const tc = await client.resolve("https://twitcasting.tv/user/movie/789");
// All return the same Content type
console.log(yt.title); // string
console.log(tw.platform); // "twitch"
console.log(tc.type); // "broadcast" | "archive"
ConcernHow unified-live handles it
AuthenticationAPI key injection (YouTube), OAuth2 auto-refresh (Twitch), Basic auth encoding (TwitCasting)
Rate LimitingLocal quota tracking with QuotaExhaustedError (YouTube), token bucket with header parsing (Twitch), fixed token bucket (TwitCasting)
RetriesExponential backoff for 429/5xx, token refresh on 401
Data NormalizationAll platforms map to unified Content, Channel, Broadcast, Archive types
URL ResolutionAuto-detects platform from URL, supports multiple URL formats per platform
ObservabilityOpenTelemetry spans and metrics for every API call (zero overhead when OTel is not configured)
FeatureYouTubeTwitchTwitCasting
Get content by URLYesYesYes
Get content by IDYesYesYes
List broadcastsYesYesYes
List archives (pagination)YesYesYes
Get channel infoYesYesYes
Archive resolutionYesYesYes
SearchYesYesYes
ClipsNoYesNo
Batch get contentsYesYesYes*
Batch get broadcastsYes*YesYes*
Batch get channelsYesYes*Yes*
Batch get clipsNoYesNo
Cross-platform broadcastsYesYesYes
Cross-platform searchYesYesYes
OpenTelemetry traces & metricsYesYesYes

* Supported via automatic per-item fallback (no native batch API)