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 forsize
is 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=2
will return items 21 through 40, andp=5
will 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", ... } ] }