This document explains how you can use the Switch Tube web service API to automate interaction with Switch Tube.
- Accessing the web service
- Authentication
- Errors
- Paths
- Profiles
- Channels
- Videos
- Trash
- Organizations
- Avatars
- Languages
- Categories
- Notes on video upload processing
- Browsing Switch Tube
- Changes
Accessing the web service
Just as on the regular Switch Tube website, most requests to the web service are performed on behalf of an authenticated profile. When we refer to you or your in the documentation below, we mean the currently authenticated profile.
All requests to the service are performed over HTTPS using an access token in the headers. For optimal throughput to the service we recommend using up to 3 parallel keep-alive connections to send the requests.
The web service is intended for server-to-server usage only. Do not attempt to use the web service from a web browser or from any other type of client-side application.
Please be gentle with the servers because hammering the web service will also decrease performance of the website. Keep an eye on netstat
or similar tools to make sure you don’t accidentally keep hundreds of connections open and starve the servers.
The base URL for all requests is https://tube.switch.ch
.
Payloads for both requests and responses will generally be encoded as JSON, unless specified differently.
Text
Switch Tube requires text to be encoded as UTF-8 in requests and will use the same in responses. The response headers will reflect this fact by specifying a charset
.
Time
Time in payloads is expressed according to the ISO 8601 W3C profile as defined in https://www.w3.org/TR/NOTE-datetime. We recommend using standard libraries to parse and convert this time to local time for your end-users.
Authentication
Getting an access token
You can manage access tokens for a profile by navigating to your profile page and then opening the access tokens tab. Follow instructions on that page to create a new access token.
In the examples below we use the fake value d4e650
for the access token. Real tokens will be longer but we use a short example for brevity.
Access tokens will automatically expire when they are not used at least once every 60 days. This reduces the chance of leaking an access token through an unused drive or server. We recommend creating separate access tokens for every machine that accesses the API if possible.
Make sure to keep the access token secret and to never store or use it in an untrusted environment.
Using the access token
To perform an authenticated request you must add the authentication token to an Authorization
header with each request. Prefix the token value with Token
to indicate you will be using a token.
GET /api/v1/profiles/me
Host: tube.switch.ch
Accept: application/json, */*
Authorization: Token d4e650
You can quickly test this with curl
.
curl -i -H "Authorization: Token d4e650" \
https://tube.switch.ch/api/v1/profiles/me.json
In the examples below we will leave out these details for brevity.
Errors
When a request was successful you can expect a 200 OK
response status or a 201 Created
response status when you attempted to create something. In general the response body will be either JSON or empty. When something went wrong you may receive one of the responses below. Error responses may also contain a JSON body with details about what went wrong.
- 400: Usually this means you have to do something before you are allowed to complete the request. For example: complete an upload.
- 401: You probably forgot to send an access token in the headers.
- 403: You are not allowed to access the request path. This also happens when the access token is invalid or expired. See the response body for details about what went wrong.
- 404: The resource you are attempting to access does not exist or you are not allowed to know it exists. An object with the supplied id may not exist, for example: organization with id 12. It’s also possible that you are using an incorrect request path, for example:
/api/v1/profiles/i
instead of/api/v1/profiles/me
). Finally you will also get a404
when Switch Tube does not want to expose the existence of an object, for example/api/v1/channels/12
when you only have access to/api/v1/channels/75
. - 422: Something went wrong with the contents of the payload and the response body will contain each property that has an issue.
- 429: You are sending too many requests. A
Retry-After
header might be included to this response indicating how long you are suggested to wait before making a new request. This value is expressed in seconds. - 500: Something went wrong on the server and we’ve been notified. The issue could be intermittent.
When something goes wrong you may receive an HTTP response in the 400-499 or 500-599 range. A 4xx response means you must not immediately retry the request and the request probably requires a change before retrying. A 5xx response means something went wrong in Switch Tube and the issue may be intermittent so you can attempt to retry the same request.
Validation errors
When receiving a 422 Unprocessable Entity
response you will receive a JSON encoded response body that explains which properties of the resource you were trying to create or update were wrong. For example, creating a channel requires a name:
{"name":[{"error":"blank"}]}
In some cases this may also include the original value or other details:
{"name":[{"error":"too_short","value":"Hi"}]}
Read the linked JSON schemas to know in advance which properties are required, need a specific value, or only work with strict formatting.
Paths
Channels, videos, and some other objects contain a path property. This is a path relative to the website, for example:
/channels/O8WElDsKqr
/videos/RQzWFDvShW
/image/representations/eyJfcmFpbHMiO
/collaborators/12
In order to create a valid URL, you prepend base URL of the website:
https://tube.switch.ch/channels/O8WElDsKqr
In case of videos you can add a timestamp to point to a specific time code:
https://tube.switch.ch/videos/RQzWFDvShW#12
https://tube.switch.ch/videos/RQzWFDvShW#1:16
Profiles
A profile contains the personal information supplied by edu-ID or AAI when the user signs in. It also holds some settings like their preferred user interface locale.
Details about the authenticated profile
You can fetch the profile associated the access token used in the request:
GET /api/v1/profiles/me
It will return the details for your profile:
{
"organization_id":86234,
"first_name":"Sofia",
"last_name":"Andretta",
"locale":"de",
"avatar":{
"small_path":"/avatars/GJb6vxcubsjtVozsVrrtnQDK8XaxPqKT/small",
"created_at":"2023-06-12T22:00:00.000+02:00"
}
}
- organization_id integer: Every profile belongs to an organization (eg. a university) this id references the organization. (read-only)
- first_name string: First name of the person associated with this profile. (read-only)
- last_name string: Last name of the person associated with this profile. (read-only)
- locale string:
Locale chosen by the user for their user interface.
Accepted values:
en
de
. - avatar object: See the avatar schema for more details.
Profiles contain information received from SWITCHaai so a person’s name is split into first and last name. We assume that you can concatenate them to get their full name.
See the documentation for avatars below for a description of the avatar specific properties.
Details about other profiles
You can fetch details about any profile by their numeric id. You will find references to profiles in a lot of objects, for example: videos and channels.
GET /api/v1/profiles/97
The response will be the same as for your own profile. You can also expect a 404 Not Found
when the profile id does not exist.
Channels
A channel groups videos with a similar theme or purpose.
Create a new channel
When you create a new channel it will be automatically associated with you and your organization. The only other required property for creating a channel is its name.
POST /api/v1/channels
{"name":"Einführung in die Analysis"}
There are a lot of other properties that allow you to configure the presentation, permissions, and behavior of a channel.
name string: Display name of the channel.
description string: Description of a channel, the text may contain a limited set of HTML tags: p, h3, ul, ol, li, pre, blockquote, a, em, strong.
category string: Category for the channel. Mostly used by the podcast functionality to include a category in the feed. See the categories endpoint for a list of valid values.
language string: Primary language of the channel in ISO 639 notation. Mostly used by the podcast functionality to include a language in the feed. See the languages endpoint for a list of valid values.
viewable_by string: Gives permission to see the channel and its videos to a group of users. See the create channel form on the website to understand how permissions work. After choosing the collaborator setting you can use the collaborators endpoint to manage collaborator permissions for profiles. Accepted values:
all
all-hidden
authenticated
organization
collaborators
.open_channel boolean: Open Channels contain teaching, learning, and research videos intended to be freely used by everyone. Requires
viewable_by
to beall
.commentable boolean: Authenticated users will be able to leave comments on each video page in this channel.
downloadable boolean: Each video page in this channel will include a “Downloadable version” link.
archive_original_video_files boolean: Deprecated. The uploaded video file is now always archived.
external_playback boolean: Each “Edit video” page in this channel will include a URL to load the video in an external player. Requires
viewable_by
to beall
orall-hidden
.hide_owner boolean: On the channel overview, the name of the channel owner will not be shown as a link to their profile page.
podcast boolean: All uploaded files will be processed as a podcast and viewers will be able to subscribe to a feed. Requires
viewable_by
to beall
orall-hidden
.explicit boolean: Can be set when the channel contains media only suited for mature audiences. Mostly used by the podcast functionality to include an explicit tag in the feed.
If the request is successful you will receive a 201 Created
response with the id and public request path of the created channel.
{"id":42","path":"/channels/dci0acJEYm"}
You can expect a 403 Forbidden
response when you are not a video producer.
Video, audio, artwork, and collaborators can be added through their respective endpoints explained below.
List channels
There are thousands of channels so listing all channels would not be very helpful in most cases. To limit the number of channels you filter by specifying your role in the channel. The default role is owner.
- owner: Lists all channels you own.
- contributor: Lists all the channels you can contribute to (eg. edit and upload media)
The default role is owner
so you can perform a request to get all channels you may view like this:
GET /api/v1/channels
Or you can specify either contributor
to filter those records:
GET /api/v1/channels?role=contributor
If the request is successful you will receive a 200 OK
response with a list of channel objects.
[
{"id":42,"name":"Einführung in die Analysis", …},
{"id":43,"name":"Schwarze Wissenschaft", …}
]
You may get an empty list when there are no channels:
[]
Someone can contribute to a channel outside of their organization so the organization_id
of a channel doesn’t always have to be the same as the organization_id
of the authenticated profile.
Fetch channel details
You can find all details for a specific channel:
GET /api/v1/channels/42
If the request is successful you will receive a 200 OK
response with a channel object.
{"id":42,"name":"Einführung in die Analysis", …}
You should expect a 404 Not Found
response when the channel does not exist or when you don’t have access to it.
Update a channel
To update channel details you can send the same properties as when creating a channel:
PATCH /api/v1/channels/42
{"name":"Einführung in die Analysis", …}
If the request is successful you will receive a 200 OK
response with an empty body.
You should expect a 404 Not Found
response when the channel does not exist or when you are not allowed to update it.
Delete a channel
You can delete a channel and all its associated content:
DELETE /api/v1/channels/42
If the request is successful you will receive a 200 OK
response with an empty body. There is no way to recover a channel once it was deleted, so be very careful.
You should expect a 404 Not Found
response when the channel does not exist or when you are not allowed to delete it.
Add media to a channel
Creating a new video starts by uploading a video or audio file to Switch Tube. Switch Tube uses the tus protocol for resumable uploads and it supports all protocol extensions.
The protocol is based on HTTP and allows you to either POST the entire file in one go or use PATCH requests to upload a file in segments.
Note that the path for file uploads does not start with /api/v1
like with other API requests.
Upload at once
You can choose to upload an entire file in one HTTP request. This is only recommended when you are uploading smaller files (eg. less than 50 megabytes) or when have a really stable connection to Switch Tube.
POST /files
Content-Length: 7634
Upload-Length: 7634
Tus-Resumable: 1.0.0
Authorization: Token d4e650
«7634 bytes of data»
Your HTTP library will likely set the Content-Length
header correctly when you set the body for the request. You will have to make sure to send the correct values for the Upload-Length
, Tus-Resumable
, and Authorization
headers.
Switch Tube will respond with a 201 Created
response and a Location
header with a URL that represents the newly created upload.
Location: https://tube.switch.ch/files/43ae77
You may receive a 401 Unauthorized
, 403 Forbidden
, or 500 Internal Server Error
. In case of a 500 Internal Server Error
you can retry the request, in all other cases you have to change something about the request first. Keep in mind that the connection to the server may close during the request, this is much more likely to happen for a long running request like an upload.
The last segment of the upload url is the upload identifier, in our example that’s 43ae77
. Real upload ids will be a lot longer. You will need this upload id to create a video record (see below).
Upload a file in parts
When uploading a file in parts you start by creating the upload. The Content-Length
header will have the value 0
because there is no request body. The Upload-Length
header should have the length of the entire file in bytes.
POST /files
Content-Length: 0
Upload-Length: 7634
Tus-Resumable: 1.0.0
Authorization: Token d4e650
Your HTTP library will likely set the Content-Length
header correctly. You will have to make sure to send the correct values for the Upload-Length
, Tus-Resumable
, and Authorization
headers.
The server will respond with a 201 Created
and a Location
header with a URL that represents the newly created upload.
Location: https://tube.switch.ch/files/43ae77
You may receive a 401 Unauthorized
, 403 Forbidden
, or 500 Internal Server Error
. In case of a 500 Internal Server Error
you can retry the request, in all other cases you have to change something about the request first.
To complete the file you send a series of PATCH
requests with segments of the file. You get to decide how big each file segment will be and theoretically they can all be different sizes.
A good starting point for a segment size is how much the current connection can upload in a few seconds. Switch Tube prefers segments of at least a few megabytes.
We recommend 5 megabytes if you don’t know the speed of the connection.
Using the Upload-Offset
and Content-Length
you can now send a PATCH
request with a byte range of the file you are uploading.
It’s important to use exactly the same Content-Type
header as shown in the example or the upload will fail. A request will also fail when the Tus-Resumable
or Authorization
headers are missing.
In the first request the offset is 0 and the content length is 5 megabytes.
PATCH /files/43ae77
Content-Type: application/offset+octet-stream
Content-Length: 5242880
Upload-Offset: 0
Tus-Resumable: 1.0.0
Authorization: Token d4e650
«5242880 bytes of data»
You can expect the same responses as for the initial create request. When you get an error or when the connection drops during the upload you will have to retry the segment before continuing.
In the second request the offset is 5 megabytes and the content length is again 5 megabytes.
PATCH /files/43ae77
Content-Type: application/offset+octet-stream
Content-Length: 5242880
Upload-Offset: 5242880
Tus-Resumable: 1.0.0
Authorization: Token d4e650
«5242880 bytes of data»
Each segment has to be immediately adjacent to the previous one, so when you send an invalid offset you can expect a 409 Conflict
response. In that case you can always perform a HEAD
request to query the correct offset from the server.
HEAD /files/43ae77
The server will respond with an empty body and the current offset in the headers:
Upload-Offset: 5242880
Keep going until the file is completely uploaded. The last segment will likely be smaller that 5 megabytes, so make sure you compute and send the correct content length.
If you want to upload segments in parallel you will have to use the concatenation extension in the tus protocol documentation.
The last segment of the upload url is the upload identifier, in our example that’s 43ae77
. Real upload ids will be a lot longer. You will need this upload id to create a video record (see below).
After completing the upload
In order to create a video you will need a channel identifier and the upload identifier you stored while uploading the file.
POST /api/v1/videos
{
"channel_id":42,
"upload_id":"43ae77",
}
When creating the video you can optionally send all additional properties specified in the video schema.
POST /api/v1/videos
{
"channel_id":42,
"upload_id":"43ae77",
"title":"Stochastische Variabelen",
"published":true
}
title string: The title of the video.
abstract string: A short description of the video, the text may contain a limited set of HTML tags: p, h3, ul, ol, li, pre, blockquote, a, em, strong.
published boolean: Used to set the published state for the video to either ‘published’ (true) or ‘draft’ (false). Note that a video can’t be seen through the website when its published state is ‘draft’.
episode string: Allows videos to be sorted by their episode label instead of their title when they form a series.
license_code string: Can be used to set a specific license for use of the video. See https://creativecommons.org/licenses/ for more information about what the licenses mean.
You will receive a 201 Created
response with the id of the created video and their public path:
{"id":83,"path":"/videos/6RfMZZzQ1R"}
After creating the video the upload will be placed in the media processing queue to prepare it for use on the web.
A video will be published when it has a valid title, the upload was processed, and the published
property is set. The video will automatically publish after processing when you set title
and published
during creation.
Videos have a number of properties like abstract and episode which allow you to change how the video is presented to the viewer. Note that all access permissions are always configured on the channel. You can set video properties when creating the video or later by updating the video. For a full explanation of the video properties see the schema or the update section below.
The process for publishing an audio recording is the same, just replace the video by an audio file.
Media processing progress
At any time you can fetch information about the current processing progress for a video based on their id:
GET /api/v1/videos/83/progress
When successful it will return a 200 OK
with progress details:
{
"status":"processing",
"started_at":"2022-03-04T16:23:29+01:00",
"updated_at":"2022-03-04T16:23:29+01:00"
}
You should expect a 404 Not Found
when the video does not exist or when you are not allowed to access it.
These are all possible processing statuses:
pending
: Waiting to get selected for processing.queued
: Entered the processing queue.processing
: Currently processing.completed
: Finished processing.failed
: Something went wrong during processing.stopped
: Processing stopped because the video was deleted. You should never encounter this status.
The statuses failed
, stopped
and completed
can be considered as final; the status should no longer change.
Collaborators
The collaborator feature allows you to give a small group of people access to a channel. For example when you are working on a research project with sensitive video that may not be viewed by the entire organization.
List collaborators for a channel
The collaborator object is used for both active collaborators and collaborator invitations. An active collaborator will have their profile_id
set. A collaborator invitation will have the email
property set, but not the profile_id
.
GET /api/v1/channels/42/collaborators
[
{"id":92,"profile_id":"97,"permissions":"view-only"},
{"id":93,"email":"artur@exampel.com","permissions":"upload"},
…
]
- permissions string:
Holds a single string that describes the access permissions of the collaborator to the channel. See the permissions form for a channel on the website for a longer description of the permissions.
Accepted values:
view-only
upload
manage-channel
. profile_id integer: References the profile that receives the access permissions to the channel. The collaborator object is effectively an invitation when the profile_id is null and the email property is set.
email string: Can be set instead of the profile_id to send a collaborator invitation to any e-mail address. The recipient will be able to click a link to accept the invitation. If the e-mail address matches their Switch Tube profile they will also be able to accept the invitation on their profile page.
Create an active collaborator for a channel
When you know the profile id of someone you can use it to add them as a collaborator.
POST /api/v1/channels/42/collaborators
{"profile_id":100,"permissions":"upload"}
If the request is successful you will receive a 201 Created
response with the id the created collaborator.
{"id":77"}
You can expect a 404 Not Found
response when you are not allowed to add collaborators to the channel.
It’s also possible to get a 422 Unprocessable Entity
when you leave out the profile_id
or permissions
properties.
The new collaborator will receive an e-mail to explain that they are added to the channel.
Update active collaborator’s permissions on a channel
When you know the profile id of a someone and you want to ensure that they have a certain permission level you can use the same request as when you add a collaborator.
POST /api/v1/channels/42/collaborators
{"profile_id":100,"permissions":"manage-channel"}
If the request is successful you will receive a 200 OK
response with the id the updated collaborator.
{"id":77"}
The difference between creating and updating a permission is the response status code.
Create collaborator invitation for a channel
When you don’t know the profile id of someone you want to add as a collaborator you can send them an invitation using their e-mail address.
The e-mail address does not have to be the same as the e-mail address of their profile on Switch Tube.
POST /api/v1/channels/42/collaborators
{"email":"jessy@example.com","permissions":"manage-channel"}
You can expect a 404 Not Found
response when you are not allowed to add collaborators to the channel.
It’s also possible to get a 422 Unprocessable Entity
when you leave out the email
or permissions
properties.
The new collaborator will receive an e-mail to ask them to accept the invitation. After accepting the invitation they can access the channel with the permissions you configured.
Update collaborator invitation’s permissions for a channel
If you want to change the permission level for a collaborator invitation you can perform the same request as when creating the invitation.
POST /api/v1/channels/42/collaborators
{"email":"jessy@example.com","permissions":"upload"}
If the request is successful you will receive a 200 OK
response with the id the updated collaborator.
{"id":77"}
After updating we don’t send the invitation e-mail. If you want to resend an invitation you have to delete the collaborator invitation and re-create it.
Delete a collaborator from a channel
You can delete a collaborator from a channel by its id. Note that this is the collaborator id and not the profile id.
DELETE /api/v1/collaborators/77
If the request is successful you will receive a 200 OK
response with an empty body.
You should expect a 404 Not Found
response when the collaborator does not exist or when you are not allowed to delete it.
Artwork
Artwork is a square image that is mostly used in the podcast feed but may also be used on the website in the future to identify a channel. Artwork is always public because it has to be served with a public podcast feed.
Add artwork to a channel
Uploading artwork works similar to adding media to a channel. You start by uploading a file and parsing the upload id from the Location
header in the response. Then you use the upload id and a channel id to add the artwork to the channel:
POST /api/v1/artworks
{
"channel_id":42,
"upload_id":"43ae77"
}
You will receive a 201 Created
response with the id of the created artwork and their path:
{"id":75,"path":"/channels/42/artwork"}
You can expect a 400 Bad Request
with a warning label incomplete-upload
when you attempt to create an artwork before completing the upload.
Keep in mind that artwork always replaces the current artwork immediately and is publicly accessible.
Videos
A video represents video or audio on the website. We use video as an umbrella term because Switch Tube is primarily a video platform.
List videos in a channel
You can fetch a list of editable videos from channels you may upload videos to:
GET /api/v1/channels/42/videos
If the request is successful you will receive a 200 OK
response with a list of videos objects.
[
{"id":84,"title":"Verteilugen", …},
{"id":83,"title":"Stochastische Variablen", …}
]
If you are not allowed to upload videos to a channel you will receive a 404 Not Found
response.
Fetch video details
You can find all details for a specific video:
GET /api/v1/videos/84
If the request is successful you will receive a 200 OK
response with a video object.
{"id":84,"title":"Verteilugen", …}
You should expect a 404 Not Found
response when the channel does not exist or when you don’t have access to the channel or the video.
Update a video
To update video details you can send the same properties as when creating a video:
PATCH /api/v1/videos/83
{"title":"Stochastische Variablen", …}
title string: The title of the video.
abstract string: A short description of the video, the text may contain a limited set of HTML tags: p, h3, ul, ol, li, pre, blockquote, a, em, strong.
published boolean: Used to set the published state for the video to either ‘published’ (true) or ‘draft’ (false). Note that a video can’t be seen through the website when its published state is ‘draft’.
episode string: Allows videos to be sorted by their episode label instead of their title when they form a series.
license_code string: Can be used to set a specific license for use of the video. See https://creativecommons.org/licenses/ for more information about what the licenses mean.
If the request is successful you will receive a 200 OK
response with an empty body.
You should expect a 404 Not Found
response when the video does not exist or when you are not allowed to update it.
Delete a video
You can delete a video and all its associated content:
DELETE /api/v1/videos/83
If the request is successful you will receive a 200 OK
response with an empty body. There is no way to recover a video once it was deleted, so be very careful.
You should expect a 404 Not Found
response when the video does not exist or when you are not allowed to delete it.
Download original files
After a video was processed you may want to download the original. Note that every video may have multiple original files associated with it because videos can’t be replaced.
GET /api/v1/videos/83/files
If the request is successful you will receive a 200 OK
response with a file list object.
[
{"url":"https://…", "filename":"IMG_0297.MOV"},
{"url":"https://…", "filename":"IMG_0430.MOV"}
]
The files should be ordered newest first, so generally you will want to download the first one. Note that the filename is optional and may be missing.
The URL in the payload is a presigned URL that will give temporary access to the original file on the storage servers.
You should expect a 404 Not Found
response when the video does not exist or when you don’t have access to the video.
Full file list schema Full file schema
Posters
A poster is an image that is either an extracted frame from the original video or a file uploaded by a video producer. A video can have multiple posters associated with it.
One of these posters can be selected. Switch Tube will choose a current poster when no poster was selected. The current poster is shown on channel and video pages to represent the video.
List posters for a video
You can fetch all posters associated with a video.
GET /api/v1/video/42/posters
[
{"id":65,"source":"extracted","selected":false,…},
{"id":66,"source":"uploaded","selected":true,…},
…
]
You can expect a 200 OK
with a list of posters. When there are not posters yet, you may get an empty list.
- id integer: A unique numeric reference to the poster. (read-only)
- source string:
A poster can either be an extracted frame from the video or an image uploaded by a video producer.
Accepted values:
extracted
uploaded
. (read-only) - selected boolean: A poster is selected when the video producer explicitly selected it. Switch Tube will choose one of the posters as the current poster when none are selected. (read-only)
- path string: Absolute path where anyone can access the poster for a limited time. Depending on the permissions on the channel this path will stay valid for somewhere between an hour and 7 days. (read-only)
- media_type string:
A media type to describe the expected content of the file.
Accepted values:
image/jpeg
. (read-only) - expires_at string: Date and time at which the path is no longer usable including time zone information formatted according to the ISO 8601 W3C profile as defined in https://www.w3.org/TR/NOTE-datetime. (read-only)
Fetch current poster details
You can fetch details about the current poster for a video.
GET /api/v1/video/42/poster
{"id":65,"source":"extracted","selected":false,…}
If the request is successful you will get a 200 OK
response with details about the poster.
You should expect a 404 Not Found
response when the video does not exist or when you are not allowed to delete it.
See the section about paths on how to format a URL to the poster based on the path returned by this resource. Keep in mind that the path will only be valid for a limited time.
Add poster to a video
Uploading a poster works similar to adding media to a channel. You start by uploading a file and parsing their upload id from the Location
header in the response.
Then you use the upload id and a video id to add the poster frame to the channel:
POST /api/v1/posters
{
"video_id":83,
"upload_id":"43ae77"
}
When the request is successful you will receive a 201 Created
response with the id of the created poster:
{"id":67}
You can expect a 400 Bad Request
with a warning label incomplete-upload
when you attempt to create a poster before completing the upload.
Change the selected poster for a video
You can select an existing poster as the new selected poster by updating the video:
PATCH /api/v1/videos/83
{"poster_id":67}
For more details about updating a video resource, see above.
Remove poster from a video
You can delete an uploaded poster:
DELETE /api/v1/posters/67
If the request is successful you will receive a 200 OK
response with an empty body. There is no way to recover a poster frame once it was deleted, so be very careful.
Documents
A video page can show documents related to the video, for example: slides, exercises, or images.
List documents uploaded for a video
You can get a list of all uploaded documents for a video:
GET /api/v1/videos/42/documents
[
{"id":91,"label":"ok.pptx","size":263222,"url":"https://…"},
…
]
You can expect a 200 OK
with details about the poster.
- id integer: A unique numeric reference to the document. (read-only)
- label string: Contains either the original filename of the uploaded file or a label entered by the uploader. (read-only)
- size integer: Size of the file in bytes. Only use this value for presentation purposes because it can vary slightly from the actual file size. (read-only)
- url string: A presigned URL to the file on object storage. The URL expires after a while so it’s meant for immediate use. Do not cache this value. (read-only)
You should expect a 404 Not Found
response when the video does not exist or when you are not allowed to access it.
Add document to a video
Uploading a document works similar to adding media to a channel. You start by uploading a file.
It is mandatory to set the filename
metadata when creating the upload. A file upload without the filename
metadata can not be used to create a document.
POST /files
Tus-Resumable: 1.0.0
Upload-Metadata: filename c2xpZGVzLnBwdHg=
Remember that all metadata values have to Base64 encoded.
After the upload you parse the upload id from the Location
header as described above. Then you use the upload id and a video id to add the document to the video:
POST /api/v1/documents
{
"video_id":83,
"upload_id":"43ae77"
}
Just like with other resources you will receive a 201 Created
response with the id of the created document:
{"id":75}
You can expect a 422 Unprocessable Entity
with an error on the file
attribute when the filename is not set on the upload or when the upload was not completed first.
Remove document from a video
You can delete a document:
DELETE /api/v1/documents/82
If the request is successful you will receive a 200 OK
response with an empty body. There is no way to recover a document once it was deleted, so be very careful.
Trash
When you delete a channel or video they are not immediately removed from the system. Switch Tube keeps them invisible for a month and then removes them completely. During this time you can fetch them as trash entries.
GET /api/v1/trash
[
{
"id":12,
"title":"Space is Awesome",
"type":"channel",
"restorations_path":"/api/v1/channels/1/restorations",
"marked_for_deletion_at":"2023-03-21T13:05:07.861+01:00",
"expires_at":"2023-04-21T13:05:07.861+02:00"
},
…
]
You can expect a 200 OK
with details about the trash entries or and empty list when there are no entries.
Every trash entry has common properties which may differ from the regular channel and video objects.
- id integer: A unique numeric reference to the channel or video. (read-only)
- title string: Either the name of the channel or the title of the video. (read-only)
- type string: Either the value channel or video depending on the type of object (read-only)
- restorations_path string: Request path to use to restore the channel or video back to its state before deletion. (read-only)
- marked_for_deletion_at string: Time when the record was originally marked for deletion. (read-only)
- expires_at string: Time when the record will be permanently removed. You will not be able to restore the channel or video after this time. (read-only)
Restoration
You can restore trash entries to their state before they were deleted. Meaning, for example, that a draft video will be restored as a draft video. You can get the restoration path from the trash entry.
POST /api/v1/channels/1/restorations
You can expect a 200 OK
when the item was successfully restored. You may get a 404 Not Found
when you are not allowed to edit the referenced video, but this should not happen for trash entries returned from the trash endpoint unless they were restored by another process in the meantime.
Note that you cannot restore a single videos from a deleted channel because they would not have a channel to restore to. Instead you can restore the channel, copy the video to another channel, and then delete the channel again.
Organizations
Profiles belong to organizations based on the home organization and entitlements properties on their AAI account. Organizations are usually a higher education institute in the context of Switch Tube.
Fetch organization details
You can fetch details about an organization:
GET /api/v1/organizations/4
{
"name":"Université de Lausanne",
"url":"https://unil.ch"
}
You can expect a 200 OK
with details about the organization or a 404 Not Found
when there is no organization with the supplied id.
- name string: Display name of the organiation. (read-only)
- url string: URL to the homepage of the organization. (read-only)
Avatars
A profile may have an avatar, you request them as part of the profile resource as descibed above.
- small_path string: Absolute path where anyone can access the avatar image. (read-only)
- created_at string: Date and time at which the avatar was saved including time zone information formatted according to the ISO 8601 W3C profile as defined in https://www.w3.org/TR/NOTE-datetime. (read-only)
Upload a new avatar
Uploading an avatar works similar to adding media to a channel. You start by uploading a file.
POST /files
Tus-Resumable: 1.0.0
After the upload you parse the upload id from the Location
header as described above. Then you use the upload id to create a new avatar for the authenticated profile:
POST /api/v1/avatars
{
"upload_id":"43ae77"
}
Just like with other resources you will receive a 201 Created
response but with a blank body. You can get details about the current avatar through the profile endpoint.
You can expect a 400 Bad Request
with an error description when the upload wasn’t completed first.
Remove previously uploaded avatar
You can delete the current avatar:
DELETE /api/v1/avatars
If the request is successful you will receive a 200 OK
response with an empty body. There is no way to recover an avatar once it was deleted, so be very careful.
Languages
Languages are expressed as an IETF BCP 47 language tag. Any two or three letter tag as well as subtags from the current IANA Language Subtag Registry are supported. You can fetch the languages object where every property is the tag for a known language and the value is the language name in English.
GET /api/v1/languages
{
"aa":"Afar",
"ab":"Abkhazian",
"ae":"Avestan",
…
"fr-CH":"French (Switzerland)",
…
"de-CH":"German (Switzerland)",
…
"it-CH":"Italian (Switzerland)",
…
]
The languages resource does not have a schema because it’s much easier to describe as a nested object where the properties are also values.
Categories
Categories are separated in a main category and a sub category. When specifying a category you must choose a main category and optionally you may choose a sub category. When supplying the category you join the main category and subcategory with the /
separator. Some examples of valid categories are:
Arts
Arts/Books
Music/Music History
You can fetch all possible values through the API. Currently we only have a list of categories in English, but we will supply translated versions in the future.
GET /api/v1/categories
{
"Arts":["Books","Design",…],
"Business":["Careers","Entrepreneurship",…]
}
If you want to make your implementation future-proof and you know you want a German version in the future you can add the language
parameter to the request.
GET /api/v1/categories?language=de
The categories resource does not have a schema because it’s much easier to describe as a nested object where the properties are also values.
Notes on video upload processing
The video processing servers are a limited resource. Switch Tube attempts to share the capacity fairly across all its users. When you use the API to import large archives of videos you may run into the profile’s processing quota. The processing quota is dependent on how busy Switch Tube is. If you end up with a large queue of unprocessed video it will likely be finished during the night. Please contact Switch if you plan on importing large archives of video so our engineers will not be surprised.
Browsing Switch Tube
This section describes how you can browse Switch Tube using the API. Most of the objects returned by the endpoints in this section look a lot like the ones described earlier but are more focussed on presentation.
Pagination
An endpoint that returns multiple items may return a subset of the entire collection of items for performance reasons. You can fetch the next ‘page’ of items using the URL in the Link
header.
Link: <https://tube.switch.ch/api/v1/browse/channels?page=3>; rel="next"
You have reached the last page when there is no Link
header or when the Link
header does not include an item with rel="next"
.
If you attempt to construct the next page by manipulating the counter in the URL you may get a 404 Not Found
responses.
List browsable channels
You can get a list of all browsable channels. A channel is browsable when it contains at least one video you are allowed to watch.
GET /api/v1/browse/channels
[
{"id":"2bQTrXl8F8","name":"Metabolic Processes",…},
{"id":"2Brw2M4kvz","name":"Botany",…},
…
]
You may get an empty list when you’re not allowed to access any channels:
[]
This endpoint uses pagination as explained earlier.
Full browsable channel list schema
Fetch browsable channel details
You can fetch details about a specific channel.
GET /api/v1/browse/channels/2bQTrXl8F8
{"id":ZR60vp2eAK","title":"ATP to ADP Conversion",…}
id string: An alphanumeric reference to the channel.
organization_id integer: Every channel belongs to an organization (eg. a university) this id references the organization.
name string: Display name of the channel.
description string: Description of a channel, the text may contain a limited set of HTML tags: p, h3, ul, ol, li, pre, blockquote, a, em, strong.
category string: Category for the channel. Mostly used by the podcast functionality to include a category in the feed. See the categories endpoint for a list of valid values.
language string: Primary language of the channel in ISO 639 notation. Mostly used by the podcast functionality to include a language in the feed. See the languages endpoint for a list of valid values.
List browsable videos
You can get a list of all browsable videos in a channel.
GET /api/v1/browse/channels/2bQTrXl8F8/videos
This endpoint uses pagination as explained earlier.
Full browsable video list schema
Fetch browsable video details
You can fetch details about a specific video.
GET /api/v1/browse/videos/5qLzqcJVfv
id string: An alphanumeric reference to the channel.
profile_id integer: The profile that published the video. This property will be missing or null when the video publisher does not want to share this information.
channel_id integer: Every video is posted to a channel. This id references that channel.
title string: The title of the video.
abstract string: A short description of the video, the text may contain a limited set of HTML tags: p, h3, ul, ol, li, pre, blockquote, a, em, strong.
duration_in_milliseconds integer: Duration of the video expressed in milliseconds. The value can be slightly different from the duration in the actual media files. (read-only)
published_at string: Date and time at which the video was last published including time zone information formatted according to the ISO 8601 W3C profile as defined in https://www.w3.org/TR/NOTE-datetime. (read-only)
episode string: Allows videos to be sorted by their episode label instead of their title when they form a series.
license_code string: Can be used to set a specific license for use of the video. See https://creativecommons.org/licenses/ for more information about what the licenses mean.
Fetch video variants, audio variants, waveform, poster, and artwork
Every video may have video variants, a poster image, audio variants, or a waveform image. Which of these are present depends on the source and choices made by the video producer. You can all fetch them in a similar way.
GET /api/v1/browse/videos/5qLzqcJVfv/video_variants
GET /api/v1/browse/videos/5qLzqcJVfv/poster
GET /api/v1/browse/videos/5qLzqcJVfv/audio_variants
GET /api/v1/browse/videos/5qLzqcJVfv/waveform
Video variants are ordered on their quality level with the highest quality variant first.
A channel may have artwork.
GET /api/v1/browse/channels/2bQTrXl8F8/artwork
All these endpoints return either a list or a single asset object.
path string: Absolute path where anyone can access the asset for a limited time. The path will stay valid somewhere between 1 hour and 7 days depending on the type of asset, permissions, and the authenticated user.
name string: A label to distinguish between video and audio variants.
media_type string: A media type to describe the expected content of the file. Accepted values:
video/mp4
audio/mp3
image/jpeg
image/png
.expires_at string: Date and time at which the asset path is no longer usable including time zone information formatted according to the ISO 8601 W3C profile as defined in https://www.w3.org/TR/NOTE-datetime.
Changes
- November 2023: The
archive_original_video_files
channel property has been deprecated. The uploaded video file is now always archived and will continue to be available for download to the channel admins. The property is still included with the channel details, but its value will always betrue
, no matter what it was set to when the channel was created or updated.