Making requests to the TwentyThree API
Requests
The API is based on HTTP, and any request is made to the workspace's api base url, for example https://videos.examples.com/api/2, followed by the API endpoint such as /user/create or /tag/related).
Both GET and POST requests are allowed, but note that the GET-style query string parameters (i.e. /api/tag/related?tag=mytag) are not used on POST requests.
For example, using the tags list method a request could look like this:
https://video.example.com/api/2/tag/list?size=2
And return something like this:
{
"status": "ok",
"permission_level": "anonymous",
"cached": true,
"p": 1,
"size": 20,
"total_count": 6,
"cache_time": 1712310006,
"data": [
{
"tag": "drones",
"count": 2,
"url": "/tag/drones"
},
{
"tag": "open",
"count": 1,
"url": "/tag/open"
}
]
}
The API expects UTF-8 formatted input and will return in UTF-8 as well.
Responses
All responses from the platform come in the form of JSON and will always have a status attribute detailing if the request was ok or error. Success and failure responses will also be reflected in HTTP status codes, for example 200 for successful requests.
Success
{
"status": "ok",
"permission_level": "admin",
"cached": false,
"message": "The user has been created",
"data": {
"user_id": 96584427,
"email": "somebody@twentythree.com",
"username": "somebody",
"full_name": "Somebody Cool",
"site_admin": 0,
"timezone": "Etc/UTC"
}
}
Failure
Whenever a request to the API fails, a response detailing the exception is returned. The response includes an error_code and a detailed error description:
{
"status": "error",
"message": "User already exists",
"code": "user_already_exists",
"permission_level": "admin"
}
JSON-P style responses
Responses are also available as a JSONP-style callback using thecallback parameter. Requesting the same data with https://videos.example.com/api/2/tag/list?size=2&callback=listTags gets you:
/* */
listTags({
"status": "ok",
"permission_level": "anonymous",
"cached": true,
"p": 1,
"size": 2,
"total_count": 37,
"cache_time": 1712310327,
"data": [
{
"tag": 2016,
"count": 1,
"url": "\/tag\/2016"
},
{
"tag": "adventures",
"count": 4,
"url": "\/tag\/adventures"
}
]
});
This is valuable for reading publicly available data across domains in a browser:
<script>
function listTags(o) {
for (i in o.data) {
console.log(o.data[i].tag);
}
}
</script>
<script src="https://videos.example.com/api/2/tag/list?size=2&callback=listTags"></script> Pagination
A number of API methods (including for example /photo/list, /user/list and /tag/list)
returns a list of objects. These lists will often only return a subset
of the data, and the programmer will need to handle pagination
explicitly. This is done using p and size:
size: Number of items to return with each request. Where nothing else is stated, the default value forsizeis 20 and the maximum value is 100.p: The page number to return. The default value is 1 and given a size of 20,p=2will return items 21 through 40, andp=5will yield items 81 through 100.
Any request offering pagination will include the p and size parameters in their responses, and in addition a third property is included:
total_count: The total number of object available through the request.
For example, you might query https://videos.example.com/api/2/album/list?size=2:
{
"status": "ok",
"permission_level": "anonymous",
"cached": true,
"p": 1,
"size": 2,
"total_count": 6,
"cache_time": 1712310527,
"data": [
{
"album_id": 62945245,
"title": "First Category",
...
},
{
"album_id": 62915571,
"title": "Second Category",
...
}
]
}
Based on the response, we know that there are 6 categories distributed along 3 pages. Armed with this information we can make a few additional requests ending with https://videos.example.com/api/2/album/list?size=2&p=3:
{
"status": "ok",
"permission_level": "anonymous",
"cached": true,
"p": 3,
"size": 2,
"total_count": 6,
"cache_time": 1712310600,
"data": [
{
"album_id": 86246876,
"title": "Fifth Category",
...
},
{
"album_id": 61550144,
"title": "Sixth Category",
...
}
]
}