Developers
Developer APIs
Strimm exposes two HTTP APIs for apps and integrations. Use the REST API for new integrations
with a { success, data } envelope. Use the Custom Services API for
the bundled mobile app template and other legacy-compatible clients that expect a { data } envelope.
The bundled Roku, Fire TV, Apple TV and Android TV templates use the same Custom Services API, identifying
themselves with a Platform-Id header.
Claude, ChatGPT, and Grok should use the hosted
MCP server
instead of calling these APIs directly.
REST API
Token-based API for studio-authenticated apps. Login with username or email, then send the GUID auth token on protected routes.
Base URL
https://strimm.com/api/v1/rest
Response envelope
Successful responses:
{
"success": true,
"data": { ... }
}
Error responses:
{
"success": false,
"error": {
"code": "invalid_credentials",
"message": "Login failed."
}
}
Authentication
/auth/login
No auth required. Accepts username or email and password.
Request body
{
"username": "your_username",
"password": "your_password"
}
Response data
{
"authToken": "00000000-0000-0000-0000-000000000000",
"userId": 123,
"userName": "creator",
"email": "[email protected]",
"publicUrl": "creator"
}
/auth/logout
Revokes the Bearer token sent in the Authorization header. Works for session tokens from
/auth/login and for the long-lived app tokens embedded in generated TV app archives
(Studio → Apps → Download), so an app can sign itself out of a leaked build.
Apps
/apps/{platform}
Returns app configuration for the authenticated user. Platforms:
mobile, roku, firetv, appletv, androidtv (case-insensitive).
Example request
GET /api/v1/rest/apps/mobile
Authorization: Bearer {authToken}
Example response
{
"success": true,
"data": {
"appId": 1,
"platform": "Mobile",
"appName": "My Network App",
"channelTubeIds": [42, 58],
"isPaid": true,
"storeProducts": [
{
"storePlatform": "Apple",
"productId": "com.yourbrand.app.weekly",
"displayName": "Weekly access",
"billingPeriod": "Weekly",
"isActive": true,
"storeSharedSecretConfigured": false
},
{
"storePlatform": "Apple",
"productId": "com.yourbrand.app.monthly",
"displayName": "Monthly access",
"billingPeriod": "Monthly",
"isActive": true,
"storeSharedSecretConfigured": false
},
{
"storePlatform": "Apple",
"productId": "com.yourbrand.app.yearly",
"displayName": "Yearly access",
"billingPeriod": "Yearly",
"isActive": true,
"storeSharedSecretConfigured": false
},
{
"storePlatform": "Google",
"productId": "com.yourbrand.app.monthly",
"displayName": "Monthly access",
"billingPeriod": "Monthly",
"isActive": true,
"storeSharedSecretConfigured": false
}
],
"vodPpv": {
"isEnabled": true,
"accessDurationHours": 48,
"storeProducts": [
{
"storePlatform": "Apple",
"productId": "com.yourbrand.app.vod",
"displayName": "Unlock VOD",
"billingPeriod": "OneTime",
"isActive": true,
"storeSharedSecretConfigured": false
},
{
"storePlatform": "Google",
"productId": "com.yourbrand.app.vod",
"displayName": "Unlock VOD",
"billingPeriod": "OneTime",
"isActive": true,
"storeSharedSecretConfigured": false
}
]
},
"mobile": {
"appSlug": "my-network",
"logoUrl": "/api/v1/services/custom/users/123/apps/mobile/assets/logo?v=638500000000000000",
"logoBlobKey": "db:logo",
"iconUrl": "/api/v1/services/custom/users/123/apps/mobile/assets/icon?v=638500000000000000",
"iconBlobKey": "db:icon",
"selectionColor": "FF5722",
"headerFooterColor": "212121",
"backgroundColor": "000000",
"fontColor": "FFFFFF",
"about": "Welcome to my channel network.",
"copyrightPolicyLink": null,
"gdprLink": null,
"supportEmail": "[email protected]",
"faqLink": null,
"termsLink": null,
"privacyPolicyLink": "https://example.com/privacy",
"instagram": null,
"facebook": null,
"twitter": null
},
"roku": null,
"fireTv": null,
"appleTv": null,
"androidTv": null
}
}
Only the platform-specific object is populated (mobile, roku, fireTv, appleTv, or androidTv).
The others are null.
Example: roku object (GET /apps/roku)
"roku": {
"privacyPolicyLink": "https://example.com/privacy",
"about": "Welcome to my channel network.",
"advertisementLink": null,
"avatarHdUrl": "/api/v1/services/custom/users/123/apps/roku/assets/avatar-hd?v=638500000000000000",
"avatarHdBlobKey": "db:avatar-hd",
"avatarSdUrl": "/api/v1/services/custom/users/123/apps/roku/assets/avatar-sd?v=638500000000000000",
"avatarSdBlobKey": "db:avatar-sd",
"apiKey": "00000000-0000-0000-0000-000000000000",
"primaryColor": "E17600",
"secondaryColor": "BBBBBB",
"backgroundColor": "000000",
"styleColor": "FFFFFF"
}
Color scheme. Every TV app object (roku, fireTv, appleTv,
androidTv) carries the same four theme roles as 6-digit hex without #, edited in
Studio → Apps, and the TV templates render them the same way. androidTv has no separate
backgroundColor. Roku apps created before the scheme became editable report the stock
template colors shown above.
| Field | Used for |
|---|---|
primaryColor | Accent: focus rings, selected borders, active labels and the "Playing now" header. |
secondaryColor | Secondary text: programme times, hints, descriptions. |
backgroundColor | Base surface behind everything; panels, cards and the guide band are derived from it. |
styleColor | Primary text: titles and channel names. |
storeProducts lists every paid subscription SKU for the app
(weekly / monthly / yearly per store). Multiple rows per store are allowed.
vodPpv remains one one-time SKU per store for VOD unlocks.
Prices are configured in App Store Connect / Google Play — Strimm stores Product IDs only.
Channels
/channels
Lists all channels owned by the authenticated user, each including its video library and any platform-specific VAST ad settings that have been configured.
Example response
{
"success": true,
"data": [
{
"channelTubeId": 42,
"name": "Main Channel",
"url": "main-channel",
"categoryName": "Entertainment",
"pictureUrl": "https://cdn.example.com/tubestrimm/123/channel.jpg",
"description": "My flagship channel.",
"order": 1,
"videos": [
{
"videoTubeId": 1001,
"title": "Intro to the Network",
"description": "A quick overview.",
"durationSeconds": 185.5,
"thumbnailUrl": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg",
"providerVideoId": "dQw4w9WgXcQ",
"providerName": "YouTube",
"categoryName": "Promo"
},
{
"videoTubeId": 1002,
"title": "Behind the Scenes",
"description": null,
"durationSeconds": 612,
"thumbnailUrl": "https://cdn.example.com/tubestrimm/123/thumb.jpg",
"providerVideoId": "abc123",
"providerName": "Custom",
"categoryName": "Documentary"
}
],
"vastSettings": [
{
"platform": "web",
"vastUrl": "https://ads.example.com/vast?channel=42&platform=web",
"vastVersion": 1,
"skippable": true,
"adFrequency": 1,
"midRollFrequency": 10,
"slottable": false,
"timeFrom": null,
"timeTo": null,
"vastType": "fullscreen",
"allowAdsInVod": false
},
{
"platform": "roku",
"vastUrl": "https://ads.example.com/vast?channel=42&platform=roku",
"vastVersion": 1,
"skippable": false,
"adFrequency": 1,
"midRollFrequency": 0,
"slottable": true,
"timeFrom": 18,
"timeTo": 23,
"vastType": "fullscreen",
"allowAdsInVod": false
}
]
},
{
"channelTubeId": 58,
"name": "Kids Corner",
"url": "kids-corner",
"categoryName": "Kids",
"pictureUrl": null,
"description": null,
"order": 2,
"videos": [],
"vastSettings": []
}
]
}
/channels/{channelId}
Returns a single channel by numeric id, including videos and any configured platform-specific VAST ad settings.
Example response
{
"success": true,
"data": {
"channelTubeId": 42,
"name": "Main Channel",
"url": "main-channel",
"categoryName": "Entertainment",
"pictureUrl": "https://cdn.example.com/tubestrimm/123/channel.jpg",
"description": "My flagship channel.",
"order": 1,
"videos": [
{
"videoTubeId": 1001,
"title": "Intro to the Network",
"description": "A quick overview.",
"durationSeconds": 185.5,
"thumbnailUrl": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg",
"providerVideoId": "dQw4w9WgXcQ",
"providerName": "YouTube",
"categoryName": "Promo"
}
],
"vastSettings": [
{
"platform": "web",
"vastUrl": "https://ads.example.com/vast?channel=42&platform=web",
"vastVersion": 1,
"skippable": true,
"adFrequency": 1,
"midRollFrequency": 10,
"slottable": false,
"timeFrom": null,
"timeTo": null,
"vastType": "fullscreen",
"allowAdsInVod": false
}
]
}
}
VAST settings object
vastSettings is an array containing one entry per platform that has a VAST tag URL configured in the studio.
Platforms without ads configured are omitted, so an empty array means no platform-specific ads are set for the channel.
| Field | Type | Description |
|---|---|---|
platform | string | Target platform: web, roku, mobile, firetv, appletv, or androidtv. |
vastUrl | string | The VAST ad tag URL used for this platform. |
vastVersion | integer | Internal VAST configuration version. |
skippable | boolean | Whether ads can be skipped. |
adFrequency | integer | null | Pre-roll frequency (play an ad every N items). |
midRollFrequency | integer | null | Mid-roll frequency as a percentage interval; 0 disables mid-rolls. |
slottable | boolean | Whether ads are restricted to a daily time window. |
timeFrom | integer | null | Start hour (0–23) of the ad time window when slottable is true. |
timeTo | integer | null | End hour (0–23) of the ad time window when slottable is true. |
vastType | string | null | Ad presentation: fullscreen or picInPic. |
allowAdsInVod | boolean | When true, VAST ads may also run during VOD (on-demand) playback for this platform. |
Schedules
/channels/{channelId}/schedules?date=yyyy-MM-dd
Returns schedule blocks for a channel on the given date, including ordered videos with playback times.
Both regular scheduled videos and live streams linked to the channel are included. Each video has
isLive: false for regular schedule entries and
true for live streams. Live streams appear as single-video blocks sorted
with regular blocks by start time; their channelScheduleId is the negative
of the live video id.
Example request
GET /api/v1/rest/channels/42/schedules?date=2026-05-29
Authorization: Bearer {authToken}
Example response
{
"success": true,
"data": {
"channelTubeId": 42,
"date": "2026-05-29",
"schedules": [
{
"channelScheduleId": 901,
"startTime": "2026-05-29T06:00:00",
"published": true,
"loopDaily": false,
"videos": [
{
"videoTubeId": 1001,
"playbackOrderNumber": 1,
"title": "Morning Show",
"thumbnailUrl": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg",
"playTimeLabel": "06:00 AM - 06:30 AM",
"playbackStartTime": "2026-05-29T06:00:00",
"playbackEndTime": "2026-05-29T06:30:00",
"providerVideoId": "dQw4w9WgXcQ",
"providerName": "YouTube",
"isLive": false
},
{
"videoTubeId": 1002,
"playbackOrderNumber": 2,
"title": "Behind the Scenes",
"thumbnailUrl": "https://cdn.example.com/tubestrimm/123/thumb.jpg",
"playTimeLabel": "06:30 AM - 07:10 AM",
"playbackStartTime": "2026-05-29T06:30:00",
"playbackEndTime": "2026-05-29T07:10:00",
"providerVideoId": "abc123",
"providerName": "Custom",
"isLive": false
}
]
},
{
"channelScheduleId": -5501,
"startTime": "2026-05-29T14:00:00",
"published": true,
"loopDaily": false,
"videos": [
{
"videoTubeId": 5501,
"playbackOrderNumber": 1,
"title": "Live Town Hall",
"thumbnailUrl": "https://i.ytimg.com/vi/liveExample/hqdefault.jpg",
"playTimeLabel": "02:00 PM - 04:00 PM",
"playbackStartTime": "2026-05-29T14:00:00",
"playbackEndTime": "2026-05-29T16:00:00",
"providerVideoId": "liveExample",
"providerName": "YouTube",
"isLive": true
}
]
}
],
"totalVideos": 3,
"totalDurationLabel": "3h 10m"
}
}
Schedule times are returned in the channel's local timezone. When no blocks exist for the date,
schedules is an empty array and totalVideos is 0.
totalVideos and totalDurationLabel include both regular and live entries.
Favorites
Manage the authenticated user's favorite channels. Favorites are stored server-side and scoped to the
current user (the account identified by the Bearer token), so the same list is available across every device
and integration. All endpoints require the Authorization: Bearer {authToken} header.
/favorites
Lists the channels the current user has favorited, most recently favorited first.
Example request
GET /api/v1/rest/favorites
Authorization: Bearer {authToken}
Example response
{
"success": true,
"data": [
{
"channelTubeId": 42,
"name": "Main Channel",
"url": "main-channel",
"categoryName": "Entertainment",
"pictureUrl": "https://cdn.example.com/tubestrimm/123/channel.jpg",
"description": "My flagship channel.",
"favoritedAt": "2026-06-23T09:15:00Z"
},
{
"channelTubeId": 58,
"name": "Kids Corner",
"url": "kids-corner",
"categoryName": "Kids",
"pictureUrl": null,
"description": null,
"favoritedAt": "2026-06-20T18:02:11Z"
}
]
}
When the user has no favorites, data is an empty array.
/favorites/{channelId}
Adds a channel to the current user's favorites. The call is idempotent — favoriting a channel that is
already a favorite still returns success. Returns channel_not_found when the
channel id does not exist or has been deleted.
Example request
POST /api/v1/rest/favorites/42
Authorization: Bearer {authToken}
Example response
{
"success": true,
"data": {
"channelTubeId": 42,
"isFavorite": true
}
}
/favorites/{channelId}
Removes a channel from the current user's favorites. The call is idempotent — removing a channel that
is not a favorite still returns success. Returns channel_not_found when the
channel id does not exist or has been deleted.
Example request
DELETE /api/v1/rest/favorites/42
Authorization: Bearer {authToken}
Example response
{
"success": true,
"data": {
"channelTubeId": 42,
"isFavorite": false
}
}
REST API error codes
unauthorized— missing or invalid Bearer tokeninvalid_credentials— login failedaccount_locked— account is lockedaccount_not_activated— email not confirmedapp_not_found— no app configured for the platformchannel_not_found— channel id not found or not owned by userunsupported_platform— unknown app platform
Custom Services API (mobile & TV apps)
Legacy-compatible API used by the Strimm mobile app template (api/v1/services/custom).
Responses wrap payloads in { data: ... } without a success flag.
Auth tokens are the same GUID Bearer tokens stored in strimm.AuthToken.
Base URL
https://strimm.com/api/v1/services/custom
Response envelope
Successful responses:
{
"data": { ... }
}
Validation errors (HTTP 422):
{
"data": {
"message": "The given data was invalid.",
"errors": { ... }
}
}
Not found (HTTP 404):
{
"data": {
"message": "User is required",
"status_code": 404
}
}
Common headers
Authorization: Bearer {access_token}— required on protected auth routesPlatform-Id— the calling app:ios/android(mobile),roku,fire-tv,apple-tvorandroid-tv. Selects the app record forapp_settings, the store for SKU selection and entitlements (Apple, Google, Amazon or Roku Pay), and scopes channel lists to the channels assigned to that app (falls back toPlatform)Platform: mobile— legacy form of the same headerDevice-Id— device id for subscription / VOD PPV entitlements (falls back toAccept-Platform-Device-Id)timezone— IANA or Windows timezone id for schedule-day filtering (e.g.America/New_York)Accept-Platform-Device-Id— legacy device id for password-unlock flows
Paid apps and VOD PPV may return HTTP 403 with
{ "data": { "message": "subscription_required", "status_code": 403 } }
on channel/schedule/VOD list endpoints when the viewer is not entitled.
Custom API — Authentication
/auth/login
No auth required. Accepts email (or username) and password.
{
"email": "[email protected]",
"password": "your_password"
}
{
"data": {
"access_token": "00000000-0000-0000-0000-000000000000",
"token_type": "bearer",
"expires_in": 3600
}
}
/auth/refresh
Bearer required. Revokes the current token and returns a new one.
/auth/me
Bearer required.
{
"data": {
"id": 123,
"full_name": "Jane Creator",
"public_name": "creator",
"publicUrl": "creator",
"email": "[email protected]"
}
}
/auth/logout
Bearer required. Revokes the token.
{
"data": { "message": "Success" }
}
Custom API — User & branding
Path parameter {id} is the account owner's numeric user id or publicUrl slug
(same value as the mobile app USER_ID env var).
/users/{id}/settings
White-label web/app branding from UserCustomApps, or mobile app colors when configured.
{
"data": {
"user_id": 123,
"title": "My Network",
"hex1": "#EF4E32",
"hex2": "#091221",
"hex3": "#102944",
"fontColor": "#EAE9F9",
"header_background": "white",
"FAQ": "...",
"PrivacyPolicy": "https://example.com/privacy",
"logo_header": "{base64}",
"logo_android": "{base64}",
"useVastSettings": false
}
}
/users/{id}/app_settings
App record from Studio → Apps for the calling platform. The Platform-Id header is
required: ios / android / mobile,
roku, fire-tv, apple-tv or android-tv
(the legacy Platform header is still accepted). It selects which app record and
store product IDs are returned; a missing or unknown value returns HTTP 422 with
errors.platform_id instead of silently falling back to the mobile app.
{
"data": {
"user_id": 123,
"slug": "my-network",
"app_name": "My Network App",
"hex1": "#FF5722",
"hex2": "#212121",
"hex3": "#000000",
"fontColor": "#FFFFFF",
"Logo": "{base64}",
"Icon": "{base64}",
"privacy_policy_link": "https://example.com/privacy",
"about": "Welcome.",
"platform": "Mobile",
"app_id": "7",
"is_paid": true,
"store_product_id": "com.yourbrand.app.weekly",
"store_products": [
{
"product_id": "com.yourbrand.app.weekly",
"billing_period": "Weekly",
"display_name": "Weekly access"
},
{
"product_id": "com.yourbrand.app.monthly",
"billing_period": "Monthly",
"display_name": "Monthly access"
},
{
"product_id": "com.yourbrand.app.yearly",
"billing_period": "Yearly",
"display_name": "Yearly access"
}
],
"vod_ppv_enabled": true,
"vod_ppv_store_product_id": "com.yourbrand.app.vod",
"vod_ppv_access_hours": 48
}
}
is_paid gates app-wide access via the subscription endpoints.
store_products lists every configured subscription for this client store;
store_product_id is the primary/first id (compat).
When vod_ppv_enabled is true, each VOD video requires a separate one-time purchase
(vod_ppv_store_product_id) that unlocks that video for vod_ppv_access_hours.
TV apps. With Platform-Id: roku, fire-tv, apple-tv or
android-tv the same shape carries that app's record. The color slots map to the TV theme
roles edited in Studio → Apps: hex1 = primary, hex2 = secondary,
hex3 = background, fontColor = style. Roku additionally returns
ad_link (the optional app-level VAST tag) and reads these settings on every launch, so a
color change reaches installed channels without a rebuild.
GET /api/v1/services/custom/users/123/app_settings
Platform-Id: roku
Device-Id: device-unique-id
{
"data": {
"user_id": 123,
"slug": "My Network",
"app_name": "My Network",
"hex1": "#E17600",
"hex2": "#BBBBBB",
"hex3": "#000000",
"fontColor": "#FFFFFF",
"Logo": "",
"Icon": "",
"privacy_policy_link": "https://example.com/privacy",
"about": "Welcome to my channel network.",
"platform": "Roku",
"app_id": "2",
"is_paid": false,
"store_product_id": null,
"vod_ppv_enabled": false,
"vod_ppv_store_product_id": null,
"vod_ppv_access_hours": 48,
"vod_ppv_preview_seconds": 0,
"store_products": [],
"time_format": "12-hour",
"ad_link": null
}
}
/users/{id}/categories?default=1
Channel categories for filters. Pass default=1 to omit nested channels.
/users/{id}/languages
Languages available for channel filtering.
Custom API — Channels & playback
/users/{id}/channels
Channels scheduled for today. Send Platform: mobile to limit to channels assigned in the mobile app.
Query params: language_id, category_id (comma-separated; 999 = live only),
search, skip, take, newest, oldest, most_subscribed.
GET /api/v1/services/custom/users/creator/channels?skip=0&take=20
Platform: mobile
timezone: America/New_York
{
"data": [
{
"id": 42,
"categoryId": 3,
"userId": 123,
"name": "Main Channel",
"url": "main-channel",
"pictureUrl": "https://cdn.example.com/.../channel.jpg",
"isWhiteLabeled": 1,
"playLiveFirst": false,
"privateChannel": false,
"isVerified": true,
"liveAvailable": true,
"guideMode": "fixed",
"keepGuideOpened": 0,
"vodAvailable": true,
"scheduleAvailable": true
}
]
}
vodAvailable is true when the channel has at least one linked VOD catalog video.
scheduleAvailable is true when the channel has a published linear schedule for today
(request timezone). Apps use these flags to show a VOD mode toggle and to keep VOD-only channels
in the list even when they have no schedule for today.
/users/{id}/channels/video
Scheduled videos for one or more channels and dates. Required query: channels_ids (comma-separated),
dates (comma-separated; yyyy-MM-dd, or the compact yyyyMMdd /
yyyyMMddHHmmss forms — any time part is ignored, schedules resolve per calendar day).
Optional: page, per_page, timezone.
GET /api/v1/services/custom/users/creator/channels/video?channels_ids=42,58&dates=2026-06-04&page=1&per_page=6
{
"data": [
{
"customId": "42-1001-1",
"videoTubeId": 1001,
"userId": 123,
"title": "Morning Show",
"providerVideoId": "dQw4w9WgXcQ",
"channelId": 42,
"duration": 1800,
"timeDuration": "0h. 30min",
"startDate": "2026-06-04 06:00:00",
"endDate": "2026-06-04 06:30:00",
"providerName": "YouTube",
"durationInDate": "6:00am-6:30am",
"thumbnail": "https://i.ytimg.com/vi/.../hqdefault.jpg",
"streamUrl": null,
"isVod": false
}
],
"links": { "first": null, "last": null, "prev": null, "next": null },
"meta": {
"current_page": 1,
"last_page": 1,
"per_page": 6,
"total": 1
}
}
Note: this endpoint returns the paginated object at the top level (data / links / meta),
not wrapped in an extra { data } envelope. isVod is always false for schedule rows.
/users/{id}/channels/vod
On-demand (VOD) catalog for one or more channels. Same paginated shape as
/users/{id}/channels/video. Required query: channels_ids (comma-separated).
Optional: page, per_page (default 50).
GET /api/v1/services/custom/users/creator/channels/vod?channels_ids=42&page=1&per_page=50
Platform-Id: ios
Device-Id: device-unique-id
{
"data": [
{
"customId": "42-2001-vod",
"videoTubeId": 2001,
"userId": 123,
"title": "Highlight Reel",
"providerVideoId": "987654321",
"channelId": 42,
"duration": 720,
"timeDuration": "0h. 12min",
"startDate": "2026-06-04 00:00:00",
"endDate": "2026-06-04 00:12:00",
"providerName": "Vimeo",
"durationInDate": "0:00-0:12",
"thumbnail": "https://cdn.example.com/.../thumb.jpg",
"streamUrl": "https://player.vimeo.com/...",
"isVod": true
}
],
"links": { "first": null, "last": null, "prev": null, "next": null },
"meta": {
"current_page": 1,
"last_page": 1,
"per_page": 50,
"total": 1
}
}
Apps should render timeDuration (not schedule start/end) when isVod is true.
When app VOD PPV is enabled, unlock each videoTubeId via the VOD PPV endpoints before playback.
/getChannelToken
Unlock a password-protected channel.
{
"channel_id": 42,
"password": "channel-secret"
}
With Accept-Platform-Device-Id, returns { "data": { "message": "Success" } }.
With Bearer auth only, returns a fresh token payload (same shape as login).
Custom API — Video tokens, live & favorites
/token_by_video/{videoTubeId}
Returns cached Vimeo progressive playback renditions for a video. Used by TV/app clients to pick the best width (1280 / 960 / 640 / 426) for direct playback. Non-expired renditions are returned when available; otherwise every cached rendition is returned so the client can still attempt playback.
GET /api/v1/services/custom/token_by_video/1001
{
"data": [
{
"url": "https://vod-progressive.akamaized.net/.../video-1280.mp4",
"expiration_date": "2026-06-08T18:30:00Z",
"width": "1280",
"height": "720"
},
{
"url": "https://vod-progressive.akamaized.net/.../video-640.mp4",
"expiration_date": "2026-06-08T18:30:00Z",
"width": "640",
"height": "360"
}
]
}
Returns { "data": [] } when no cached renditions exist for the video (e.g. non-Vimeo providers,
which are played directly via providerVideoId).
/users/{id}/channels/{channelId}/live?date=yyyy-MM-dd
Live-stream videos scheduled on a channel for the given day. When date is omitted the current
UTC date is used. Times are formatted yyyy-MM-dd HH:mm:ss.
GET /api/v1/services/custom/users/creator/channels/42/live?date=2026-06-08
{
"data": [
{
"videoTubeId": 5001,
"channelId": "42",
"startDate": "2026-06-08 19:00:00",
"endDate": "2026-06-08 20:00:00",
"description": "Live keynote",
"timeDuration": "1h. 0min",
"isPrivate": false,
"IsRRated": false,
"isRemovedByProvider": false,
"isRestrictedByProvider": false,
"providerVideoId": "987654321",
"thumbnail": "https://cdn.example.com/.../live.jpg",
"title": "Evening Live",
"uri": "",
"providerName": "Vimeo",
"live": true
}
]
}
/users/{id}/app/favorites
Lists the channels the user has favorited, most recently favorited first. Each item uses the same channel
shape as /users/{id}/channels with marked set to true.
GET /api/v1/services/custom/users/creator/app/favorites
{
"data": [
{
"id": 42,
"name": "Creator Channel",
"url": "creator-channel",
"pictureUrl": "https://cdn.example.com/.../channel.jpg",
"liveAvailable": true,
"marked": true
}
]
}
When the user has no favorites, data is an empty array.
/users/{id}/channels/{channelId}/app/favorite/add
/users/{id}/channels/{channelId}/app/favorite/remove
Adds or removes a channel from the user's favorites. The server validates that the channel exists and belongs to the account, persists the change server-side, then returns success (HTTP 200). Both calls are idempotent — re-adding an existing favorite or removing one that is not favorited still returns success.
{
"data": { "message": "Success" }
}
Returns 404 with { "data": { "message": "Channel not found", "status_code": 404 } }
when the channel is missing or not owned by the account.
/channels/{channelId}/vast?platform=mobile
Platform-specific VAST settings for a channel. Prefer Platform-Id header; optional
platform query overrides it. Response uses PascalCase keys for legacy TV clients.
{
"data": {
"ChannelId": 42,
"VastVersion": 1,
"VastUrl": "https://ads.example.com/vast?channel=42",
"Skippable": false,
"AdFrequency": 1,
"MidRollFrequency": 10,
"Slottable": false,
"TimeFrom": null,
"TimeTo": null,
"VastType": "fullscreen",
"Platform": "mobile",
"AllowAdsInVod": false
}
}
Custom API — Subscriptions & VOD PPV
Native store purchases for white-label apps configured in Studio → Apps.
Send Platform-Id (ios / android / roku / fire-tv /
apple-tv / android-tv) and Device-Id on every call.
store_platform in request bodies is Apple, Google, Amazon or
Roku (Roku Pay: receipt_data is the Channel Store transaction id).
/users/{id}/apps/subscription/status
Whether the device/viewer is entitled to a paid app. When the app is not marked paid,
entitled is true and isPaidApp is false.
{
"data": {
"entitled": true,
"status": "active",
"expiresUtc": "2026-09-01T12:00:00Z",
"isPaidApp": true,
"storeProductId": "com.yourbrand.app.weekly",
"storeProductIds": [
"com.yourbrand.app.weekly",
"com.yourbrand.app.monthly",
"com.yourbrand.app.yearly"
]
}
}
/users/{id}/apps/subscription/verify
Verifies a store subscription receipt / purchase token and records entitlement for the device (and viewer when authenticated).
product_id must be one of the configured subscription Product IDs for that store
(any billing period).
{
"store_platform": "Apple",
"product_id": "com.yourbrand.app.monthly",
"receipt_data": "{transaction-receipt-or-purchase-token}",
"original_transaction_id": "1000000123456789",
"device_id": "device-unique-id"
}
{
"data": {
"ok": true,
"entitled": true,
"error": null,
"expiresUtc": "2026-09-01T12:00:00Z"
}
}
/users/{id}/apps/subscription/restore
Restores entitlement from known original transaction ids (and/or device history). Same result shape as verify.
{
"store_platform": "Apple",
"device_id": "device-unique-id",
"original_transaction_ids": ["1000000123456789"]
}
/users/{id}/apps/vod_ppv/status?video_tube_id={videoTubeId}&channel_tube_id={channelTubeId}
Per-video unlock status for app-level VOD pay-per-view. When VOD PPV is disabled for the app,
unlocked is true and vodPpvEnabled is false.
channel_tube_id is optional: the app-level switch says the app sells unlocks, the
channel's Pay-Per-View setting says which videos need one, so pass the channel the video is
being watched from when the same video appears in several channels.
GET /api/v1/services/custom/users/creator/apps/vod_ppv/status?video_tube_id=2001
Platform-Id: ios
Device-Id: device-unique-id
{
"data": {
"vodPpvEnabled": true,
"unlocked": false,
"expiresUtc": null,
"storeProductId": "com.yourbrand.app.vod",
"accessDurationHours": 48
}
}
/users/{id}/apps/vod_ppv/verify
Verifies a one-time store purchase and unlocks a single video_tube_id for
accessDurationHours. Clients should finish the store transaction as consumable so the
same Product ID can unlock another video later. channel_tube_id is optional (same
meaning as on status).
{
"store_platform": "Google",
"product_id": "com.yourbrand.app.vod",
"receipt_data": "{purchase-token}",
"original_transaction_id": "GPA.1234-5678",
"device_id": "device-unique-id",
"video_tube_id": 2001,
"channel_tube_id": 42
}
{
"data": {
"ok": true,
"unlocked": true,
"error": null,
"expiresUtc": "2026-06-06T18:00:00Z"
}
}
Validation failures return HTTP 422 with
{ "data": { "message": "The given data was invalid.", "errors": { "vod_ppv": "..." } } }.
Custom API — Analytics
Activity ingestion for the white-label TV and mobile apps. Replaces the retired
analytics-api.strimm.com service: apps report watch heartbeats and
login/logout events directly to this host.
/activity
No auth required. Accepts application/json or
application/x-www-form-urlencoded bodies. Also reachable at the
legacy-compatible path https://strimm.com/api/v1/activity (same handler) for
clients that kept the old URL shape and only swap the host.
Request body
{
"source": "android_tv",
"action": "play_channel",
"client_id": "123",
"channel_id": "42",
"user_id": "device-id-or-viewer-id"
}
Fields
| Field | Type | Description |
|---|---|---|
source | string | Required. One of roku_app, fire_tv, android_tv, apple_tv, mobile_app_on_ios, mobile_app_on_android, custom_app_on_ios, custom_app_on_android, website_embedded_player, broadcast_on_strimm_dot_com. |
action | string | Required. play_channel, login, or logout (other legacy action names are accepted but not processed). |
client_id | integer | string | Strimm account owner user id (the app's USER_ID). |
user_id | string | End-viewer/device identifier (e.g. Android ID, identifierForVendor, Roku tracking id). Required for login/logout. |
channel_id | integer | string | Channel being played. Required for play_channel. |
payload | any | null | Optional extra data, stored as-is. |
Response (HTTP 200)
{
"message": "Success"
}
Note: for compatibility with the legacy analytics contract this endpoint returns a bare
{ "message" } object, not the { data } envelope used by the rest of the Custom API.
Watch-session heartbeats
While a channel is playing, post a play_channel event every 60 seconds.
The server folds consecutive heartbeats with the same
source + client_id + user_id + channel_id
into one watch session, extending its end time on each heartbeat. If no heartbeat arrives for more than
3 minutes the session is closed and its duration recorded (minimum 60 seconds credited); the next heartbeat
starts a new session.
Errors
403invalid_user— the owner ofchannel_idhas no qualifying subscription order422— validation failed (unknownsource/action, missing required field, or unparsable body)
Custom API notes
-
There are no platform-specific route trees. Every bundled template (mobile, Roku, Fire TV, Apple TV,
Android TV) calls these routes with its own
Platform-Id; the Roku template also gets itsuser_idandapi_base_urlbaked intodata/config.jsonat download. - Favorites (list/add/remove) are persisted server-side per user. Watch-later, search, and social auth endpoints are not yet implemented on this host.
-
Paid subscription and VOD PPV are configured per app in Studio → Apps. Subscription is app-wide;
VOD PPV unlocks are per
videoTubeId+ device (or authenticated viewer). -
Archive builds bake
IS_PAID,STORE_PRODUCT_ID_*,VOD_PPV_ENABLED,VOD_PPV_STORE_PRODUCT_ID_*, andVOD_PPV_ACCESS_HOURSinto the mobile template.env. - Configure the mobile app
API_BASE_URLto this site's origin (e.g.https://strimm.com).
Legacy Web Services (ASMX-compatible)
Read-only compatibility endpoints that mirror the old *.asmx web services, kept for
shipped Roku / mobile / TV apps that still call the original URLs. Paths, parameters and response
bytes are identical to the legacy site — new integrations should use the REST API above instead.
Base URL
https://strimm.com/WebServices
Conventions
- No authentication. Every endpoint accepts GET (query string) and POST (
application/x-www-form-urlencodedbody). - Except for
GetVastSettings(raw JSON body), responses are JSON wrapped in the classic ASMX XML envelope, served astext/xml; charset=utf-8:
<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://tempuri.org/">{ ...json... }</string>
- Every declared parameter must be present on the wire (an empty value counts); omitting one returns the legacy HTTP 500
Missing parameterplain-text page. - JSON keys are PascalCase and lookups that find no row serialize as the literal
null.
Legacy — VAST settings
/VastService.asmx/GetVastSettings?channelId={channelId}
VAST ad settings for a channel. Unlike the other legacy endpoints, the response is a raw JSON body
(no XML envelope, no Content-Type header). When the channel has per-platform rows configured,
the web row is returned.
Example response
{
"ChannelId": 42,
"VastVersion": 1,
"VastUrl": "https://ads.example.com/vast?channel=42",
"Skippable": false,
"AdFrequency": 1,
"MidRollFrequency": 10,
"Slottable": false,
"TimeFrom": null,
"TimeTo": null,
"VastType": "fullscreen",
"Platform": "web",
"AllowAdsInVod": false
}
Returns the literal null when the channel has no VAST settings.
Legacy — Roku app
/RokuAppGeneratorService.asmx/GetChannelTubeRokuSettings?channelId={channelId}
Whether a channel is included in the account's Roku app.
Example response (JSON inside the XML envelope)
{
"ChannelTubeId": 42,
"AddedToRoku": true,
"LastUpdateDate": "2024-01-22T12:56:28"
}
/RokuAppGeneratorService.asmx/GetUserRokuApp?userId={userId}
The account owner's Roku app record. Images are base64-encoded PNG bytes.
Example response (JSON inside the XML envelope)
{
"UserID": 123,
"AppName": "My Network",
"AdLink": "https://ads.example.com/roku",
"About": "Welcome to my channel network.",
"PrivacyPolicyLink": "https://example.com/privacy",
"ImageHD": "{base64}",
"ImageSD": "{base64}",
"ApiKey": "00000000-0000-0000-0000-000000000000",
"PrimaryColor": "E17600",
"SecondaryColor": "BBBBBB",
"BackgroundColor": "000000",
"StyleColor": "FFFFFF"
}
The four *Color fields (6-digit hex, no #) are the Roku color scheme from Studio → Apps;
the Custom API app_settings serves them
as hex1–hex3 / fontColor.
Legacy — Mobile app
/MobileAppGeneratorService.asmx/GetChannelMobileApp?userId={userId}&channelId={channelId}
The account owner's mobile app branding plus the channel's app membership
(Sorting, AddedToApp, UseVastSettings come from the channel's
app assignment; they are null / account-level when the channel is not assigned).
Example response (JSON inside the XML envelope)
{
"UserID": 123,
"ChannelTubeId": 42,
"HeaderTitle": "My Network",
"Slug": "my-network",
"HeaderLogo": "{base64}",
"LogoIOS": "{base64}",
"LogoAndroid": null,
"Hex1": "FF5722",
"Hex2": "212121",
"Hex3": "000000",
"FontColor": "FFFFFF",
"About": "Welcome.",
"Sorting": 1,
"CopyrightLink": "",
"GDPRLink": "",
"CustomerSupportEmail": "[email protected]",
"FAQ": "",
"TermsLink": "",
"PrivacyPolicyLink": "https://example.com/privacy",
"Instagram": "",
"Facebook": "",
"Twitter": "",
"AddedToApp": true,
"UseVastSettings": false
}
When userId or channelId is sent empty, the envelope contains the plain string
One of the required fields is not passed.
Legacy — TV app
/TVAppGeneratorService.asmx/GetUserTVApp?userId={userId}&platform={platform}&skipImages={true|false}
The account owner's TV app (theme, images, and per-channel settings) for a platform:
fire-tv, android-tv, or apple-tv.
With skipImages=true the binary fields (Logo, Icon,
BackgroundImage, Image1, Image2) and AppId are returned as null.
Each entry in Settings includes the channel's VAST configuration when
UseVastSettings is enabled.
Example response (JSON inside the XML envelope)
{
"UserID": 123,
"AppName": "My Network TV",
"Slug": "my-network-tv",
"About": "Welcome.",
"PrivacyPolicyLink": "https://example.com/privacy",
"Logo": null,
"Icon": null,
"BackgroundImage": null,
"Image1": null,
"Image2": null,
"PrimaryColor": "FF5722",
"SecondaryColor": "212121",
"BackgroundColor": "000000",
"StyleColor": "102944",
"Platform": "fire-tv",
"ChannelId": null,
"AppId": null,
"Settings": [
{
"ChannelTubeId": 42,
"AddedToTV": true,
"Platform": "fire-tv",
"UseVastSettings": true,
"ChannelNumber": "1",
"AppId": null,
"LastUpdateDate": "2026-05-29T10:15:00",
"VastSettings": {
"ChannelId": 42,
"VastVersion": 1,
"VastUrl": "https://ads.example.com/vast?channel=42",
"Skippable": false,
"AdFrequency": 1,
"MidRollFrequency": 10,
"Slottable": false,
"TimeFrom": null,
"TimeTo": null,
"VastType": "fullscreen",
"Platform": "fire-tv",
"AllowAdsInVod": false
}
}
]
}
Errors (HTTP 200, JSON inside the XML envelope)
{"error":"One of the required fields is not passed"}—userIdorplatformsent empty{"error":"Application does not exist on {platform} platform"}— no app configured for the user on that platform