---
title: Scripting Xibo Content Management - A brief tour of the API
description: "Please note: This article refers to Xibo 1.7 only and has been retired from our
catalogue of updated Guides. Please refer to the API Introduction Guide 1.8
[https://community.xibo.org.uk/t/1-8-api-introduction/7702]
One common use case people put forward is that they want to update a particular
piece of content in a layout automatically on a schedule.

That could take the form of a video being updated on a daily basis, or an image.

Since Xibo 1.5 series, there has been a “work in progress” OAuth authenticated
API for scripting actions in the Xibo CMS. As of Xibo 1.6.0-rc1, there are
enough API methods implemented to do some basic layout and media management to
script tasks such as these.

This article is a basic walk through showing you how to connect to the API,
authorise an application to use the Xibo CMS on your behalf, a quick look at
some basic API methods, and finally complete code to automatically replace a
media item in a layout.

Firstly you must be running Xibo CMS 1.6.0-rc1 or later. Earlier versions may
not have the API methods required for this guide.

This guide uses Python as the scripting language. Python is chosen because it’s
cross platform, widely available, and it’s what the Xibo project uses to test
the API with, so there are existing libraries (XiboAPI) that we can leverage.
It’s perfectly possible to connect to the API from other languages. Indeed some
example PHP code
[http://bazaar.launchpad.net/~xibo-maintainers/xibo/ponswinnecke/files/head:/example_oauth/]
 is provided in the main Xibo repository. The use of the API from other
languages however falls outside this scope of this guide.

Most modern Linux installations will come with Python ready-installed. Windows
users can download and install Python here:http://www.python.org/getit  This
guide assumes you have Python 2.7 installed.

 * You also need the Python OAuth2 library installed. - On Linux, you’ll need to
   install the “python-oauth2” package (at least on Debian based systems such as
   Ubuntu).
 * On Windows, the process is slightly less straight forward - Download OAuth2
   library from github:
   https://github.com/simplegeo/python-oauth2/archive/master.zip
 * Extract the downloaded file somewhere on your PC (remember where this is!)
 * Open a command promt (Start -> Run -> cmd)
 * Change directory to where you extracted OAuth2 to (eg cd
   c:\\tmp\\python-oauth2-master)
 * Then run: python setup.py install
 * The OAuth2 library will be installed to your Python installation
 * Make an empty folder somewhere to store your new script in.
 * Download the XiboAPI.py library
   [http://bazaar.launchpad.net/~alexharrington/xibo/api-testsuite/download/head:/xiboapi.py-20100925203753-fuax1wpyhb2ydvee-2/XiboAPI.py] 
    and config file
   [http://bazaar.launchpad.net/~alexharrington/xibo/api-testsuite/download/head:/defaults.cfg-20100925170824-0y3ixp9r08s1l0bq-1/defaults.cfg]
   , and save a copy of both in your new folder.
 * Python is a white-space delimited language, which means that the amount each
   line of code is indented defines which code block a line belongs to. It’s
   therefore very important that you setup your text editor to follow the
   standard Python convention. Tab characters should not be used, but instead
   four space characters. On Linux, gedit is a suitable choice, and on Windows
   I’d recommend Notepad++ [http://notepad-plus-plus.org/].
 * This guide will give you the overview of how to communicate with the Xibo CMS
   via the API. It is not intended to be a guide on programming in the Python
   scripting language. There’s a plethora of resources out there aimed at that.
   I would recommend Dive into Python [http://www.diveintopython.net/]  as a
   good primer before embarking on this is Python is your chosen language.
 * So lets make a start! We’ll create a new file called ReplaceVideo.py with the
   following contents:

!/usr/bin/python # -- coding: utf-8 -- # # Script to upload a Video to the Xibo
CMS and replace # an old copy of it in a region # Imports import os from xml.dom
import minidom import XiboAPI api = XiboAPI.XiboAPI()
 * So there we’ve defined that the script is Python and that it’s UTF-8 encoded
   (so we don’t have issues with unicode characters down the line). We then
   import the os, minidom and XiboAPI libraries. Finally we create an instance
   of the XiboAPI to communicate with the CMS.
 * Next we need to register your application with the Xibo CMS. You’ll need an
   administrative login to your Xibo CMS. - Once logged in as an administrator
   (eg xibo_admin), go to Administration -> Applications
 * Click Add Application
 * Enter your name and email address. You can leave the third and fourth boxes
   (website and callback URL empty)
 * Click Register
 * Note the Key and Secret that have been generated. We’ll need those in the
   next step.
 * Next open defaults.cfg in your text editor. We need to point the XiboAPI
   library at your Xibo CMS.
 * Edit the file as follows, replacing the consumer_key and consumer_secrets
   with the values you got from your CMS, and the URL for your Xibo CMS:

[Main] secret = NULL token = NULL url = http://yourXiboServer.com/path/xibo 
consumer_key = 1b9e2c84fc747257375ae3eaaa01d49705303dac7 consumer_secret =
948989ef9eb9c17c26369a2265c35cea

 * Save defaults.cfg and close it
 * Save your ReplaceVideo,py script
 * Now lets run what we have:

alex@alex-laptop:~/scratch/xibo-release/ReplaceVideo$ python ReplaceVideo.py
Request Token: - oauth_token = 7dda5851bf99e09bdad1b27aebaa6fd005303dc3e -
oauth_token_secret = a289a41cab324475c849283d553b113b Go to the following link
in your browser: 
http://localhost/html/xibo-16/server/index.php?p=oauth&q=authorize&oauth_token=7dda5851bf99e09bdad1b27aebaa6fd005303dc3e
[http://localhost/html/xibo-16/server/index.php?p=oauth&q=authorize&oauth_token=7dda5851bf99e09bdad1b27aebaa6fd005303dc3e] 
 Have you authorized me? (y/n)

 * That’s the output from my script so far. So hopefully your script will
   attempt to connect to the Xibo CMS at the URL you configured, and will ask
   you to authorise it with the CMS. Now before you click the link, it’s
   important that you log on to the Xibo CMS as the user you want the script to
   impersonate. So if the script needs to appear to be the user “alex”, log off
   the Xibo CMS and log in as “alex”. Then follow the link.
 * You’ll be taken to a page “Xibo API – Authorization Requested”. Click the
   Allow button. Since we didn’t define a callback URL, the page will refresh
   lots now. That’s normal and can be ignored. Keep clicking the Allow button
   until you see a message ‘Request authorized. Please return to your
   application.’
 * Go back to your running script and enter “y” to indicate the API request has
   been authorised.
 * You will see that access has been authorised:

Access Token: - oauth_token = 93399a91be50497afd0e3f66521ddc4b05303de08 -
oauth_token_secret = 104e4911f5f0e1dc9a45978d2428cbfa You may now access
protected resources using the access tokens above.

 * Excellent, so now we have access to the XiboAPI as your intended user. I
   appreciate that’s alot of setup work but most of this only ever needs to be
   done once. You can reuse the same XiboAPI object in more than one project.
 * Your access tokens will automatically be written to disk in a file called
   site.cfg. Keep that file safe as the contents allow API access to your Xibo
   CMS.
 * Now let’s do something useful with the API! Lets get a list of layouts in the
   system. Add the following to your ReplaceVideo.py script:

Call the LayoutList Method response, status, code, message, content =
api.callMethod('LayoutList') # Parse the response XML doc =
minidom.parseString(content) #List the layouts nodes =
doc.getElementsByTagName('layout') for layout in nodes: layoutId =
int(layout.attributes['layoutid'].value) layoutName =
str(layout.attributes['layout'].value) layoutDescription =
str(layout.attributes['description'].value) layoutTags =
str(layout.attributes['tags'].value) print \"Layout ID %d\" % layoutId print \"
Name: %s\" % layoutName print \" Description: %s\" % layoutDescription print \"
Tags: %s\\n\" % layoutTags print \"Layout List Complete\\n\\n\"
 * Save the file and run it again. Note this time since we already have API
   credentials, the access to the API is seemless and no user interaction is
   required. A list of layouts the user has access to view is shown:

alex@alex-laptop:~/scratch/xibo-release/ReplaceVideo$ python ReplaceVideo.py
Layout ID 4 Name: Default Layout Description: Tags: Layout ID 5 Name: My Video
Layout Description: Daily Updated Video Tags: video Layout List Complete

 * So here the Layout we’re interested in is Layout ID 5. Lets add some code to
   see what regions are in Layout ID 5. Add the following to ReplaceVideo.py:

We're interested in LayoutID 5 params = [('layoutid', '5')] # Call the
RegionList Method response, status, code, message, content =
api.callMethod('LayoutRegionList', params) # Parse the response XML doc =
minidom.parseString(content) # List the Regions nodes =
doc.getElementsByTagName('region') for node in nodes: regionId =
str(node.attributes['regionid'].value) regionWidth =
int(node.attributes['width'].value) regionHeight =
int(node.attributes['height'].value) regionTop =
int(node.attributes['top'].value) regionLeft =
int(node.attributes['left'].value) print \"Region ID %s\" % regionId print \"
Width: %s\" % regionWidth print \" Height: %s\" % regionHeight print \" Top: %s\" %
regionTop print \" Left: %s\\n\" % regionLeft print \"Region List Complete\\n\\n\"
 * Again save the file and run it again:

Region ID 47ff29524ce1b Width: 409 Height: 450 Top: 0 Left: 0 Region ID
5303e4c0c0973 Width: 227 Height: 212 Top: 40 Left: 502 Region List Complete

 * So my example layout (id 5) has two regions on it. The right-most region is
   the one which will host our video and that’s the second one in the list (we
   know it’s that one as the Left value is highest putting it further away from
   the left hand edge of the layout). So we’ll make a note of the region ID
   (5303e4c0c0973)
 * Now let’s see what’s in that region already:

We're interested in LayoutID 5 # RegionID 5303e4c0c0973 params = [('layoutid',
'5'), ('regionid', '5303e4c0c0973')] # Call the RegionList Method response,
status, code, message, content = api.callMethod('LayoutRegionTimelineList',
params) # Parse the response XML doc = minidom.parseString(content) # List the
Regions nodes = doc.getElementsByTagName('media') for node in nodes: mediaId =
str(node.attributes['mediaid'].value) mediaType =
str(node.attributes['mediatype'].value) mediaDuration =
str(node.attributes['mediaduration'].value) print \"Media ID %s\" % mediaId print
\" Type: %s\" % mediaType print \" Duration: %s\\n\" % mediaDuration print \"Media
List Complete\\n\\n\"
 * Now save ReplaceMedia.py and run it:

Media ID 11 Type: video Duration: 0 Media List Complete

 * See the video that’s already in the region listed.
 * Hopefully that’s given a basic overview of how to navigate the API, how to
   pass in parameters etc. Now we’ll remove most of the code we’ve written and
   get on with the job in hand of scripting the file upload and replacing that
   video in the region. We need to remember it’s Layout ID 5,
   region 5303e4c0c0973 (or the correct values from your CMS). That’s how we’ll
   identify where we want our video to end up being added, and the old video to
   delete.
 * So now your ReplaceVideo.py should look like this:

!/usr/bin/python # -- coding: utf-8 -- # # Script to upload a Video to the Xibo
CMS and replace # an old copy of it in a region # Imports import os from xml.dom
import minidom import XiboAPI api = XiboAPI.XiboAPI() layoutId = 5 regionId =
'5303e4c0c0973' fileToUpload = 'myVideo.mp4' mediaName = 'Daily Video'
 * Clearly set layoutId and regionId to the correct values we obtained earlier.
   Change fileToUpload to be the filename of the video you want to upload. It
   could be in the same directory as your script (in which case just the name is
   sufficient), or it could be a full path to the file. It’s up to you.
 * I’ve included some library functions to do the heavy lifting for you. Add the
   following to the file and save:

################################# # START LIBRARY FUNCTIONS
################################# def
uploadFile(api,path,chunksize=256000,fileid='0',offset=0,size=0): # Uploads file
at path (full path) # Returns a file upload ID which can be used to add the
media # to the library # # eg uploadFile(api,'/home/user/1.jpg') # # Optional
Parameters: # chunksize - Int: How many bytes to upload at each pass # fileid -
String: The fileUploadID to use. Useful if you're resuming an interupted upload.
# offset - Long: How many bytes to skip over before beginning upload. Useful for
resuming an interupted upload. # size - Long: How many bytes to upload. 0 = the
whole file. Useful to break an upload part way through for testing. # Must be
smaller than the size of the file in bytes. # First check the test file exists
if not os.path.isfile(path): print \"Error: File does not exist %s \" % path
exit(1) checksum = '' data = '' if size == 0: size = os.path.getsize(path)
chunkOK = False # If the file is smaller than the chunksize, send one chunk # of
the correct size. if chunksize > size: chunksize = size # Open the file for
binary read fh = open(path,'rb') while offset size: chunksize = size - offset #
All chunks uploaded # Close the file handle fh.close() return fileid def
layoutRegionMediaDelete(api,layoutid,regionid,mediaid,lkid): params =
[('mediaId',mediaid), ('regionId',regionid), ('layoutId',int(layoutid)),
('lkId',int(lkid)) ] response, status, code, message, content =
api.callMethod('LayoutRegionMediaDelete', params) def
libraryMediaDelete(api,mediaid): params = [('mediaId',mediaid)] response,
status, code, message, content = api.callMethod('LibraryMediaDelete', params)
############################################# # END LIBRARY FUNCTIONS
#############################################

 * So first up we upload the new file to the CMS. Note here that by upload we
   mean copy it to the server ready to be added to the library. We add it to the
   library in a second stage later on. Add the following to upload:

Upload our file to the CMS so it's ready to add # Note this won't make it appear
in the library # We do that further down the script uploadId =
uploadFile(api,fileToUpload)
 * Next we need to find the ID of the old video file, remove it from the Region
   Timeline, and then delete it from the library. Add the following:

Find out what the mediaID of the old video is, and remove it from the layout
oldMediaId = None params = [('layoutid', layoutId), ('regionid', regionId)] #
Call the RegionList Method response, status, code, message, content =
api.callMethod('LayoutRegionTimelineList', params) # Parse the response XML doc
= minidom.parseString(content) # List the Regions nodes =
doc.getElementsByTagName('media') for node in nodes: if
str(node.attributes['mediatype'].value) == 'video': oldMediaId =
str(node.attributes['mediaid'].value) lkid = str(node.attributes['lkid'].value)
if not oldMediaId is None: # We found an old video in the region # Lets delete
it print \"Removing old media with ID %s\" % oldMediaId
layoutRegionMediaDelete(api, layoutId, regionId, oldMediaId, lkid)
libraryMediaDelete(api, oldMediaId)
 * Now the old video is gone from the layout timeline, and from the CMS Library,
   we can add our new video to the library and add it to the region. Add the
   following:

Now the file is uploaded, and the old file is deleted, # we need to add the
newly uploaded file to the CMS Library params = [('fileId', uploadId), ('type',
'video'), ('name', mediaName), ('duration', '0'), ('permissionId','1'),
('fileName',os.path.basename(fileToUpload)) ] response, status, code, message,
content = api.callMethod('LibraryMediaAdd', params) # Get the ID of the file we
just added mediaId = api.parseID(content,'media') # Now mediaID contains the
library media ID of our freshly uploaded video print \"Adding new media with ID
%s\" % mediaId # Now add our new media item to the region params =
[('layoutId',layoutId), ('regionId',regionId), ('mediaList',mediaId), ]
response, status, code, message, content =
api.callMethod('LayoutRegionLibraryAdd', params)
 * Finally check that the video was added correctly by listing the media items
   in the region. Add the following:

Finally Check the layout now contains the new video # by listing the contents of
the region and checking for our new video params = [('layoutId', layoutId),
('regionId', regionId)] # Call the RegionList Method response, status, code,
message, content = api.callMethod('LayoutRegionTimelineList', params) # Parse
the response XML doc = minidom.parseString(content) # List the Regions nodes =
doc.getElementsByTagName('media') for node in nodes: if
str(node.attributes['mediatype'].value) == 'video': if
str(node.attributes['mediaid'].value) == str(mediaId): print \"Video Uploaded and
Layout Modified Successfully\" exit(0) print \"Error Uploading Video\"
 * Now save and run your file. You should see output as follows:

alex@alex-laptop:~/scratch/xibo-release/ReplaceVideo$ python ReplaceVideo.py
Removing old media with ID 15 Adding new media with ID 16 Video Uploaded and
Layout Modified Successfully

 * You can now use cron or Windows Task Scheduler to run that script on a
   schedule and have your content update in Xibo automatically.
 * There’s an API reference showing all the API calls currently available in the
   manual here:
   http://xibo.org.uk/manual/index.php?toc=developer_api&p=admin/api_overview
   [http://xibo.org.uk/manual/index.php?toc=developer_api&p=admin/api_overview]

You can download the completed ReplaceVideo.py
[/wp-content/uploads/2014/02/ReplaceVideo.py]  file here."
---

[Blog | Xibo Digital Signage ](https://xibosignage.com/blog)

# [Scripting Xibo Content Management - A brief tour of the API](https://xibosignage.com/blog/scripting-xibo-content-management-a-brief-tour-of-the-api)

 Written by [Alex](https://xibosignage.com/blog/author/alex) | Feb 19, 2014 12:00:00 AM

### The information contained on this page is now archived. Please see our website and documentation for current information

## Please note: This article refers to Xibo 1.7 only and has been retired from our catalogue of updated Guides. Please refer to the [API Introduction Guide 1.8](https://community.xibo.org.uk/t/1-8-api-introduction/7702)

One common use case people put forward is that they want to update a particular piece of content in a layout automatically on a schedule.

That could take the form of a video being updated on a daily basis, or an image.

Since Xibo 1.5 series, there has been a “work in progress” OAuth authenticated API for scripting actions in the Xibo CMS. As of Xibo 1.6.0-rc1, there are enough API methods implemented to do some basic layout and media management to script tasks such as these.

This article is a basic walk through showing you how to connect to the API, authorise an application to use the Xibo CMS on your behalf, a quick look at some basic API methods, and finally complete code to automatically replace a media item in a layout.

Firstly you must be running Xibo CMS 1.6.0-rc1 or later. Earlier versions may not have the API methods required for this guide.

This guide uses Python as the scripting language. Python is chosen because it’s cross platform, widely available, and it’s what the Xibo project uses to test the API with, so there are existing libraries (XiboAPI) that we can leverage. It’s perfectly possible to connect to the API from other languages. Indeed some [example PHP code](http://bazaar.launchpad.net/~xibo-maintainers/xibo/ponswinnecke/files/head:/example_oauth/) is provided in the main Xibo repository. The use of the API from other languages however falls outside this scope of this guide.

Most modern Linux installations will come with Python ready-installed. Windows users can download and install Python here: [http://www.python.org/getit](http://www.python.org/getit) This guide assumes you have Python 2.7 installed.

- You also need the Python OAuth2 library installed. - On Linux, you’ll need to install the “python-oauth2” package (at least on Debian based systems such as Ubuntu).
- On Windows, the process is slightly less straight forward - Download OAuth2 library from github: [https://github.com/simplegeo/python-oauth2/archive/master.zip](https://github.com/simplegeo/python-oauth2/archive/master.zip)
- Extract the downloaded file somewhere on your PC (remember where this is!)
- Open a command promt (Start -> Run -> cmd)
- Change directory to where you extracted OAuth2 to (eg cd c:\tmp\python-oauth2-master)
- Then run: python setup.py install
- The OAuth2 library will be installed to your Python installation
- Make an empty folder somewhere to store your new script in.
- Download the [XiboAPI.py library](http://bazaar.launchpad.net/~alexharrington/xibo/api-testsuite/download/head:/xiboapi.py-20100925203753-fuax1wpyhb2ydvee-2/XiboAPI.py) and [config file](http://bazaar.launchpad.net/~alexharrington/xibo/api-testsuite/download/head:/defaults.cfg-20100925170824-0y3ixp9r08s1l0bq-1/defaults.cfg), and save a copy of both in your new folder.
- Python is a white-space delimited language, which means that the amount each line of code is indented defines which code block a line belongs to. It’s therefore very important that you setup your text editor to follow the standard Python convention. Tab characters should not be used, but instead four space characters. On Linux, gedit is a suitable choice, and on Windows I’d recommend [Notepad++](http://notepad-plus-plus.org/).
- This guide will give you the overview of how to communicate with the Xibo CMS via the API. It is not intended to be a guide on programming in the Python scripting language. There’s a plethora of resources out there aimed at that. I would recommend [Dive into Python](http://www.diveintopython.net/) as a good primer before embarking on this is Python is your chosen language.
- So lets make a start! We’ll create a new file called ReplaceVideo.py with the following contents:

# !/usr/bin/python # -*- coding: utf-8 -*- # # Script to upload a Video to the Xibo CMS and replace # an old copy of it in a region # Imports import os from xml.dom import minidom import XiboAPI api = XiboAPI.XiboAPI()

- So there we’ve defined that the script is Python and that it’s UTF-8 encoded (so we don’t have issues with unicode characters down the line). We then import the os, minidom and XiboAPI libraries. Finally we create an instance of the XiboAPI to communicate with the CMS.
- Next we need to register your application with the Xibo CMS. You’ll need an administrative login to your Xibo CMS. - Once logged in as an administrator (eg xibo_admin), go to Administration -> Applications
- Click Add Application
- Enter your name and email address. You can leave the third and fourth boxes (website and callback URL empty)
- Click Register
- Note the Key and Secret that have been generated. We’ll need those in the next step.
- Next open defaults.cfg in your text editor. We need to point the XiboAPI library at your Xibo CMS.
- Edit the file as follows, replacing the consumer_key and consumer_secrets with the values you got from your CMS, and the URL for your Xibo CMS:

[Main] secret = NULL token = NULL url = [http://yourXiboServer.com/path/xibo](http://yourXiboServer.com/path/xibo) consumer_key = 1b9e2c84fc747257375ae3eaaa01d49705303dac7 consumer_secret = 948989ef9eb9c17c26369a2265c35cea

- Save defaults.cfg and close it
- Save your ReplaceVideo,py script
- Now lets run what we have:

alex@alex-laptop:~/scratch/xibo-release/ReplaceVideo$ python ReplaceVideo.py Request Token: - oauth_token = 7dda5851bf99e09bdad1b27aebaa6fd005303dc3e - oauth_token_secret = a289a41cab324475c849283d553b113b Go to the following link in your browser: [http://localhost/html/xibo-16/server/index.php?p=oauth&q=authorize&oauth_token=7dda5851bf99e09bdad1b27aebaa6fd005303dc3e](http://localhost/html/xibo-16/server/index.php?p=oauth&q=authorize&oauth_token=7dda5851bf99e09bdad1b27aebaa6fd005303dc3e) Have you authorized me? (y/n)

- That’s the output from my script so far. So hopefully your script will attempt to connect to the Xibo CMS at the URL you configured, and will ask you to authorise it with the CMS. Now before you click the link, it’s important that you log on to the Xibo CMS as the **user you want the script to impersonate**. So if the script needs to appear to be the user “alex”, log off the Xibo CMS and log in as “alex”. Then follow the link.
- You’ll be taken to a page “Xibo API – Authorization Requested”. Click the Allow button. Since we didn’t define a callback URL, the page will refresh lots now. That’s normal and can be ignored. Keep clicking the Allow button until you see a message ‘Request authorized. Please return to your application.’
- Go back to your running script and enter “y” to indicate the API request has been authorised.
- You will see that access has been authorised:

Access Token: - oauth_token = 93399a91be50497afd0e3f66521ddc4b05303de08 - oauth_token_secret = 104e4911f5f0e1dc9a45978d2428cbfa You may now access protected resources using the access tokens above.

- Excellent, so now we have access to the XiboAPI as your intended user. I appreciate that’s alot of setup work but most of this only ever needs to be done once. You can reuse the same XiboAPI object in more than one project.
- **Your access tokens will automatically be written to disk in a file called site.cfg. Keep that file safe as the contents allow API access to your Xibo CMS.**
- Now let’s do something useful with the API! Lets get a list of layouts in the system. Add the following to your ReplaceVideo.py script:

# Call the LayoutList Method response, status, code, message, content = api.callMethod('LayoutList') # Parse the response XML doc = minidom.parseString(content) #List the layouts nodes = doc.getElementsByTagName('layout') for layout in nodes: layoutId = int(layout.attributes['layoutid'].value) layoutName = str(layout.attributes['layout'].value) layoutDescription = str(layout.attributes['description'].value) layoutTags = str(layout.attributes['tags'].value) print "Layout ID %d" % layoutId print " Name: %s" % layoutName print " Description: %s" % layoutDescription print " Tags: %s\n" % layoutTags print "Layout List Complete\n\n"

- Save the file and run it again. Note this time since we already have API credentials, the access to the API is seemless and no user interaction is required. A list of layouts the user has access to view is shown:

alex@alex-laptop:~/scratch/xibo-release/ReplaceVideo$ python ReplaceVideo.py Layout ID 4 Name: Default Layout Description: Tags: Layout ID 5 Name: My Video Layout Description: Daily Updated Video Tags: video Layout List Complete

- So here the Layout we’re interested in is Layout ID 5. Lets add some code to see what regions are in Layout ID 5. Add the following to ReplaceVideo.py:

# We're interested in LayoutID 5 params = [('layoutid', '5')] # Call the RegionList Method response, status, code, message, content = api.callMethod('LayoutRegionList', params) # Parse the response XML doc = minidom.parseString(content) # List the Regions nodes = doc.getElementsByTagName('region') for node in nodes: regionId = str(node.attributes['regionid'].value) regionWidth = int(node.attributes['width'].value) regionHeight = int(node.attributes['height'].value) regionTop = int(node.attributes['top'].value) regionLeft = int(node.attributes['left'].value) print "Region ID %s" % regionId print " Width: %s" % regionWidth print " Height: %s" % regionHeight print " Top: %s" % regionTop print " Left: %s\n" % regionLeft print "Region List Complete\n\n"

- Again save the file and run it again:

Region ID 47ff29524ce1b Width: 409 Height: 450 Top: 0 Left: 0 Region ID 5303e4c0c0973 Width: 227 Height: 212 Top: 40 Left: 502 Region List Complete

- So my example layout (id 5) has two regions on it. The right-most region is the one which will host our video and that’s the second one in the list (we know it’s that one as the Left value is highest putting it further away from the left hand edge of the layout). So we’ll make a note of the region ID (5303e4c0c0973)
- Now let’s see what’s in that region already:

# We're interested in LayoutID 5 # RegionID 5303e4c0c0973 params = [('layoutid', '5'), ('regionid', '5303e4c0c0973')] # Call the RegionList Method response, status, code, message, content = api.callMethod('LayoutRegionTimelineList', params) # Parse the response XML doc = minidom.parseString(content) # List the Regions nodes = doc.getElementsByTagName('media') for node in nodes: mediaId = str(node.attributes['mediaid'].value) mediaType = str(node.attributes['mediatype'].value) mediaDuration = str(node.attributes['mediaduration'].value) print "Media ID %s" % mediaId print " Type: %s" % mediaType print " Duration: %s\n" % mediaDuration print "Media List Complete\n\n"

- Now save ReplaceMedia.py and run it:

Media ID 11 Type: video Duration: 0 Media List Complete

- See the video that’s already in the region listed.
- Hopefully that’s given a basic overview of how to navigate the API, how to pass in parameters etc. Now we’ll remove most of the code we’ve written and get on with the job in hand of scripting the file upload and replacing that video in the region. We need to remember it’s Layout ID 5, region 5303e4c0c0973 (or the correct values from your CMS). That’s how we’ll identify where we want our video to end up being added, and the old video to delete.
- So now your ReplaceVideo.py should look like this:

# !/usr/bin/python # -*- coding: utf-8 -*- # # Script to upload a Video to the Xibo CMS and replace # an old copy of it in a region # Imports import os from xml.dom import minidom import XiboAPI api = XiboAPI.XiboAPI() layoutId = 5 regionId = '5303e4c0c0973' fileToUpload = 'myVideo.mp4' mediaName = 'Daily Video'

- Clearly set layoutId and regionId to the correct values we obtained earlier. Change fileToUpload to be the filename of the video you want to upload. It could be in the same directory as your script (in which case just the name is sufficient), or it could be a full path to the file. It’s up to you.
- I’ve included some library functions to do the heavy lifting for you. Add the following to the file and save:

################################# # START LIBRARY FUNCTIONS ################################# def uploadFile(api,path,chunksize=256000,fileid='0',offset=0,size=0): # Uploads file at path (full path) # Returns a file upload ID which can be used to add the media # to the library # # eg uploadFile(api,'/home/user/1.jpg') # # Optional Parameters: # chunksize - Int: How many bytes to upload at each pass # fileid - String: The fileUploadID to use. Useful if you're resuming an interupted upload. # offset - Long: How many bytes to skip over before beginning upload. Useful for resuming an interupted upload. # size - Long: How many bytes to upload. 0 = the whole file. Useful to break an upload part way through for testing. # Must be smaller than the size of the file in bytes. # First check the test file exists if not os.path.isfile(path): print "Error: File does not exist %s " % path exit(1) checksum = '' data = '' if size == 0: size = os.path.getsize(path) chunkOK = False # If the file is smaller than the chunksize, send one chunk # of the correct size. if chunksize > size: chunksize = size # Open the file for binary read fh = open(path,'rb') while offset size: chunksize = size - offset # All chunks uploaded # Close the file handle fh.close() return fileid def layoutRegionMediaDelete(api,layoutid,regionid,mediaid,lkid): params = [('mediaId',mediaid), ('regionId',regionid), ('layoutId',int(layoutid)), ('lkId',int(lkid)) ] response, status, code, message, content = api.callMethod('LayoutRegionMediaDelete', params) def libraryMediaDelete(api,mediaid): params = [('mediaId',mediaid)] response, status, code, message, content = api.callMethod('LibraryMediaDelete', params) ############################################# # END LIBRARY FUNCTIONS #############################################

- So first up we upload the new file to the CMS. Note here that by upload we mean copy it to the server ready to be added to the library. We add it to the library in a second stage later on. Add the following to upload:

# Upload our file to the CMS so it's ready to add # Note this won't make it appear in the library # We do that further down the script uploadId = uploadFile(api,fileToUpload)

- Next we need to find the ID of the old video file, remove it from the Region Timeline, and then delete it from the library. Add the following:

# Find out what the mediaID of the old video is, and remove it from the layout oldMediaId = None params = [('layoutid', layoutId), ('regionid', regionId)] # Call the RegionList Method response, status, code, message, content = api.callMethod('LayoutRegionTimelineList', params) # Parse the response XML doc = minidom.parseString(content) # List the Regions nodes = doc.getElementsByTagName('media') for node in nodes: if str(node.attributes['mediatype'].value) == 'video': oldMediaId = str(node.attributes['mediaid'].value) lkid = str(node.attributes['lkid'].value) if not oldMediaId is None: # We found an old video in the region # Lets delete it print "Removing old media with ID %s" % oldMediaId layoutRegionMediaDelete(api, layoutId, regionId, oldMediaId, lkid) libraryMediaDelete(api, oldMediaId)

- Now the old video is gone from the layout timeline, and from the CMS Library, we can add our new video to the library and add it to the region. Add the following:

# Now the file is uploaded, and the old file is deleted, # we need to add the newly uploaded file to the CMS Library params = [('fileId', uploadId), ('type', 'video'), ('name', mediaName), ('duration', '0'), ('permissionId','1'), ('fileName',os.path.basename(fileToUpload)) ] response, status, code, message, content = api.callMethod('LibraryMediaAdd', params) # Get the ID of the file we just added mediaId = api.parseID(content,'media') # Now mediaID contains the library media ID of our freshly uploaded video print "Adding new media with ID %s" % mediaId # Now add our new media item to the region params = [('layoutId',layoutId), ('regionId',regionId), ('mediaList',mediaId), ] response, status, code, message, content = api.callMethod('LayoutRegionLibraryAdd', params)

- Finally check that the video was added correctly by listing the media items in the region. Add the following:

# Finally Check the layout now contains the new video # by listing the contents of the region and checking for our new video params = [('layoutId', layoutId), ('regionId', regionId)] # Call the RegionList Method response, status, code, message, content = api.callMethod('LayoutRegionTimelineList', params) # Parse the response XML doc = minidom.parseString(content) # List the Regions nodes = doc.getElementsByTagName('media') for node in nodes: if str(node.attributes['mediatype'].value) == 'video': if str(node.attributes['mediaid'].value) == str(mediaId): print "Video Uploaded and Layout Modified Successfully" exit(0) print "Error Uploading Video"

- Now save and run your file. You should see output as follows:

alex@alex-laptop:~/scratch/xibo-release/ReplaceVideo$ python ReplaceVideo.py Removing old media with ID 15 Adding new media with ID 16 Video Uploaded and Layout Modified Successfully

- You can now use cron or Windows Task Scheduler to run that script on a schedule and have your content update in Xibo automatically.
- There’s an API reference showing all the API calls currently available in the manual here: [http://xibo.org.uk/manual/index.php?toc=developer_api&p=admin/api_overview](http://xibo.org.uk/manual/index.php?toc=developer_api&p=admin/api_overview)

You can download the completed [ReplaceVideo.py](https://xibosignage.com/wp-content/uploads/2014/02/ReplaceVideo.py) file here.

[View full post](https://xibosignage.com/blog/scripting-xibo-content-management-a-brief-tour-of-the-api)

```json
{
  "@context" : "http://schema.org",
  "@type" : "BlogPosting",
  "author" : {
    "@type" : "Person",
    "name" : "Alex"
  },
  "dateModified" : "2025-11-26T15:17:35.345Z",
  "datePublished" : "2014-02-19T00:00:00Z",
  "headline" : "Scripting Xibo Content Management - A brief tour of the API",
  "image" : {
    "@type" : "ImageObject",
    "height" : 60,
    "url" : "/hs/hsstatic/content_shared_assets/static-1.4092/img/default-amp-logo.png",
    "width" : 60
  },
  "mainEntityOfPage" : "https://xibosignage.com/blog/scripting-xibo-content-management-a-brief-tour-of-the-api",
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject",
      "height" : 60,
      "url" : "/hs/hsstatic/content_shared_assets/static-1.4092/img/default-amp-logo.png",
      "width" : 60
    },
    "name" : "Blog"
  }
}
```