REST API reference

Uscreen API

15 endpoints for Uscreen. Each one is a POST with a JSON body, called with your API key.

Base URL
https://cotlet.dev/api/v1/uscreen
Connects with
Your own Uscreen admin account (store owner, or a team member who can open Content, Marketing and Community)
Integration page
Uscreen
Uscreen Endpoints
Endpoint Access Description
list_videos read Videos in your library with status, categories and release date.
get_video read One video: title, description, tags, categories, publication status and the collections it is in.
list_collections read Collections with status, categories and number of videos.
get_collection read A collection with its playlist in order: videos, dividers and drip days.
list_live_events read Live events with start time, streaming method and status.
get_content_analytics read Views, watch time and completion for videos, live events or collections in a period.
list_community_channels read Channels of your community with ID, name and whether they are public or private.
upload_video write Upload a video file from a URL. It is saved unpublished and processed by Uscreen.
update_video write Change the title, description, tags or categories of a video.
publish_video write Publish a video now or schedule its release, optionally emailing members.
create_collection write New collection from uploaded videos, saved unpublished.
set_collection_playlist write Replace the playlist of a collection: video order, dividers and drip days.
create_live_event write Create a live event; for RTMP it returns the stream URL and stream key.
create_coupon write New coupon code with a discount, target, limits and expiry.
create_community_post write Post as you in a community channel, now or at a set time.

POST https://cotlet.dev/api/v1/uscreen/list_videos

Returns videos with their publication status, categories and, for scheduled videos, the release date. A video that is still processing is marked as such. Uscreen processes a new upload for 10 minutes to 72 hours. Videos without a category are listed but stay out of the catalog.

Parameters

Parameters: list_videos
NameTypeDescription
status enum published, unpublished or scheduled. Empty: all.
search string Match on title.
limit integer Maximum videos to return.
cursor string Next page cursor from the previous call.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/uscreen/list_videos \
  -H "Authorization: Bearer $COTLET_API_KEY"
Python
result = client.call("uscreen", "list_videos")
Node.js
const result = await cotlet.call('uscreen', 'list_videos');
CLI
cotlet call uscreen list_videos

Example response

{
  "videos": [
    {
      "video_id": "2390417",
      "title": "Mobility Basics 1: Ankles",
      "status": "unpublished",
      "category_ids": [
        "48211"
      ],
      "processing": false
    },
    {
      "video_id": "2390418",
      "title": "Mobility Basics 2: Hips",
      "status": "scheduled",
      "release_at": "2026-11-02T07:00:00-05:00",
      "category_ids": [
        "48211"
      ],
      "processing": false
    }
  ],
  "next_cursor": null
}

Get video

read

POST https://cotlet.dev/api/v1/uscreen/get_video

Returns the details shown on the video page in Uscreen. If the video is scheduled, it includes the release date and whether it shows as Coming Soon. It also lists the collections that contain the video, because one video can sit in several.

Parameters

Parameters: get_video
NameTypeDescription
video_id required string Video ID from list_videos.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/uscreen/get_video \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"video_id":"video_8c41d2"}'
Python
result = client.call("uscreen", "get_video", {"video_id":"video_8c41d2"})
Node.js
const result = await cotlet.call('uscreen', 'get_video', {"video_id":"video_8c41d2"});
CLI
cotlet call uscreen get_video --data '{"video_id":"video_8c41d2"}'

Example response

{
  "video_id": "2390417",
  "title": "Mobility Basics 1: Ankles",
  "description": "A 12 minute ankle mobility routine.",
  "status": "unpublished",
  "category_ids": [
    "48211"
  ],
  "tags": [
    "mobility",
    "beginner"
  ],
  "collection_ids": [
    "118204"
  ]
}

POST https://cotlet.dev/api/v1/uscreen/list_collections

Returns each collection with its publication status, categories and video count. A collection appears in the catalog only when it is published and has a category.

Parameters

Parameters: list_collections
NameTypeDescription
search string Match on title.
limit integer Maximum collections to return.
cursor string Next page cursor from the previous call.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/uscreen/list_collections \
  -H "Authorization: Bearer $COTLET_API_KEY"
Python
result = client.call("uscreen", "list_collections")
Node.js
const result = await cotlet.call('uscreen', 'list_collections');
CLI
cotlet call uscreen list_collections

Example response

{
  "collections": [
    {
      "collection_id": "118204",
      "title": "Mobility Basics",
      "status": "unpublished",
      "category_ids": [
        "48211"
      ],
      "video_count": 2
    }
  ],
  "next_cursor": null
}

POST https://cotlet.dev/api/v1/uscreen/get_collection

Returns the playlist in the order viewers see it, with section dividers and the drip delay of each video. It also returns the collection access, gated or free, because drip only works on gated collections.

Parameters

Parameters: get_collection
NameTypeDescription
collection_id required string Collection ID from list_collections.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/uscreen/get_collection \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"collection_id":"collection_8c41d2"}'
Python
result = client.call("uscreen", "get_collection", {"collection_id":"collection_8c41d2"})
Node.js
const result = await cotlet.call('uscreen', 'get_collection', {"collection_id":"collection_8c41d2"});
CLI
cotlet call uscreen get_collection --data '{"collection_id":"collection_8c41d2"}'

Example response

{
  "collection_id": "118204",
  "title": "Mobility Basics",
  "status": "unpublished",
  "access": "gated",
  "items": [
    {
      "divider": "Week 1"
    },
    {
      "video_id": "2390417",
      "title": "Mobility Basics 1: Ankles",
      "drip_days": 0
    },
    {
      "divider": "Week 2"
    },
    {
      "video_id": "2390418",
      "title": "Mobility Basics 2: Hips",
      "drip_days": 7
    }
  ]
}

POST https://cotlet.dev/api/v1/uscreen/list_live_events

Returns each live event with its start time, streaming method (Live Studio, RTMP or Zoom), publication status and whether preregistration is on. It never returns a stream key; create_live_event does that once.

Parameters

Parameters: list_live_events
NameTypeDescription
search string Match on title.
limit integer Maximum events to return.
cursor string Next page cursor from the previous call.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/uscreen/list_live_events \
  -H "Authorization: Bearer $COTLET_API_KEY"
Python
result = client.call("uscreen", "list_live_events")
Node.js
const result = await cotlet.call('uscreen', 'list_live_events');
CLI
cotlet call uscreen list_live_events

Example response

{
  "events": [
    {
      "event_id": "77310",
      "title": "Thursday Q&A",
      "start_at": "2026-11-05T18:00:00-05:00",
      "method": "rtmp",
      "status": "published",
      "preregistration": true
    }
  ],
  "next_cursor": null
}

POST https://cotlet.dev/api/v1/uscreen/get_content_analytics

Returns the totals for the period and one row per item, most views first, matching the Content Analytics reports in Uscreen. Video rows include viewers, watch time and completion rate. Live event rows include preregistered, attendees and replays. Offline viewing is not tracked by Uscreen, so it is not counted.

Parameters

Parameters: get_content_analytics
NameTypeDescription
report required enum videos, live_events or collections.
from required date First day of the period.
to required date Last day of the period.
limit integer Items to return, most views first.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/uscreen/get_content_analytics \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"report":"videos","from":"2026-10-01","to":"2026-10-01"}'
Python
result = client.call("uscreen", "get_content_analytics", {"report":"videos","from":"2026-10-01","to":"2026-10-01"})
Node.js
const result = await cotlet.call('uscreen', 'get_content_analytics', {"report":"videos","from":"2026-10-01","to":"2026-10-01"});
CLI
cotlet call uscreen get_content_analytics --data '{"report":"videos","from":"2026-10-01","to":"2026-10-01"}'

Example response

{
  "report": "videos",
  "from": "2026-10-01",
  "to": "2026-10-31",
  "totals": {
    "views": 1840,
    "viewers": 612
  },
  "rows": [
    {
      "video_id": "2390417",
      "title": "Mobility Basics 1: Ankles",
      "views": 412,
      "viewers": 301,
      "total_watch_time": "71h 20m",
      "completion_rate": "64%"
    },
    {
      "video_id": "2390418",
      "title": "Mobility Basics 2: Hips",
      "views": 366,
      "viewers": 280,
      "total_watch_time": "58h 05m",
      "completion_rate": "59%"
    },
    {
      "video_id": "2390422",
      "title": "Warm-up Flow",
      "views": 301,
      "viewers": 254,
      "total_watch_time": "40h 10m",
      "completion_rate": "71%"
    }
  ]
}

POST https://cotlet.dev/api/v1/uscreen/list_community_channels

Returns every channel the signed-in admin can see, including private ones. Channel names are lowercase, with hyphens or underscores instead of spaces. The default general channel is always public.

Parameters

No parameters.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/uscreen/list_community_channels \
  -H "Authorization: Bearer $COTLET_API_KEY"
Python
result = client.call("uscreen", "list_community_channels")
Node.js
const result = await cotlet.call('uscreen', 'list_community_channels');
CLI
cotlet call uscreen list_community_channels

Example response

{
  "channels": [
    {
      "channel_id": "ch_general",
      "name": "general",
      "visibility": "public"
    },
    {
      "channel_id": "ch_announcements",
      "name": "announcements",
      "visibility": "public"
    }
  ]
}

Upload video

write

POST https://cotlet.dev/api/v1/uscreen/upload_video

Cotlet downloads the file and uploads it to Content > Videos, then sets the video to Unpublished. Uscreen then transcodes it, which takes 10 minutes to 72 hours depending on size, bit rate and format; the response says processing until it is ready. Files over 8 Mbps or outside MP4 with H.264 can cause playback problems or slow processing. It reaches no one, because the video stays unpublished until publish_video, so it runs without asking.

Parameters

Parameters: upload_video
NameTypeDescription
file_url required string Public or signed URL of an MP4 file, H.264, 16:9 recommended.
title required string Video title.
description string Shown on the video page.
category_ids string[] Categories it appears under. Without one it stays out of the catalog.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/uscreen/upload_video \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"file_url":"https://example.com","title":"title"}'
Python
result = client.call("uscreen", "upload_video", {"file_url":"https://example.com","title":"title"})
Node.js
const result = await cotlet.call('uscreen', 'upload_video', {"file_url":"https://example.com","title":"title"});
CLI
cotlet call uscreen upload_video --data '{"file_url":"https://example.com","title":"title"}'

Example response

{
  "video_id": "2390417",
  "title": "Mobility Basics 1: Ankles",
  "status": "unpublished",
  "processing": true,
  "category_ids": [
    "48211"
  ]
}

Update video

write

POST https://cotlet.dev/api/v1/uscreen/update_video

Changes only the fields you send and returns the previous values, so one more call restores them. Tags replace the whole tag list. A published video shows the new text to members at once. It runs without asking because it sends nothing to anyone and one call undoes it.

Parameters

Parameters: update_video
NameTypeDescription
video_id required string Video ID from list_videos.
fields required object Any of title, description, tags, category_ids.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/uscreen/update_video \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"video_id":"video_8c41d2","fields":"fields"}'
Python
result = client.call("uscreen", "update_video", {"video_id":"video_8c41d2","fields":"fields"})
Node.js
const result = await cotlet.call('uscreen', 'update_video', {"video_id":"video_8c41d2","fields":"fields"});
CLI
cotlet call uscreen update_video --data '{"video_id":"video_8c41d2","fields":"fields"}'

Example response

{
  "video_id": "2390417",
  "updated": [
    "title",
    "tags"
  ],
  "previous": {
    "title": "Ankles",
    "tags": [
      "mobility"
    ]
  }
}

POST https://cotlet.dev/api/v1/uscreen/publish_video

Sets Visibility to Published, or to Scheduled when release_at is given. Uscreen releases at the time in your store time zone (Settings > General), so Cotlet converts the offset you send. The video needs a category to appear in the catalog, and it stays out of the catalog until Uscreen finishes processing it. With send_email, the broadcast reaches every member with access. By default you confirm each call; you can switch that off for this tool.

Parameters

Parameters: publish_video
NameTypeDescription
video_id required string Video ID from list_videos.
release_at datetime ISO 8601 with offset. Empty: publish now.
send_email boolean Email all members with access when it goes live. Default: false.
show_coming_soon boolean Show it as Coming Soon in the catalog until release. Default: true.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/uscreen/publish_video \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"video_id":"2390417","release_at":"2026-11-02T07:00:00-05:00","send_email":true,"show_coming_soon":true}'
Python
result = client.call("uscreen", "publish_video", {"video_id":"2390417","release_at":"2026-11-02T07:00:00-05:00","send_email":True,"show_coming_soon":True})
Node.js
const result = await cotlet.call('uscreen', 'publish_video', {"video_id":"2390417","release_at":"2026-11-02T07:00:00-05:00","send_email":true,"show_coming_soon":true});
CLI
cotlet call uscreen publish_video --data '{"video_id":"2390417","release_at":"2026-11-02T07:00:00-05:00","send_email":true,"show_coming_soon":true}'

Example response

{
  "video_id": "2390417",
  "status": "scheduled",
  "release_at": "2026-11-02T07:00:00-05:00",
  "show_coming_soon": true,
  "send_email": true
}

POST https://cotlet.dev/api/v1/uscreen/create_collection

Creates the collection in Content > Collections and adds the videos to its playlist. It stays unpublished, so it reaches no one, and it runs without asking; publish it in Uscreen when it is ready. Uscreen advises keeping a collection under 50 videos. Pricing and access keep their defaults, so check them before you publish.

Parameters

Parameters: create_collection
NameTypeDescription
title required string Collection title.
description string Shown on the collection home page.
video_ids string[] Videos to add, in order. They must already be uploaded.
category_ids string[] Categories it appears under. Without one it stays out of the catalog.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/uscreen/create_collection \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title":"title"}'
Python
result = client.call("uscreen", "create_collection", {"title":"title"})
Node.js
const result = await cotlet.call('uscreen', 'create_collection', {"title":"title"});
CLI
cotlet call uscreen create_collection --data '{"title":"title"}'

Example response

{
  "collection_id": "118204",
  "title": "Mobility Basics",
  "status": "unpublished",
  "video_count": 2,
  "category_ids": [
    "48211"
  ]
}

POST https://cotlet.dev/api/v1/uscreen/set_collection_playlist

Replaces the whole playlist with the order you send and returns the previous one, so one more call restores it. Drip delays are days after a viewer first opens the collection, and Uscreen unlocks each video about every 2 hours after that delay. It is rejected if drip_days is set on a collection with free access. It runs without asking because members only see a change once the collection is published.

Parameters

Parameters: set_collection_playlist
NameTypeDescription
collection_id required string Collection ID from list_collections.
items required object[] Ordered list of { video_id, drip_days } or { divider: "Week 1" }. drip_days needs Gated access.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/uscreen/set_collection_playlist \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"collection_id":"118204","items":[{"divider":"Week 1"},{"video_id":"2390417","drip_days":0},{"divider":"Week 2"},{"video_id":"2390418","drip_days":7}]}'
Python
result = client.call("uscreen", "set_collection_playlist", {"collection_id":"118204","items":[{"divider":"Week 1"},{"video_id":"2390417","drip_days":0},{"divider":"Week 2"},{"video_id":"2390418","drip_days":7}]})
Node.js
const result = await cotlet.call('uscreen', 'set_collection_playlist', {"collection_id":"118204","items":[{"divider":"Week 1"},{"video_id":"2390417","drip_days":0},{"divider":"Week 2"},{"video_id":"2390418","drip_days":7}]});
CLI
cotlet call uscreen set_collection_playlist --data '{"collection_id":"118204","items":[{"divider":"Week 1"},{"video_id":"2390417","drip_days":0},{"divider":"Week 2"},{"video_id":"2390418","drip_days":7}]}'

Example response

{
  "collection_id": "118204",
  "title": "Mobility Basics",
  "status": "unpublished",
  "access": "gated",
  "playlist_items": 4,
  "videos": 2,
  "dividers": 2
}

Create live event

write Confirm

POST https://cotlet.dev/api/v1/uscreen/create_live_event

Creates the event in Content > Live Streaming. For rtmp the response includes the stream URL and the stream key once; paste both into OBS or similar software, and keep the key private. Live Studio and RTMP events count against your plan's live streaming hours. Purchase and access options stay at their defaults, so check them before the event. Published events are visible to members, and with preregistration on, the event shows a countdown. By default you confirm each call; you can switch that off for this tool.

Parameters

Parameters: create_live_event
NameTypeDescription
title required string Event title.
start_at required datetime ISO 8601 with offset.
method required enum live_studio, rtmp or zoom.
description string Shown on the event page.
category_ids string[] Categories it appears under. Without one it stays out of the catalog.
preregistration boolean Let viewers register before it starts. Default: false.
live_chat boolean Turn on live chat. Default: false.
publish boolean Set Visibility to Published. Default: false, saved unpublished.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/uscreen/create_live_event \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title":"Thursday Q&A","start_at":"2026-11-05T18:00:00-05:00","method":"rtmp","live_chat":true,"preregistration":true,"publish":true}'
Python
result = client.call("uscreen", "create_live_event", {"title":"Thursday Q&A","start_at":"2026-11-05T18:00:00-05:00","method":"rtmp","live_chat":True,"preregistration":True,"publish":True})
Node.js
const result = await cotlet.call('uscreen', 'create_live_event', {"title":"Thursday Q&A","start_at":"2026-11-05T18:00:00-05:00","method":"rtmp","live_chat":true,"preregistration":true,"publish":true});
CLI
cotlet call uscreen create_live_event --data '{"title":"Thursday Q&A","start_at":"2026-11-05T18:00:00-05:00","method":"rtmp","live_chat":true,"preregistration":true,"publish":true}'

Example response

{
  "event_id": "77310",
  "title": "Thursday Q&A",
  "start_at": "2026-11-05T18:00:00-05:00",
  "method": "rtmp",
  "status": "published",
  "preregistration": true,
  "live_chat": true,
  "stream_url": "rtmp://live.example.com/app",
  "stream_key": "sk_example_4f9a21"
}

Create coupon

write Confirm

POST https://cotlet.dev/api/v1/uscreen/create_coupon

Creates the coupon in Marketing > Coupons. The code and the discount cannot be changed afterwards; a wrong code means deleting the coupon and creating a new one. The expiry only stops new redemptions and leaves discounts already applied. It changes what members pay, so it asks first. By default you confirm each call; you can switch that off for this tool.

Parameters

Parameters: create_coupon
NameTypeDescription
code required string Letters and numbers only, no spaces.
discount_type required enum fixed or percentage.
value required number Percent off, or the fixed amount in the currency the coupon is denominated in.
applies_to required enum all_products, subscription, bundles or content.
offer_ids string[] Plans, bundles or content it applies to. Not used with all_products.
duration enum Subscription coupons only: once, forever or repeating. Default: once.
duration_periods integer Billing periods, when duration is repeating.
expires_on date Last day the code can be redeemed.
redemption_limit integer Most users who can redeem it.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/uscreen/create_coupon \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"code":"code","discount_type":"fixed","value":1,"applies_to":"all_products"}'
Python
result = client.call("uscreen", "create_coupon", {"code":"code","discount_type":"fixed","value":1,"applies_to":"all_products"})
Node.js
const result = await cotlet.call('uscreen', 'create_coupon', {"code":"code","discount_type":"fixed","value":1,"applies_to":"all_products"});
CLI
cotlet call uscreen create_coupon --data '{"code":"code","discount_type":"fixed","value":1,"applies_to":"all_products"}'

Example response

{
  "coupon_id": "55102",
  "code": "SPRING30",
  "discount": "30% off",
  "applies_to": "subscription",
  "duration": "once",
  "expires_on": "2027-04-30",
  "redemption_limit": 200,
  "status": "active"
}

Create community post

write Confirm

POST https://cotlet.dev/api/v1/uscreen/create_community_post

Posts from your admin account in the channel you name, now or scheduled. Members who can see the channel see it in the feed. Large images can take a while and may time out after about a minute. By default you confirm each call; you can switch that off for this tool.

Parameters

Parameters: create_community_post
NameTypeDescription
channel_id required string Channel ID from list_community_channels.
body required string Post text.
image_url string Attach one image by URL: jpeg, png, webp or gif.
publish_at datetime ISO 8601 with offset. Empty: post now.

Request

cURL
curl -X POST https://cotlet.dev/api/v1/uscreen/create_community_post \
  -H "Authorization: Bearer $COTLET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"channel_id":"channel_8c41d2","body":"body"}'
Python
result = client.call("uscreen", "create_community_post", {"channel_id":"channel_8c41d2","body":"body"})
Node.js
const result = await cotlet.call('uscreen', 'create_community_post', {"channel_id":"channel_8c41d2","body":"body"});
CLI
cotlet call uscreen create_community_post --data '{"channel_id":"channel_8c41d2","body":"body"}'

Example response

{
  "post_id": "p_90417",
  "channel_id": "ch_announcements",
  "status": "published"
}