OnTheAir Video REST API

OnTheAir Video's REST API allows you to retrieve OTAV's status, change playlists, do controls of the playback and playing with the DGO. Also note that this REST API is not final, it's a first draft and there could be changes in the future when it is finalised.

This API is meant to be RESTful, then, using different verbs on requests leads to different behaviour on request processing.
In general manner, consider theses verbs to have the described behaviour:

When you modify or retrieving data, be sure to handle properly the return code that is returned by the API as it indicates if the operation was successfull or not.
For POST & PUT requests you MUST supply the 'Content-Type' header with value 'application/json'.
Here is a short list common codes returned by the API:

Code Meaning Description
200 OK The request was succesfully processed.
201 Created A new resource has been created on server side.
202 Accepted The resquest was accepted but was not processed.
400 Bad Request The resquest was not well formed.
401 Unauthorized The request needs an access token to proceed. See Authorization
403 Forbidden The token provided doesn't have sufficient privileges/permissions. See Authorization
404Not found The resquest couldn't be processed. The path is not recognized.
422 Unprocessable entity The resquest is well formed but is sementically incorrect

To know if your request succeded; command, update, create and delete requests are followed with this kind of response:

Command response object:

{
	"success" : boolean,
	"error" : string OPTIONAL
}

"success": Indicates if the request was accepted and processed or not by OnTheAir Video.
"error": In case of success false, indicates what was wrong when processing the request.


NOTE:
OPTIONAL marked parameters indicates that these parameters can be or not be present in the response object, this is due to internal logics.
However for requests that require a body, like PUT or POST, it means that it can be passed but they are not mandatory.



Authorization

Since playlists can play sensitive content at a time, an authorization mechanism will be required if you decide to enable it in OnTheAir Video's preferences. (General -> HTTP Server -> Require Authentication).

If this feature is enabled, it implies that you have to login with one of the registred user defined in OnTheAir Video and use the token received. In case not, you can ignore this section.

Each user has an access level, it defines how much control you have.
Theses are described as follows:

# Title Description
1 Read Only You'll only be able to retrieve informations but not modifying it.
2 Modify Playlists You'll only be able to modify playlists.
3 Modify And Control Playlists You'll be able to modify playlist, control the playback and DGO.
4 Full Access You'll be granted to execute all commands (admin privileges).

In order to make request you must first login with the following request:

PUT http://localhost:8081/authorize
{
	"username": string, REQUIRED
	"password": string REQUIRED
}

Response:
{
	"token": string, OPTIONAL
	"error": string, OPTIONAL
	"level": number
}

The token received MUST be added in the query parameter of each request you make to OTAV.
The level property is indicating the level granted to the logged user as defined in the table above.

NOTE:



Unique id - index or display name ?

Each playlist can be addressed using either its unique_id or its index.

Each clip can be addressed using either its unique_id, its index or eventually its display name.

Each action can only be addressed by its unique_id.



Controlling the playback or getting the status

Types of controls

You have three ways to control the playback. Depending on what you want to achieve:

  • Control the playback without specifying a playlist, or a clip. In this case, the front playlist (or the playing one) will be the one answering your requests.
  • Control the playback by specifying the playing you want to control, but without specifying a clip. In this case you can start the playback on a specific playlist, and the first clip (or the playing one) in the playlist will be controlled
  • Control the playback by specifying both the playing you want to control, as well as the clip. That's the way to start playing a specific clip in a specific playlist.

Controlling the playback without specifying a playlist or a clip:

Get the status

GET http://localhost:8081/playback/playing
Response: playback status object

Playback response object:

{
	"is_playing" : boolean,
	"is_paused" : boolean,
	"is_locked" : boolean,
	"current_date_time" : string eg: "2021-03-08 12:53:03"
	"playlist_elapsed" : number, OPTIONAL * eg. 233.3199
	"playlist_duration" : number, OPTIONAL * eg. 233.3199
	"playlist_remaining" : number, OPTIONAL * eg. 80.7999
	"playlist_index": number, OPTIONAL *  Playing playlist's index (in opening order)
	"playlist_display_name": string, OPTIONAL * Playing playlist's name
	"playlist_unique_id": string, OPTIONAL * Playing playlist's unique ID
	"item_index" : number, OPTIONAL * eg. 3
	"item_playback_status" : string, OPTIONAL * 
playback mode
"item_elapsed" : number, OPTIONAL * eg. 152.5200 "item_remaining" : number, OPTIONAL * eg. 65.03 "item_display_name" : string, OPTIONAL * eg. "MyMovie1" "item_path" : string, OPTIONAL * eg. "/Volumes/Videos/MyMovie1.mov" "item_unique_id" : string, OPTIONAL * eg. "666AD1EF-54C6-4A63-A67B-501C57E6080F" or "" if not playing "item_duration" : number, OPTIONAL * eg. 233.3199 }

*: Thoses fields will only appear if a playlist is playing

Stop

GET http://localhost:8081/playback/stop
Response: command response object


Controlling the playback by specifying a playlist, but not the clip

You have two ways to control the playback. Either can control the playback of the playlist, without specifying a clip. In that case it behave exactly as if you were pushing the playback buttons in the playlist. Depending on which clip plays or is selected it will behave differently. If you need to stop or pause the playback, it's easier to just tell the playlist to stop or pause. But to play, you may not know which clip will start playing.

NOTE:
When using playback commands (play or pause) by specifying a clip, the following parameters can be passed in the URL to set the playback's play head at a precise timecode:

"position_relative_timecode": string HH:MM:SS:FF timecode position from the clip's start
"position_media_timecode": string HH:MM:SS:FF absolute timecode in the media
"position_relative_seconds": number position after x seconds from the media's beginning

Get the status

GET http://localhost:8081/playlists/{n}/playing
Response: command response object

Play

GET http://localhost:8081/playlists/{n}/play
Response: command response object

Pause

GET http://localhost:8081/playlists/{n}/pause
Response: command response object

Resume

GET http://localhost:8081/playlists/{n}/resume
Response: command response object

Stop

GET http://localhost:8081/playlists/{n}/stop
Response: command response object


Cue trigger

GET http://localhost:8081/playlists/{n}/cue_trigger
Response: command response object


Skip to next

GET http://localhost:8081/playback/skip_next
GET http://localhost:8081/playlists/{n}/skip_next
Response:

{
	"success": boolean,
	"last_position": number Indicates the elapsed time of the previously playing clip in seconds.
}


Skip to previous

GET http://localhost:8081/playback/skip_previous
GET http://localhost:8081/playlists/{n}/skip_previous
Response: command response object


Play next (clip)

GET http://localhost:8081/playlists/{n}/items/{i}play_next
Response: command response object


Clear next (clip)

GET http://localhost:8081/playback/clear_next
GET http://localhost:8081/playlists/{n}/clear_next
Response: command response object


Join in progress

GET http://localhost:8081/playback/join_in_progress
GET http://localhost:8081/playlists/{n}/join_in_progress
Response: command response object


Get available transitions

GET http://localhost:8081/playback/transitions
Response: array <string>


Get playback's subtitles

GET http://localhost:8081/playback/subtitles
Response: array <subtitle record object>

Subtitle record response object:

{
	"start_time_seconds": number,
	"start_timecode": string,
	"end_time_seconds": number,
	"end_timecode": string,
	"text_lines": array <subtitle line>
}

Subtitle line response object:

{
	"alignment": string, eg. "center" see 
alignment type
"text": string }

Controlling the playback for a specific clip within a playlist

If you want to start playing the clip {m} within the playlist {n}, you need to specify the clip via its index or unique id.

Play

GET http://localhost:8081/playlists/{n}/items/{m}/play
Response: command response object


Adding subtitles to current playback

POST http://localhost:8081/playback/subtitles

Subtitle record object:

{
	"start_time_seconds": number, REQUIRED
	"start_timecode": string, OPTIONAL Format HH:MM:SS,ttt
	"end_time_seconds": number, REQUIRED
	"end_timecode": string, OPTIONAL Format HH:MM:SS,ttt
	"text_lines": array <subtitle line> REQUIRED
}

Subtitle line object:

{
	"color": string, eg. "#ff00ff" OPTIONAL
	"alignment": string, 
alignment type
OPTIONAL "vertical_position": number, eg. 11 OPTIONAL "text": string }
Response: command response object

NOTE:
"end_time_seconds" property override the "end_timecode" property.
"start_time_seconds" property override the "start_timecode" property.




Control the DGO

Get the DGO projects:

Here are examples of requests to get the available CG projects or a specific project designated by {n}:

GET http://localhost:8081/playback/cg_projects
Response: array <CG Project object>
GET http://localhost:8081/playback/cg_projects/{n}
Response: CG Project object

CG Project object:

{
	"unique_id" : string,
	"formatted_elapsed_time" : string, eg. "00:00:00"
	"formatted_duration_time" : string,
	"formatted_remaining_time" : string,
	"published" : boolean,
	"display_name" : string, eg. "AnalogClock"
	"display_mode" : string, OPTIONAL eg. "1080i 59.94"
	"width" : number, OPTIONAL eg. 1920
	"height" : number, OPTIONAL eg. 1080
	"frames_per_second" : number, OPTIONAL
	"metadata" : object,
	"path" : string, eg. "\/Applications\/OnTheAir CG\/Projects\/AnalogClock.cg3"
	"remaining" : number,
	"elapsed" : number,
	"duration" : number,
	"status" : string  eg. "Loading"
}


Get the CG items of a DGO project:

GET http://localhost:8081/playback/cg_projects/{n}/items
Response: array <CG Item object>
GET http://localhost:8081/playback/cg_projects/{n}/items/{i}
Response: CG Item object

CG Item object:

{
	"unique_id" : string,
	"type" : string,
	"display_name" : string,
	"frame" : number,
	"begin_time" : number,
	"hold_duration" : number,
	"stay_forever" : boolean,
	"is_locked" : boolean,
	"is_hidden" : boolean,
	"is_published" : boolean,
	"default_value" : string
}


Play/Pause/Stop a DGO project:

Play

PUT http://localhost:8081/playback/cg_projects/{n}/play
Response: command response object

Pause

PUT http://localhost:8081/playback/cg_projects/{n}/pause
Response: command response object

Stop

PUT http://localhost:8081/playback/cg_projects/{n}/stop
Response: command response object

Additional commands:

Getting the thumbnail of a project

PUT http://localhost:8081/playback/cg_projects/{n}/thumbnail
Query parameters:
	"width"  REQUIRED
	"height" REQUIRED
Response: application/jpeg DATA or command response object

Close the project

PUT http://localhost:8081/playback/cg_projects/{n}/close
Response: command response object

Scrub in the project

PUT http://localhost:8081/playback/cg_projects/{n}/scrub
Query parameters:
	"position" REQUIRED
Response: command response object

GET Playlists

Get info about a playlist:

Here is an example of request that you can use in a simple browser, to get the information about the playlist {n}:

GET http://localhost:8081/playlists/{n}
Response: Playlist object

Playlist object:

{
	"unique_id" : string, name of the document made unique
	"path" : string, OPTIONAL eg. "/Volumes/Videos/MyPlaylist.xpls"
	"name" : string, eg. "MyPlaylist"
	"loop": boolean,
	"chain": boolean,
	"cue": boolean,
	"shuffle": boolean,
	"is_folder_based": boolean,
	"folder_based_path": string OPTIONNAL eg. "/Volumes/Videos/"
	"total_items" : number, eg. 57 OPTIONAL only if 'items' is not present
	"player_description" : string, eg. "Virtual Output (1080i 59.94)"
	"duration" : number, eg. 1800.7999
	"duration_string" : string, eg. "00:30:02" HH:MM:SS
	"preset_duration": number, eg. 1800
	"preset_duration_string": string, eg. "00:30:00" HH:MM:SS
	"is_front" : boolean,
	"items": array <Playlist Item Object> OPTIONAL Pass "include_items=true" in query parameters
}

NOTE:
The "preset_duration" parameter is a theoretical value that indicates the desired duration of the playlist althougth the duration may or may not be equal to this one.


Get the playback status of a playlist

The following request will get the playback status of playlist {n}. You can use the playlist index, or a unique ID (see above).

GET http://localhost:8081/playlists/{n}/playing
Response: playback response object


Get the list of items of a playlist

The following request will get the list of items in playlist {n}. You can use the playlist index, or a unique ID (see above)

GET http://localhost:8081/playlists/{n}/items
Response: array <playlist's item object>

Get the info of a specific item in a playlist

The following request will get the info of the item {m} in playlist {n}. You can use the playlist index, or a unique ID (see above), same thing for the clip, you can use either the index or the unique ID.

GET http://localhost:8081/playlists/{n}/items/{m}

Playlist's item object response:

{
	"unique_id" : string, OPTIONAL * eg. "666AD1EF-54C6-4A63-A67B-501C57E6080F"
	"name" : string, eg. "MyMovie1"
	"clip_type" : enum <
clip_type
>, "segment_number" : number, "reconcile_id" : string, OPTIONAL "isci_code" : number, OPTIONAL "url" : string, eg. "/Users/admin/Documents/MyMovie1.mov" for FILE or STREAM "video_codec" : string, eg. "H.264" "audio_codec" : string, eg. "AAC" "last_modification_date" : string, "has_in_point" : boolean, "in_point" : number, eg. 9.902 (in seconds) "has_out_point" : boolean, "out_point" : number, eg. 59.000 (in seconds) "closed_captions" : array <string>, OPTIONAL "languages" : array <string> OPTIONAL "live_source_name": string OPTIONAL eg. "Live Source 2" "is_streamed": boolean, Indicates if the stream is a remote file or not. "playback_mode" : string,
playback mode
"resize_mode": string,
resize mode
"duration" : number, eg. 679.902 (in seconds) "duration_timecode" : string, eg. "00:11:34" HH:MM:SS "frames_per_second" : number, "drop_frame" : boolean, "is_offline": boolean, will always set to false for a LIVE or STREAM clip. "is_valid" : boolean, "is_cued_as_next": boolean, "validation_status" : string,
validation status
"validation_error" : string,
validation error
"start_time" : number, "start_timecode" : string eg. "00:00:10" HH:MM:SS "has_absolute_start_time" : boolean, "displayed_start_time" : number, "displayed_start_timecode" : string, eg. "00:00:00" HH:MM:SS "theoretical_absolute_start_time" : number, eg. 13.532 (in seconds) "actions" : array <action>, "audio_volume" : number, "logo_enabled" : boolean, "logo_filename" : string, OPTIONAL "reverse_field_order" : boolean, "subtitles" : array <string>, OPTIONAL "start_transition_name": string eg. "Push - Down", "is_used_by_scheduler": boolean }

* : if the unique_id property is not present it means that the item is still in the playlist but will be further deleted and thus cannot be accessed.
NB: If 'clip_type' is a comment item, he will only have 'unique_id', 'name', 'clip_type' & 'segment_number' properties.

Get an Apple script action of a playlist item

The following request will retrieve the action {k} set on the item {m} of playlist {n}. You can use indexes, or unique IDs (see above).

GET http://localhost:8081/playlists/{n}/items/{m}/actions/{k}

Action response object:

{
	"name" : string, eg. "Display Finder Message" -> name of the AppleScript
	"unique_id" : string, eg. 0650A319-B0B7-4B06-957C-F81B38470548
	"position" : number, eg. 0
	"position_type" : string, 
position type
"position_timecode" : string, eg. "00:00:00:00" HH:MM:SS:FF "parameter" : string, eg. Hello "is_outpoint_clamped" : boolean, "is_inpoint_clamped" : boolean, "is_valid" : boolean, "is_offline": boolean }

Get Apple script actions of a playlist item

The following request will retrieve the actions set on the item {m} of playlist {n}. You can use indexes, or unique IDs (see above).

GET http://localhost:8081/playlists/{n}/items/{m}/actions
Response: array <playback response object>

Get available Apple script action's names list

The following request will retrieve the available actions on the server. You can use them to update your clip's actions

GET http://localhost:8081/actions
Response: array <string>

Run an Apple script action on the go

The following request will run the mentionned apple script.

GET http://localhost:8081/actions/{name}/run?parameter={parameter}
Where :
{name} is the name of the action (the one you see on your folder)
{parameter} is the paramter you want to pass to that action

Warning: Use url percent encoded string if your action's name or parameter is using special characters (especially spaces) !

Response: command response object



Scheduler & Control

Enable the schedule

GET http://localhost:8081/scheduler/start

Stop the schedule

GET http://localhost:8081/scheduler/stop

Get the list of playlists in the current schedule

GET http://localhost:8081/scheduler/playlists
Response: array <scheduler's playlist object>

Scheduler's Playlist object response:

{
	"path" : string, eg. "/Volumes/Movies/DailyPlaylist.xpls"
	"missing_clips" : number,
	"modification_date" : string, eg. "Today at 09:35"
	"is_folderbased" : boolean,
	"total_items" : number,
	"duration" : number, eg. 1802.00
	"duration_string" : string eg. "00:30:02" HH:MM:SS
}

Open a playlist from the schedule

The following request will open the playlist with specified path {path}. Once a scheduled playlist is open you can control it the way you do with opened playlists.

GET http://localhost:8081/scheduler/playlists?path={path}
Response: playlist response object in case of success, command response object in case of open failure

Close a playlist

The following request will close the playlist with specified ID.
Warning ! Use this command with care as some other remote user may no longer have access to the playlist after its close.

GET http://localhost:8081/playlists/{id}/close

Get schedule's infos

GET http://localhost:8081/scheduler?include_items=1

You can retrieve several infos about the current scheduler. The query parameter "include_items" will allow you to get all the events of the scheduler. If you don't need them, don't pass it.

Response:
{
	"version" : string, eg. "2.0"
	"is_enabled" : boolean,
	"schedule_path" : string, OPTIONAL eg. "/Users/admin/Documents/MySchedule.xml"
	"current_playlist": string, OPTIONAL
	"next_playlist": string, OPTIONAL
	"next_timed_playlist": string, OPTIONAL
	"events": array <scheduler event response object> OPTIONAL
}

Get schedule's events only

GET http://localhost:8081/scheduler/events

Scheduler's event object response:

{
  "playlists": [
	{
	  "playlist_path": string, eg. "/Users/admin/Documents/MyPlaylist.xpls"
	  "should_shuffle": boolean,
	  "should_loop": boolean,
	  "should_randomize": boolean
	},
	{
	  "playlist_path": string, eg. "/Users/admin/Documents/MyPlaylist.xpls"
	  "should_shuffle": boolean,
	  "should_loop": boolean,
	  "should_randomize": boolean
	}
  ],
  "is_enabled": boolean,
  "repeating_event_start_time": number, OPTIONAL
  "should_loop": false,
  "repeating_days": {
	"monday": boolean,
	"friday": boolean,
	"sunday": boolean,
	"tuesday": boolean,
	"thursday": boolean,
	"wednesday": boolean,
	"saturday": boolean
  }, OPTIONAL
  "display_name" : string,
  "is_repeating_event" : boolean
}



PUT Requests

Update playlist's clip

All properties of a clip can be changed but here are the most common to be changed.
WARNING: if you change some properties that doesn't appear on this list, it might lead to unwanted UI behaviour.
PUT http://localhost:8081/playlists/{n}/items/{m}
Body:
{
	"name" : string, OPTIONAL eg. "MyMovie1"
	"url" : string, OPTIONAL eg. "/Volumes/Movies/MyMovie.mov" (ONLY FOR FILE or STREAM)
	"live_source_name" : string, OPTIONAL eg. "Live Source 2" (ONLY FOR LIVE)
	"duration" : number, OPTIONAL eg. 679.902 (in seconds) (ONLY FOR LIVE or STREAM)
	"playback_mode" : string, 
playback_mode
OPTIONAL "has_in_point" : boolean, OPTIONAL "in_point" : number, OPTIONAL eg. 9.902 (in seconds) "has_out_point" : boolean, OPTIONAL "out_point" : number, OPTIONAL eg. 59.000 (in seconds) "start_transition_name": string OPTIONAL }
Response: playlist's item object

Update clip's action

PUT http://localhost:8081/playlists/{n}/items/{m}/actions/{k}
Body:
{
	"name" : string, OPTIONAL eg. "Display Finder Message" -> name of the AppleScript
	"position" : number, OPTIONAL eg. 0
	"position_type" : string, OPTIONAL
	"position_timecode" : string, OPTIONAL eg. "00:00:00:00" HH:MM:SS:FF
	"parameter" : string, OPTIONAL eg. Hello
}
Response: action response object



POST Requests

Create a clip

POST http://localhost:8081/playlists/{n}/items

If you want to create a clip at a specific index {m}, you can use the following:

POST http://localhost:8081/playlists/{n}/items/{m}
Body:
{
	"clip_type" : enum <
clip_type
>, REQUIRED "url" : string, REQUIRED ONLY FOR FILE or STREAM eg. "/Volumes/Movies/MyMovie.mov" "live_source_name" : string, REQUIRED ONLY FOR LIVE eg. "Live Source 2" "duration" : number, REQUIRED ONLY FOR STREAM OR LIVE eg. 679.902 (in seconds) "name" : string, OPTIONAL eg. "MyMovie1" "playback_mode" : string,
playback_mode
OPTIONAL "has_in_point" : boolean, OPTIONAL "in_point" : number, OPTIONAL eg. 9.902 (in seconds) "has_out_point" : boolean, OPTIONAL "out_point" : number, OPTIONAL eg. 59.000 (in seconds) "start_time" : number, OPTIONAL }
Response: playlist's item object

Examples:

File based clip body:

{
	"clip_type" : 0,
	"url" : "/Volumes/Movies/MyMovie.mov"
}

Comment:

{
	"clip_type" : 3,
	"name" : "Start Section"
}

Live clip body:

{
	"clip_type" : 4,
	"live_source_name" : "Live Source 2",
	"duration" : 1800
}

Stream clip body:

{
	"clip_type" : 5,
	"url" : "rtmp://192.168.0.10:1935/live/mystream",
	"duration" : 1800
}

Create an action on a clip

POST http://localhost:8081/playlists/{n}/items/{m}/actions
Body:
{
	"name" : string, OPTIONAL eg. "Display Finder Message" -> name of the AppleScript
	"position_type" : string, 
position_type
OPTIONAL "position_timecode" : string, OPTIONAL eg. "00:00:00:00" HH:MM:SS:FF "parameter" : string, OPTIONAL eg. Hello }
Response: action response object



DELETE Requests

DELETE requests can be used to delete elements, thus affecting your upcoming playback, use it with caution as it can not be reverted once done.

Delete all clips of a playlist

DELETE http://localhost:8081/playlists/{n}/items
Response: command response object

NOTE:
Trying to delete all clips of playing playlist will return an error.

Delete a specific clip of a playlist

DELETE http://localhost:8081/playlists/{n}/items/{m}
Response: command response object

NOTE:
Trying to delete a playing clip of a playlist will return an error.

Delete all actions of a clip

DELETE http://localhost:8081/playlists/{n}/items/{m}/actions
Response: command response object

Delete a specific action

DELETE http://localhost:8081/playlists/{n}/items/{m}/actions/{k}
Response: command response object



For more information

If you need more info or support about OnTheAir Video, you can find it on our support desk. And if you need additional information on the API and/or the websockets, submit a ticket and we'll be happy to guide you.