create_content
Create content in SRG+ hub profiles with privacy settings, cover images, and structured widgets (text, links, media, profiles). Assign channels and categories to manage placement and publishing.
Instructions
Create a new content item in a hub profile.
workspace_id: target workspace ID — get available IDs from list_workspaces()
privacy: "Preview" (default), "Private", or "Public"
channels: list of channel IDs. NOTE: a channel placement needs a category,
so passing channels alone here often does NOT stick (saved channels:[]).
To reliably place content, call add_content_to_categories(content_id,
channel_id, category_ids=[...]) after create.
main_asset_id: ID of the primary playable asset
url: optional external URL to associate with the content
cover_image: http(s):// URL (or local path) of the cover; the URL PATH must
end in an image extension (.jpg/.png/...). Query strings are fine (signed
URLs work); an extension-less URL (e.g. placehold.co/600x400) returns 400.
categories: category assignment objects
context: the body — an ordered list of widget objects. Each widget MUST
carry a "$type" discriminator (literal key, with the dollar sign). Keys are
camelCase: the backend rejects snake_case for multi-word fields (assetId,
hubProfileIds, referenceIds) as a silent 400, so never send asset_id etc.
Shapes:
• Text (markdown body):
{"$type": "Text", "content": "<markdown, required>", "title": "<optional>"}
• LinkList:
{"$type": "LinkList", "title": "<optional>", "links": [
{"$type": "CustomLink", "title": "<required, unique in list>", "url": "https://...", "extension": "<optional image ext>"},
{"$type": "KnownLink", "title": "<required>", "url": "https://..."}
]}
(both link types use "title" + "url"; NOT "label"/"type". Max 20 links.)
• Media: {"$type": "Media", "assetId": "<existing PLAYABLE/video asset id>", "autoplay": false, "title": "<optional>"}
(assetId must be an EXISTING playable/video asset of the hub; an image or
a just-uploaded asset is NOT playable media and returns 404. No image-body
widget exists — use the cover, a CustomLink, or markdown in a Text widget.)
• HubProfile: {"$type": "HubProfile", "hubProfileIds": ["<hub id>", ...], "title": "<optional>"}
(hubProfileIds is a REQUIRED array, even for a single hub)
• ContentWidget: {"$type": "ContentWidget", "referenceType": "Content",
"referenceIds": [{"$type": "Content", "id": "<content id>"}], "title": "<optional>"}
(each reference is {"$type": "Content"|"Asset", "id": "..."}; referenceType matches the kind)
A single bad widget rejects the WHOLE call with 400 (the error now names the
rejected field). Widget title (when set) is 1-150 chars.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | ||
| name | Yes | ||
| context | No | ||
| details | No | ||
| privacy | No | Preview | |
| channels | No | ||
| categories | No | ||
| cover_image | No | ||
| workspace_id | Yes | ||
| main_asset_id | No | ||
| hub_profile_id | Yes |