Quru Image Server provides a web-based Application Programming Interface (API) so that software developers can integrate QIS into their own web sites and imaging solutions.
The API consists a number of HTTP RESTful web services, most of which return data in the JSON format.
Features labelled with the icon are only available in the Premium Edition, they are ignored in the Basic Edition.
- About JSON
- Using the API
- Public image services
- Public portfolio access
- Public web services
- Protected web services
- Administration web services
- image data - manage image metadata
- image templates - manage image templates
- users - manage user accounts
- groups - manage groups and system permissions
- group membership - manage group members
- folder permissions - manage access permissions
- disk files - manage the file system
- disk folders - manage the file system
- system tasks - run background tasks
JavaScript Object Notation (JSON) is a lightweight format used for exchanging data. Despite being based on a small subset of JavaScript, JSON is language independent, and is typically smaller and simpler to use than alternative data formats such as XML.
JSON handling libraries are available for almost all common programming languages in use today, including Java, C, C#, PHP, Python, Ruby, Perl, and so on.
Importantly for web applications, JSON data can be retrieved and converted directly into JavaScript objects from within the web browser. Native support for the encoding and decoding of JSON data is built into all modern web browsers, and can be emulated in older web browsers that support JavaScript. In addition, most of the common JavaScript frameworks such as jQuery provide a simple means of calling JSON web services via XHR (also known as Ajax).
The following JavaScript snippet illustrates how to call a public API function (without a login) from a web page:
// URL of the API function
var url = 'https://images.example.com/api/v1/list/';
// GET, POST, PUT, or DELETE (as supported by the API call)
var method = 'GET';
// Query parameters for GET requests
var params = '?path=myfolder';
// Initiate a new request
var request = new XMLHttpRequest();
request.open(method, url + params, true);
// Callback function on success
request.onload = function() {
alert('Successfully returned with status code ' + request.status);
var resp = JSON.parse(request.responseText);
alert('The folder contains ' + resp.data.length + ' images');
};
// Callback function on error
request.onerror = function() {
alert('The request failed with status code ' + request.status);
};
request.send();
To call a protected API function or to retrieve a non-public image, you must first either log in to the image server at https://images.example.com/login/ or obtain an API token. Obtain a token on the server side so that the username and password never leave the server, then pass the token through to where it is needed. If you embed the token into a web page, use HTTPS to serve the page so that the token remains private.
Then to call a protected API function:
// URL of the API function
var url = 'https://images.example.com/api/v1/admin/filesystem/folders/';
// GET, POST, PUT, or DELETE (as supported by the API call)
var method = 'POST';
// Initiate a new request
var request = new XMLHttpRequest();
request.open(method, url, true);
// Form data for POST, PUT requests
var data = 'path=/my-new-folder';
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8');
// Authentication token - call the "token" API function from your application, then pass it through to the web page
var token = 'abcdef0123456789abcdef0123456789';
request.setRequestHeader("Authorization", "Basic " + btoa(token + ":"));
// Callback function on success
request.onload = function() {
var resp = JSON.parse(request.responseText);
alert('Folder created successfully with ID ' + resp.data.id);
};
// Callback function on error
request.onerror = function() {
alert('Folder creation failed with status code ' + request.status);
};
request.send(data);
To log in as if the user has been through https://images.example.com/login/
,
but without displaying the page and performing the login process manually, you
can convert an API token into a web session.
curl is a popular command line utility that allows you to make HTTP calls without a web browser. It is available for all common operating systems, and allows you to create useful scripts and quickly test individual functions.
This document will also use curl for most of its examples. In these, the $
represents
the command line prompt, and is not to be typed. The curl equivalent of the first
JavaScript example above is:
$ curl 'https://images.example.com/api/v1/list/?path=myfolder'
This displays the raw JSON text returned by the server, but does not check the values or process them.
The curl equivalent of the second JavaScript example is:
$ export AUTH_TOKEN=abcdef0123456789abcdef0123456789
$ curl -X POST -u $AUTH_TOKEN: -F 'path=/my-new-folder' 'https://images.example.com/api/v1/admin/filesystem/folders/'
The following types of method are supported in general. See the rest of the documentation for which methods are supported by which API calls.
Method | Meaning |
GET | List available objects, or get an existing object |
POST | Create and return a new object |
PUT | Update an existing object |
DELETE | Delete an object |
For the GET
method, some functions support parameters which should be sent as
"query string" parameters on the end of the URL.
For the PUT
and POST
methods, data fields should be sent using standard HTML
form encoding (application/x-www-form-urlencoded
). An exception to this is if
you are performing a file upload, in which case multipart/form-data
encoding
is required.
Using form encoding to PUT/POST API data is unusual these days, with most modern
APIs preferring JSON inputs to match JSON outputs. Back in 2011 this choice was
made so that the image server API could be invoked directly from a standard HTML
form. A future release may add support for JSON-encoded data, but even in back-end
code it is simple to form-encode data using a library such as libcurl
or
python-requests.
Every API call returns JSON text containing the requested data within a wrapper object. The wrapper provides a status code and (if relevant) an error message. The following JSON illustrates a successful API call:
{
status: 200,
message: "OK",
data: [1, 2, 3, 4, 5]
}
The data
attribute provides the return value from the API call, with the return
value being different for different functions and methods.
On error, the data
attribute is usually set to null
.
In the sample JavaScript code above, the line var resp = JSON.parse(request.responseText);
converts the returned JSON text into a JavaScript object, making it available in
the variable resp
. The code is then able to access the results of the function
as resp.status
, resp.message
and resp.data
.
Because the API functions are called using HTTP, in addition to the status code returned in the JSON there is also an HTTP status code associated with the whole response. At present these status codes are set to the same value and you can check either one. In keeping with HTTP standards, status codes beginning with 2xx indicate success, those beginning 4xx indicate a problem with the client's request, and those beginning 5xx indicate a problem on the server side.
The following status codes may be returned:
Status | Meaning |
200 | Success, complete |
202 | Success, but the function is continuing in the background |
400 | A parameter to the function was missing or invalid |
401 | The client must be logged in to use the function |
403 | The client does not have permission to perform the requested action |
404 | The requested object, path or image does not exist |
405 | The requested method (GET, POST, etc) is not supported |
409 | The item already exists |
415 | The requested image is invalid or unsupported |
500 | Some other error occurred (check the server log files) |
503 | The server is too busy (wait a short time and try again) |
When you need to display private images within an HTML page in a web browser:
<img src="https://images.example.com/image?src=some-private-folder/myfile.jpg">
Or when working with an HTTP client that supports cookies, it is more convenient to log into QIS and obtain a web session cookie so that an API token does not need to be provided with every request.
Web browser security restrictions dictate that your application on one domain name cannot create a session cookie for QIS on a different domain name. Therefore the session cookie must come from QIS itself. There are 2 options...
To have the user log in to QIS manually, your application can navigate to the QIS login page and specify a different URL to return to upon success:
https://images.example.com/login/?next=https://your.application/
This method is simple but has obvious drawbacks in terms of the user experience.
To log the user in seamlessly, you must first obtain an API token. This can be done within your application on the server side so that the token is pre-generated in advance of being required. Then in your web application, as part of the login process, issue a redirect to:
https://images.example.com/api/v1/tokenlogin/?token=YOUR-API-TOKEN&next=https://your.application/
Assuming the value of YOUR-API-TOKEN
is valid (and not expired), the image
server will set its own session cookie in the web browser and then issue its own
redirect back to your application. By default the session will remain valid for
as long as the web browser remains open, so you only need to do this once per
login.
In some web browsers (not supported by Safari at the time of writing) you can achieve the same without redirecting to the image server by include the following hidden HTML in your web page:
<iframe style="display:none" src="https://images.example.com/api/v1/tokenlogin/?token=YOUR-API-TOKEN" width="10" height="10" sandbox></iframe>
Though note that the iframe
content needs to have loaded before you try to
request any private images or call the QIS API.
This "hidden iframe" technique falls foul of Safari's default policy of blocking "3rd party cookies". This policy can be relaxed in Safari's settings, and also does not apply if the user has previously visited the image server directly.
These services return binary image data without a JSON wrapper, and provide the
main way of accessing the images in the image library. They can be used directly
in HTML (with img
or picture
tags) or from JavaScript (with XHR or fetch
requests),
or can form part of a back-end workflow using any language or library that supports
HTTP requests.
For publicly accessible images, these services can be called from any anonymous HTTP client. For images with a folder permission in place, either an API token or a QIS web session) is required. The returned status codes are the same as those defined above for the JSON web services.
Creates and retrieves (as binary data) a processed image, based on the requested template and imaging parameters. If no template is specified, the image will have the system's default template applied to it. See the imaging guide for the full documentation and list of available parameters.
/image
GET
src
- Mandatory, text - Specifies the image path to retrieve[any]
- Optional, mixed - See the imaging guide for all other parameters
- View permission for the folder containing the image
- If no authentication token has been provided, the image's folder must be publicly accessible
Binary image data, with a content type that is determined by the image format requested (or otherwise the default image format). On error, returns a non-200 status code and HTML text containing an error message.
Convert the file myfile.jpg
to a png
thumbnail and save it to disk:
$ curl -o myfile.png 'https://images.example.com/image?src=myfolder/myfile.jpg&width=200&format=png'
Retrieves an original, unmodified image file as binary data. See the imaging guide for the full documentation and list of available parameters.
/original
GET
src
- Mandatory, text - Specifies the image path to retrieve[any]
- Optional, mixed - See the imaging guide for all other parameters
- Download permission for the folder containing the image
- If no authentication token has been provided, the image's folder must have public download permission
Binary image data, with a content type that is determined by the file's image format. On error, returns a non-200 status code and HTML text containing an error message.
Download the original copy of myfile.jpg
and save it to disk:
$ curl -o myfile.jpg 'https://images.example.com/original?src=myfolder/myfile.jpg'
These services provide the main way of viewing or downloading an image portfolio, returning a web page or a plain zip file without a JSON wrapper. For publicly accessible portfolios, the URLs can be used directly in web pages, emails, instant messages, or link sharing services.
For non-public portfolios, either an API token or a QIS web session is required. The returned status codes are the same as those defined above for the JSON web services.
Views a portfolio of images as a web page. To view the portfolio as JSON data, instead use the portfolio details API function. If the caller is not logged in, the portfolio must be publicly viewable.
/portfolios/[portfolio friendly id]/
GET
- None
- View permission for the portfolio
A web page as HTML text. On error, returns a non-200 status code and HTML text containing an error message.
In a web browser, open:
https://images.example.com/portfolios/the-spring-collection/
Downloads a portfolio as a zip file. The portfolio must already have been published by its author in order to create the zip file; see the portfolio publishing API function for how to do this. If the caller is not logged in, the portfolio must be publicly downloadable.
/portfolios/[portfolio friendly id]/downloads/[zip filename].zip
GET
- None
- Download permission for the portfolio
A binary zip file, with content type application/zip
.
On error, returns a non-200 status code and HTML text containing an error message.
$ curl -o myfile.zip 'https://images.example.com/portfolios/the-spring-collection/downloads/a13d7382f1124b59b62618dd4df154ba.zip'
For publicly accessible images and portfolios, these web services can be called from an anonymous (not logged in) session without requiring an authentication token. For images with a folder permission in place or for non-public portfolios, a token or a QIS web session is required however.
Retrieves the ordered list of the files within a folder path, returning the filename, whether the file is a supported image type, and if so, a URL to display the image, and optionally some additional image attributes. For unsupported file types, the image URL and all other image attributes will be zero or empty.
To avoid performance issues, this function returns a maximum of 1,000 results.
To read the full set of results you can use the start
and limit
parameters
to implement paging. The end of the results list is reached when you get back
less than limit
results.
/api/v1/list/
GET
path
- Mandatory, text - Specifies the folder path to listattributes
- Optional, boolean - Whentrue
, adds all the image fields from the image database to the returned objects. Set tofalse
for improved performance if these fields are not required.start
- Optional, integer - The zero-based result number to start from, default0
.limit
- Optional, integer - The maximum number of results to return, default1000
, and maximum value1000
.[any]
- Optional, mixed - Any additional parameters are appended to the returned image URLs so that for example the required image sizes can be specified.
- View permission for the requested folder path
- If no authentication token has been provided, the folder must be publicly accessible
An array of 0 or more objects in alphabetical order of filename.
If the array length equals limit
, you can get the next page of results by making
a second call with the start
parameter set.
List the first 3 files in myfolder
:
$ curl 'https://images.example.com/api/v1/list/?path=myfolder&limit=3'
{
"data": [
{
"filename": "image1.jpg",
"supported": true,
"url": "https://images.example.com/image?src=myfolder/image1.jpg"
},
{
"filename": "image2.jpg",
"supported": true,
"url": "https://images.example.com/image?src=myfolder/image2.jpg"
},
{
"filename": "image3.jpg",
"supported": true,
"url": "https://images.example.com/image?src=myfolder/image3.jpg"
}
],
"message": "OK",
"status": 200
}
List the next 2 files in myfolder
:
$ curl 'https://images.example.com/api/v1/list/?path=myfolder&start=3&limit=2'
{
"data": [
{
"filename": "image4.jpg",
"supported": true,
"url": "https://images.example.com/image?src=myfolder/image4.jpg"
},
{
"filename": "misplaced.docx",
"supported": false,
"url": ""
}
],
"message": "OK",
"status": 200
}
List the files in myfolder
with all image fields, and apply the Thumbnail
template inside the returned url
for each image:
$ curl 'https://images.example.com/api/v1/list/?path=myfolder&attributes=1&tmp=Thumbnail'
{
"data": [
{
"description": "",
"download": true,
"filename": "image1.jpg",
"folder": {
"id": 23,
"name": "/myfolder",
"parent_id": 1,
"path": "/myfolder",
"status": 1
},
"folder_id": 23,
"height": 2448,
"id": 114,
"src": "myfolder/image1.jpg",
"status": 1,
"supported": true,
"title": "",
"url": "https://images.example.com/image?tmp=Thumbnail&src=myfolder/image1.jpg",
"width": 3264
},
{
"description": "",
"download": true,
"filename": "image2.jpg",
"folder": {
"id": 23,
"name": "/myfolder",
"parent_id": 1,
"path": "/myfolder",
"status": 1
},
"folder_id": 23,
"height": 2171,
"id": 116,
"src": "myfolder/image2.jpg",
"status": 1,
"supported": true,
"title": "",
"url": "https://images.example.com/image?tmp=Thumbnail&src=myfolder/image2.jpg",
"width": 3264
},
{
"description": "",
"download": true,
"filename": "image3.jpg",
"folder": {
"id": 23,
"name": "/myfolder",
"parent_id": 1,
"path": "/myfolder",
"status": 1
},
"folder_id": 23,
"height": 2448,
"id": 119,
"src": "myfolder/image3.jpg",
"status": 1,
"supported": true,
"title": "",
"url": "https://images.example.com/image?tmp=Thumbnail&src=myfolder/image3.jpg",
"width": 3264
}
],
"message": "OK",
"status": 200
}
Retrieves the attributes of a single image from its path.
/api/v1/details/
GET
src
- Mandatory, text - The folder and filename of an image
- View permission for the folder that the image resides in
- If no authentication token has been provided, the folder must be publicly accessible
An object containing image attributes, as shown below.
$ curl 'https://images.example.com/api/v1/details/?src=myfolder/image1.jpg'
{
"data": {
"description": "",
"download": true,
"filename": "image1.jpg",
"folder": {
"id": 23,
"name": "/myfolder",
"parent_id": 1,
"path": "/myfolder",
"status": 1
},
"folder_id": 23,
"height": 2448,
"id": 114,
"src": "myfolder/image1.jpg",
"status": 1,
"supported": true,
"title": "",
"url": "https://images.example.com/image?src=myfolder/image1.jpg",
"width": 3264
},
"message": "OK",
"status": 200
}
Returns the list of portfolios that are allowed to be viewed by the caller.
Log in as a user with admin_folios
permission enabled (in one of the user's
groups) to see the list of all portfolios. The returned portfolio objects do
not include image information but do include a URL for viewing the portfolio.
/api/v1/portfolios/
GET
- None
- None, but the results are filtered by portfolios that the caller can view
An array of 0 or more objects ordered by portfolio name.
List all portfolios viewable by the current user:
$ curl 'https://images.example.com/api/v1/portfolios/'
{
"data": [
{
"description": "The admin user's favourite photos",
"downloads": [],
"human_id": "408eb84f7cb41a8b",
"id": 2,
"last_updated": "2018-03-09T16:54:51.662994Z",
"name": "Admin favourites",
"owner_id": 1,
"permissions": [
{
"access": 10,
"folio_id": 2,
"group_id": 1,
"id": 3
},
{
"access": 10,
"folio_id": 2,
"group_id": 2,
"id": 4
}
],
"url": "https://images.example.com/portfolios/408eb84f7cb41a8b/"
},
{
"description": "The 2018 Spring Collection",
"downloads": [
{
"created": "2018-03-23T12:38:44.264952Z",
"description": "Originals export",
"filename": "a13d7382f1124b59b62618dd4df154ba.zip",
"filesize": 1330490,
"folio_id": 3,
"id": 2,
"keep_until": "2020-01-01T00:00:00Z",
"originals": true,
"parameters": {},
"task_id": null,
"url": "https://images.example.com/portfolios/the-spring-collection/downloads/a13d7382f1124b59b62618dd4df154ba.zip"
}
],
"human_id": "the-spring-collection",
"id": 3,
"last_updated": "2018-03-09T16:39:05.342911Z",
"name": "Spring Collection 2018",
"owner_id": 2,
"permissions": [
{
"access": 10,
"folio_id": 3,
"group_id": 1,
"id": 1
},
{
"access": 10,
"folio_id": 3,
"group_id": 2,
"id": 2
}
],
"url": "https://images.example.com/portfolios/the-spring-collection/"
}
],
"message": "OK",
"status": 200
}
Retrieves the full details of a portfolio, including its ordered image list, audit trail and list of published (and non-expired) zip files available for download.
/api/v1/portfolios/
/api/v1/portfolios/[portfolio id]/
GET
- For
GET
without a numeric portfolio ID (first URL):human_id
- Mandatory, text - The unique "friendly" ID of the portfolio to retrieve
- None for
GET
with a numeric portfolio ID (second URL)
- View permission for the requested portfolio ID
The full portfolio as a JSON object.
Retrieve portfolio with numeric ID 3
:
$ curl 'https://images.example.com/api/v1/portfolios/3/'
{
"data": {
"description": "The 2018 Spring Collection",
"downloads": [
{
"created": "2018-03-23T12:38:44.264952Z",
"description": "Originals export",
"filename": "a13d7382f1124b59b62618dd4df154ba.zip",
"filesize": 1330490,
"folio_id": 3,
"id": 2,
"keep_until": "2020-01-01T00:00:00Z",
"originals": true,
"parameters": {},
"task_id": null,
"url": "https://images.example.com/portfolios/the-spring-collection/downloads/a13d7382f1124b59b62618dd4df154ba.zip"
}
],
"history": [
{
"action": 1,
"action_info": "",
"action_time": "2018-03-23T12:13:52.214960Z",
"folio_id": 3,
"id": 4,
"user_id": 3
},
{
"action": 3,
"action_info": "products/p1-bags-a0001.jpg added",
"action_time": "2018-03-23T12:24:27.452216Z",
"folio_id": 3,
"id": 5,
"user_id": 3
},
{
"action": 3,
"action_info": "products/p1-bags-a0002.jpg added",
"action_time": "2018-03-23T12:29:22.849761Z",
"folio_id": 3,
"id": 6,
"user_id": 3
},
{
"action": 3,
"action_info": "products/p1-bags-a0003.jpg added",
"action_time": "2018-03-23T12:29:30.137174Z",
"folio_id": 3,
"id": 7,
"user_id": 3
},
{
"action": 3,
"action_info": "products/p1-bags-a0002.jpg moved to position 3",
"action_time": "2018-03-23T12:32:50.556061Z",
"folio_id": 3,
"id": 8,
"user_id": 3
},
{
"action": 4,
"action_info": "Originals export (expires Wed Jan 1 00:00:00 2020 UTC, images are unmodified originals)",
"action_time": "2018-03-23T12:38:44.265397Z",
"folio_id": 3,
"id": 9,
"user_id": 3
}
],
"human_id": "the-spring-collection",
"id": 3,
"images": [
{
"filename": "",
"folio_id": 3,
"id": 5,
"image": {
"description": "",
"download": true,
"filename": "p1-bags-a0001.jpg",
"folder": {
"id": 15,
"name": "/products",
"parent_id": 1,
"path": "/products",
"status": 1
},
"folder_id": 15,
"height": 1754,
"id": 85,
"src": "products/p1-bags-a0001.jpg",
"status": 1,
"supported": true,
"title": "",
"url": "https://images.example.com/image?src=products/p1-bags-a0001.jpg",
"width": 1239
},
"image_id": 85,
"order_num": 0,
"parameters": {},
"url": "https://images.example.com/image?src=products/p1-bags-a0001.jpg"
},
{
"filename": "",
"folio_id": 3,
"id": 7,
"image": {
"description": "",
"download": true,
"filename": "p1-bags-a0003.jpg",
"folder": {
"id": 15,
"name": "/products",
"parent_id": 1,
"path": "/products",
"status": 1
},
"folder_id": 15,
"height": 1754,
"id": 86,
"src": "products/p1-bags-a0003.jpg",
"status": 1,
"supported": true,
"title": "",
"url": "https://images.example.com/image?src=products/p1-bags-a0003.jpg",
"width": 1239
},
"image_id": 86,
"order_num": 1,
"parameters": {},
"url": "https://images.example.com/image?src=products/p1-bags-a0003.jpg"
},
{
"filename": "",
"folio_id": 3,
"id": 6,
"image": {
"description": "",
"download": true,
"filename": "p1-bags-a0002.jpg",
"folder": {
"id": 15,
"name": "/products",
"parent_id": 1,
"path": "/products",
"status": 1
},
"folder_id": 15,
"height": 1754,
"id": 84,
"src": "products/p1-bags-a0002.jpg",
"status": 1,
"supported": true,
"title": "",
"url": "https://images.example.com/image?src=products/p1-bags-a0002.jpg",
"width": 1239
},
"image_id": 84,
"order_num": 2,
"parameters": {},
"url": "https://images.example.com/image?src=products/p1-bags-a0002.jpg"
}
],
"last_updated": "2018-03-23T12:29:30.137247Z",
"name": "Spring Collection 2018",
"owner_id": 3,
"permissions": [
{
"access": 10,
"folio_id": 3,
"group_id": 2,
"id": 6
},
{
"access": 10,
"folio_id": 3,
"group_id": 1,
"id": 5
}
],
"url": "https://images.example.com/portfolios/the-spring-collection/"
},
"message": "OK",
"status": 200
}
Or to retrieve the same portfolio by its human-readable "friendly" ID:
$ curl 'https://images.example.com/api/v1/portfolios/?human_id=the-spring-collection'
...
All other web services require the caller to be logged in so that permissions can be checked and a username recorded in the audit trail. To log in using the API, obtain an API authentication token and then provide this token along with every function call, or convert it to a web session.
This service returns a unique time-limited token that can be used to call all the other API functions. It is the equivalent of logging in on the QIS web site, and in fact requires the username and password of a valid QIS user.
The advantage of obtaining a token is that the username and password are only required once, and they never need to leave the server side. The token can then be passed through to a less secure area (e.g. a web page) with the username and password never having been revealed. Note that the token must also be treated securely, as anyone who takes a copy of it will then be able to use it to access the API until that token expires. On a web site therefore, use an encrypted HTTPS connection and do not pass around the token where it can be seen (e.g. on the end of a URL).
The token's expiry time is configured by the API_TOKEN_EXPIRY_TIME
system setting.
The default lifetime is 1 hour.
From a web browser or a client that supports cookies, you can convert the token into a cookie-based web session, as if the user had logged in from the image server's login page. See obtaining a web session for more details.
/api/v1/token/
POST
username
- Mandatory, text - The username to authenticate withpassword
- Mandatory, text - The password to authenticate with
These parameters can be supplied either as standard POST
data, or alternatively
using the Basic Authentication
HTTP header instead.
- The username must match an existing QIS user account
- That user account must have the Allow API setting enabled
An object that currently has only one attribute - token
- as a string.
To use the token, call the other API functions using HTTP Basic Authentication with the token as the username value. The password value is unused and can be blank or a dummy value.
Using HTTP basic authentication:
$ curl -X POST -u foo:bar 'https://images.example.com/api/v1/token/'
{
"data": {
"token": "eyJhbGciOiJIUzI1NiIsImZ4cCI6MTQyOTcwNTI4NSwibWF0IjoxNDI5NzAxNjg1fQ.eyJ1c2VyX2lkIj5zfQ.nVdH2Eee8aw2lUamFSz3Wu6CKPl49GrrGz-2LgN791Y"
},
"message": "OK",
"status": 200
}
Or using POST data fields:
$ curl -X POST -F 'username=foo' -F 'password=bar' 'https://images.example.com/api/v1/token/'
{
"data": {
"token": "eyJhbGciOiJIUzI1NiIsImlhdCI6MTU0MDkqMjQyMywiZXhwIjoxNTQwOTA2MDIzfQ.eyJ1c2VyX2lkIjozfQ.IM44WKhKo98KhMh2FLB5heXI-B9Z_bPZH7mhNog4Rzc"
},
"message": "OK",
"status": 200
}
Uploads one or more image files, optionally replacing any existing files that already exist in the same location.
/api/v1/upload/
POST
files
- Mandatory, binary - One or more files to uploadpath
- Optional, text - The destination folder path, when not usingpath_index
. This folder path must already exist. If permitted, you can use the disk folder API to find or create a folder path.path_index
- Optional, integer - The destination folder path as an index (starting from 0) into theIMAGE_UPLOAD_DIRS
list in the system settings. These pre-defined locations are considered to be trusted, and for all users the folder will be created if it does not already exist.overwrite
- Mandatory, text/boolean - The action to take when a file already exists with the same name in the destination folder:yes
(ortrue
or1
) - Overwrite the existing file with the new oneno
(orfalse
or0
) - Return a file already exists error and do not overwrite itrename
- Rename the new file so that it can be saved, leaving the existing file unchanged
One of either path
or path_index
is required.
As is standard for file upload forms on the web, the parameter data must be
multipart/form-data
encoded.
- Upload permission for the destination folder
An key/value object containing one entry for every uploaded file, where each key is the original filename and each value is either success data or an error object. Success data is in the same format returned by the image details function. The error object contains the same data as the standard API error response.
Note that for each uploaded file, the returned filename may be different from the original
filename. This happens when you upload with overwrite=rename
and a file already exists,
when 2 files are uploaded with the same filename (e.g. coming from different directories),
or when the original filename contains dangerous or unsupported characters. By default,
unicode letters and numbers are allowed, but not unicode symbols. If you do not want to
allow unicode filenames at all, you can have them converted to their simplest form (that
is ASCII) by adding ALLOW_UNICODE_FILENAMES = False
to your settings file.
If all files are uploaded successfully, the returned status will be OK
.
If one file fails to upload, the function continues to try all the other files, but returns a status of error (describing only the first error that occurred). The data object is returned as described above, so you need to check the entry for each filename to determine which files were uploaded and which failed (and why).
If there is an error with a parameter such that no uploads were even attempted, the
returned data object is null
.
Upload file myimage.jpg
into the test_images
folder, but not if it already exists:
$ curl -X POST -u <token>:unused -F files=@myimage.jpg -F path=test_images -F overwrite=false 'https://images.example.com/api/v1/upload/'
{
"data": {
"myimage.jpg": {
"description": "",
"download": true,
"filename": "myimage.jpg",
"folder": {
"id": 2,
"name": "/test_images",
"parent_id": 1,
"path": "/test_images",
"status": 1
},
"folder_id": 2,
"height": 1951,
"id": 141,
"src": "test_images/myimage.jpg",
"status": 1,
"supported": true,
"title": "",
"url": "https://images.example.com/image?src=test_images/myimage.jpg",
"width": 3000
}
},
"message": "OK",
"status": 200
}
Then running the same command a second time:
$ curl -X POST -u <token>:unused -F files=@myimage.jpg -F path=test_images -F overwrite=false 'https://images.example.com/api/v1/upload/'
{
"data": {
"myimage.jpg": {
"error": {
"data": null,
"message": "The specified item already exists (file path 'test_images/myimage.jpg' already exists)",
"status": 409
}
}
},
"message": "The specified item already exists (file path 'test_images/myimage.jpg' already exists)",
"status": 409
}
Running the same command a third time but with overwrite=rename
:
$ curl -X POST -u <token>:unused -F files=@myimage.jpg -F path=test_images -F overwrite=rename 'https://images.example.com/api/v1/upload/'
{
"data": {
"myimage.jpg": {
"description": "",
"download": true,
"filename": "myimage-001.jpg",
"folder": {
"id": 2,
"name": "/test_images",
"parent_id": 1,
"path": "/test_images",
"status": 1
},
"folder_id": 2,
"height": 1951,
"id": 142,
"src": "test_images/myimage-001.jpg",
"status": 1,
"supported": true,
"title": "",
"url": "https://images.example.com/image?src=test_images/myimage-001.jpg",
"width": 3000
}
},
"message": "OK",
"status": 200
}
Lists viewable portfolios, or gets, creates, updates, or deletes a single portfolio.
A portfolio is a collection of images that can be viewed together, downloaded
together, or transformed together (e.g. resized to the same dimensions, or have
a standard watermark applied). Unlike other objects, portfolios have a concept of
ownership. Any logged in user with the folios
system permission can create a
portfolio and add images to it. They can choose whether the portfolio is visible
only to them, to other logged in users too, or is public. Separately they can
choose the same for who is allowed to download the portfolio as a zip file.
Only the portfolio owner or a user with the admin_folios
system permission can
make changes to the portfolio or publish it as a zip file.
/api/v1/portfolios/
forGET
(list portfolios) andPOST
(create portfolio)/api/v1/portfolios/
forGET
(single portfolio byhuman_id
)/api/v1/portfolios/[portfolio id]/
forGET
,PUT
, andDELETE
GET
POST
PUT
DELETE
- None for
GET
by numeric ID - For
GET
by "friendly" ID:human_id
- Mandatory, text - The unique "friendly" ID to retrieve
human_id
- Optional, text - A unique "friendly" ID that will be used to identify the portfolio in the view and download URLs. If not supplied or left blank a unique ID will be generated for you. Some characters are disallowed (see below).name
- Mandatory, text - A name for the portfoliodescription
- Mandatory, text - A description of the portfoliointernal_access
- Mandatory, integer - The level of access to allow for other logged in users:0
- No access (make the portfolio private)10
- View permission20
- View and download permission
public_access
- Mandatory, integer - The level of access to allow for public (not logged in) users:0
- No access (make the portfolio private)10
- View permission20
- View and download permission
Because it is used inside URLs, the human_id
value is not allowed to contain
any of these characters: % < > & . ? : /
.
- None for
GET
(list portfolios), but the results are filtered by portfolios that the caller can view - Portfolio view permission for
GET
(single portfolio) - The
folios
system permission forPOST
(create portfolio) - Portfolio ownership or the
admin_folios
system permission forPUT
andDELETE
A list of abbreviated portfolio objects (for the list URL), a single portfolio object (for most other URLs), or nothing (after a delete).
If the human_id
parameter is left blank when creating a portfolio, an automatically
generated ID will be present in the returned object. Each portfolio object includes
a URL for viewing the portfolio.
To create a new portfolio:
$ curl -X POST -u <token>:unused -F 'human_id=the-spring-collection' \
-F 'name=Spring Collection 2018' -F 'description=The 2018 Spring Collection' \
-F 'internal_access=10' -F 'public_access=10' \
'https://images.example.com/api/v1/portfolios/'
{
"data": {
"description": "The 2018 Spring Collection",
"downloads": [],
"history": [
{
"action": 1,
"action_info": "",
"action_time": "2018-03-23T12:13:52.214960Z",
"folio_id": 3,
"id": 4,
"user_id": 3
}
],
"human_id": "the-spring-collection",
"id": 3,
"images": [],
"last_updated": "2018-03-23T12:13:52.206066Z",
"name": "Spring Collection 2018",
"owner_id": 3,
"permissions": [
{
"access": 10,
"folio_id": 3,
"group_id": 1,
"id": 5
},
{
"access": 10,
"folio_id": 3,
"group_id": 2,
"id": 6
}
],
"url": "https://images.example.com/portfolios/the-spring-collection/"
},
"message": "OK",
"status": 200
}
To retrieve the portfolio by numeric ID:
$ curl 'https://images.example.com/api/v1/portfolios/3/'
...
Or to retrieve the portfolio by its human-readable "friendly" ID:
$ curl 'https://images.example.com/api/v1/portfolios/?human_id=the-spring-collection'
...
Adds and removes images to and from a portfolio, allows re-ordering of the image list, and optionally sets portfolio-specific image changes.
The image changes apply only in the context of the portfolio, when the portfolio is viewed or downloaded. The feature is intended to allow things like a custom crop to be applied to a single image. If image changes are also requested at the publishing stage, the publishing changes are applied on top of the single image changes.
/api/v1/portfolios/[portfolio id]/images/
forGET
(list images) andPOST
(add image)/api/v1/portfolios/[portfolio id]/images/[image id]/
forGET
,PUT
, andDELETE
/api/v1/portfolios/[portfolio id]/images/[image id]/position/
forPUT
(reorder)
GET
POST
PUT
DELETE
- None
- For reorder
PUT
:index
- Mandatory, integer - the new zero-based index to move the image to
- For add image
POST
:image_id
orimage_src
- Mandatory, integer or text - the unique ID or path (folder and filename) of the image to add into the portfolio
- For add image and change image
POST
andPUT
:filename
- Optional, text - Sets the filename to use for this image when the portfolio is published to a zip file. Supports ASCII characters only due to zip file limitations. Defaults to the image's original filename.index
- Optional, integer - Sets the zero-based numeric list index to insert the image at. Defaults to 0. If all images are at position 0 they are ordered by the time they were added (oldest first, newest last).image_parameters
- Optional, JSON text - A set of field/value-object pairs that define portfolio-specific imaging operations for this image. The JSON format is the same as when defining an image template.
Note that setting the index
parameter during a POST
(add image) or
PUT
(update image) operation will not change the ordering number on other
images in the portfolio. This may result in multiple images being at the same
position, with the order then being determined by which image was added to the
portfolio first. If this order is not what you want, or to ensure that each
image has a unique ordering number, use the explicit /position/
reordering
function.
When using the reordering function, if the value of index
is too high or too
low it will be adjusted, so you can simply pass a large number to implement a
move to end function.
- Portfolio view permission for
GET
- Portfolio ownership or the
admin_folios
system permission forPOST
,PUT
, andDELETE
- Folder view permission for the folder of the image being added for
POST
An ordered list of the images in the portfolio (for the list URL and the reorder URL), a single portfolio-image object (for most other URLs), or nothing (after a delete).
Each portfolio-image object includes a URL for requesting the image that
incorporates the operations given in the image_parameters
parameter (if any).
Add an image to a portfolio:
$ curl -X POST -u <token>:unused -F 'image_id=85' 'https://images.example.com/api/v1/portfolios/3/images/'
{
"data": {
"filename": "",
"folio_id": 3,
"id": 5,
"image": {
"description": "",
"download": true,
"filename": "p1-bags-a0001.jpg",
"folder": {
"id": 15,
"name": "/products",
"parent_id": 1,
"path": "/products",
"status": 1
},
"folder_id": 15,
"height": 1754,
"id": 85,
"src": "products/p1-bags-a0001.jpg",
"status": 1,
"supported": true,
"title": "",
"url": "https://images.example.com/image?src=products/p1-bags-a0001.jpg",
"width": 1239
},
"image_id": 85,
"order_num": 0,
"parameters": {},
"url": "https://images.example.com/image?src=products/p1-bags-a0001.jpg"
},
"message": "OK",
"status": 200
}
Reorder the portfolio by moving image 84
to index 2
(third place because the
index number is 0-based):
$ curl -X PUT -u <token>:unused -F 'index=2' 'https://images.example.com/api/v1/portfolios/3/images/84/position/'
{
"data": [
{
"filename": "",
"folio_id": 3,
"id": 5,
"image": {
"description": "",
"download": true,
"filename": "p1-bags-a0001.jpg",
"folder": {
"id": 15,
"name": "/products",
"parent_id": 1,
"path": "/products",
"status": 1
},
"folder_id": 15,
"height": 1754,
"id": 85,
"src": "products/p1-bags-a0001.jpg",
"status": 1,
"supported": true,
"title": "",
"url": "https://images.example.com/image?src=products/p1-bags-a0001.jpg",
"width": 1239
},
"image_id": 85,
"order_num": 0,
"parameters": {},
"url": "https://images.example.com/image?src=products/p1-bags-a0001.jpg"
},
{
"filename": "",
"folio_id": 3,
"id": 7,
"image": {
"description": "",
"download": true,
"filename": "p1-bags-a0003.jpg",
"folder": {
"id": 15,
"name": "/products",
"parent_id": 1,
"path": "/products",
"status": 1
},
"folder_id": 15,
"height": 1754,
"id": 86,
"src": "products/p1-bags-a0003.jpg",
"status": 1,
"supported": true,
"title": "",
"url": "https://images.example.com/image?src=products/p1-bags-a0003.jpg",
"width": 1239
},
"image_id": 86,
"order_num": 1,
"parameters": {},
"url": "https://images.example.com/image?src=products/p1-bags-a0003.jpg"
},
{
"filename": "",
"folio_id": 3,
"id": 6,
"image": {
"description": "",
"download": true,
"filename": "p1-bags-a0002.jpg",
"folder": {
"id": 15,
"name": "/products",
"parent_id": 1,
"path": "/products",
"status": 1
},
"folder_id": 15,
"height": 1754,
"id": 84,
"src": "products/p1-bags-a0002.jpg",
"status": 1,
"supported": true,
"title": "",
"url": "https://images.example.com/image?src=products/p1-bags-a0002.jpg",
"width": 1239
},
"image_id": 84,
"order_num": 2,
"parameters": {},
"url": "https://images.example.com/image?src=products/p1-bags-a0002.jpg"
}
],
"message": "OK",
"status": 200
}
Creates or deletes a downloadable export of a portfolio as a zip file. A
portfolio may be exported multiple times with different changes applied. For
example a zip of the unmodified original files, a zip of resized images all
saved as jpg
, and a zip with all images having a colour profile applied.
When single image changes have been defined with the content function, the publishing changes (if any) will be applied on top. Note that when the portfolio is exported as unmodified original files, both the publishing changes and any single image changes are ignored.
Once created, a published zip file is not updated. So if images are added,
removed or changed in a portfolio, any existing zip files will become out of
date. If this is a concern, delete the existing exports and re-publish the
portfolio. Anyone attempting to download a deleted zip file will receive a
404 not found
error.
Published zip files also have an expiry date, after which time they will be automatically deleted. For zips that only need to be downloaded once you can set for example a 7 day expiry date. Or to prevent expiry at all, set a 100 year expiry date.
/api/v1/portfolios/[portfolio id]/exports/
forGET
(list exports) andPOST
/api/v1/portfolios/[portfolio id]/exports/[export id]/
forGET
andDELETE
GET
POST
DELETE
- None
description
- Mandatory, text - a description of the export (can be left blank)originals
- Mandatory, boolean - whether to export the original unmodified image files (when true,image_parameters
will be ignored)expiry_time
- Mandatory, text - Date in the formatyyyy-mm-dd
, or a time in the formatyyyy-mm-ddThh:mm:ss
for when the published zip file should be automatically deleted. The time is specified in the UTC time zone and the expiry routine runs hourly.image_parameters
- Optional, JSON text - A set of field/value-object pairs that define any imaging operations required for this export. The JSON format is the same as when defining an image template.
- Portfolio view permission for
GET
- Portfolio ownership or the
admin_folios
system permission forPOST
andDELETE
A list of published zip files for the portfolio (for the list URL), a single portfolio-export object (for most other URLs), or nothing (after a delete).
Zip files are generated as a background task. When creating a new zip file with
the POST
action, status 202
is returned, the filename
and filesize
fields
will be blank, and the task_id
field will be set to a value that can be monitored
with the system tasks API. Once the task has completed, the filename
and filesize
fields will be set, and the task_id
field empty. If the task fails,
the error information can be queried via the system tasks API, where the task
object will contain an exception in the result
field instead of the updated
portfolio-export object.
Each portfolio-export object includes a URL for downloading the zip file. This will be empty at first until the background task to create the zip file has completed.
Attempting to delete a zip file while the background creation task is still in
progress will result in a 503 server busy
error.
Publish the portfolio's original unmodified image files:
$ curl -X POST -u <token>:unused -F 'description=Originals export' \
-F 'originals=1' -F 'expiry_time=2020-01-01' 'https://images.example.com/api/v1/portfolios/3/exports/'
{
"data": {
"created": "2018-03-23T12:38:44.264952Z",
"description": "Originals export",
"filename": "",
"filesize": 0,
"folio_id": 3,
"id": 2,
"keep_until": "2020-01-01T00:00:00Z",
"originals": true,
"parameters": {},
"task_id": 548,
"url": ""
},
"message": "OK task accepted",
"status": 202
}
After the export task has completed, the filename and URL fields are set:
$ curl -u <token>:unused 'https://images.example.com/api/v1/portfolios/3/exports/2/'
{
"data": {
"created": "2018-03-23T12:38:44.264952Z",
"description": "Originals export",
"filename": "a13d7382f1124b59b62618dd4df154ba.zip",
"filesize": 1330490,
"folio_id": 3,
"id": 2,
"keep_until": "2020-01-01T00:00:00Z",
"originals": true,
"parameters": {},
"task_id": null,
"url": "https://images.example.com/portfolios/the-spring-collection/downloads/a13d7382f1124b59b62618dd4df154ba.zip"
},
"message": "OK",
"status": 200
}
Publish the portfolio with all images resized to 500x500:
$ curl -X POST -u <token>:unused -F 'description=500x500 thumbnails' \
-F 'originals=0' -F 'image_parameters={"width":{"value":500}, "height":{"value":500}}' \
-F 'expiry_time=2020-01-01' 'https://images.example.com/api/v1/portfolios/3/exports/'
{
"data": {
"created": "2018-03-26T13:42:40.491120Z",
"description": "500 x 500 thumbnails",
"filename": "",
"filesize": 0,
"folio_id": 3,
"id": 3,
"keep_until": "2020-01-01T00:00:00Z",
"originals": false,
"parameters": {
"height": {
"value": 500
},
"width": {
"value": 500
}
},
"task_id": 590,
"url": ""
},
"message": "OK task accepted",
"status": 202
}
These web services provide file system, user, group, data management, and system maintenance facilities. All require a logged-in web session or an API authentication token to be provided.
Gets or updates image metadata in the image database.
/api/v1/admin/images/[image id]/
GET
PUT
- None
title
- Mandatory, text - the image titledescription
- Mandatory, text - the image description
- View permission for the folder that the image resides in
- Edit permission is required for
PUT
The image's database object.
The image status
field has value 1
for active, or 0
for deleted.
Retrieve image details by image ID:
$ curl -u <token>:unused 'https://images.example.com/api/v1/admin/images/141/'
{
"data": {
"description": "",
"download": true,
"filename": "myimage.jpg",
"folder": {
"id": 2,
"name": "/test_images",
"parent_id": 1,
"path": "/test_images",
"status": 1
},
"folder_id": 2,
"height": 1951,
"id": 141,
"src": "test_images/myimage.jpg",
"status": 1,
"supported": true,
"title": "",
"url": "https://images.example.com/image?src=test_images/myimage.jpg",
"width": 3000
},
"message": "OK",
"status": 200
}
Update the title and description of the image:
$ curl -X PUT -u <token>:unused -F 'title=my sample image' -F 'description=the updated description of my sample image' 'https://images.example.com/api/v1/admin/images/141/'
{
"data": {
"description": "the updated description of my sample image",
"download": true,
"filename": "myimage.jpg",
"folder": {
"id": 2,
"name": "/test_images",
"parent_id": 1,
"path": "/test_images",
"status": 1
},
"folder_id": 2,
"height": 1951,
"id": 141,
"src": "test_images/myimage.jpg",
"status": 1,
"supported": true,
"title": "my sample image",
"url": "https://images.example.com/image?src=test_images/myimage.jpg",
"width": 3000
},
"message": "OK",
"status": 200
}
Lists all image templates, or gets, creates, updates, or deletes a single template.
A template combines a number of imaging operations into a named group, or a preset, as described in the imaging guide.
/api/v1/admin/templates/
forGET
(list templates) andPOST
/api/v1/admin/templates/[template id]/
forGET
,PUT
, andDELETE
GET
POST
PUT
DELETE
- None
name
- Mandatory, text - A unique name for the templatedescription
- Mandatory, text - A description for the templatetemplate
- Mandatory, JSON text - A set of parameter-name/value-object pairs that define the imaging operations to apply. See the examples below for the list of possible parameter names. Operations to be skipped can either have their values set tonull
or simply be omitted from the JSON.
The template JSON can contain any parameter name that is valid in the Premium Edition. When used in the Basic Edition, any unsupported parameters are simply ignored by the imaging engine.
- None for
GET
- Super user for
POST
,PUT
,DELETE
A list of template objects (for the list URL), a single template object (for most other URLs), or nothing (after a delete).
In the template object, the template
field contains image generation
parameter names and values. Note that some parameters are named differently
here than in the image
web interface.
Values are either null
or excluded from the output if the template does not set
them. Existing older templates may also be missing fields that have been added in
more recent versions of the software.
$ curl -u <token>:unused 'https://images.example.com/api/v1/admin/templates/1/'
{
"data": {
"description": "Defines a 200x200 JPG image that would be suitable for use as a thumbnail image on a web site.",
"id": 1,
"name": "SmallJpeg",
"template": {
"align_h": { "value": "C0.5" },
"align_v": { "value": "C0.5" },
"attachment": { "value": false },
"bottom": { "value": null },
"colorspace": { "value": "rgb" },
"crop_fit": { "value": false },
"dpi_x": { "value": null },
"dpi_y": { "value": null },
"expiry_secs": { "value": 604800 },
"fill": { "value": "#ffffff" },
"flip": { "value": "" },
"format": { "value": "jpg" },
"height": { "value": 200 },
"icc_bpc": { "value": false },
"icc_intent": { "value": "" },
"icc_profile": { "value": "" },
"left": { "value": null },
"overlay_opacity": { "value": null },
"overlay_pos": { "value": "" },
"overlay_size": { "value": null },
"overlay_src": { "value": "" },
"page": { "value": null },
"quality": { "value": 80 },
"record_stats": { "value": true },
"right": { "value": null },
"rotation": { "value": null },
"sharpen": { "value": null },
"size_fit": { "value": false },
"strip": { "value": true },
"tile": { "value": null },
"top": { "value": null },
"width": { "value": 200 }
}
},
"message": "OK",
"status": 200
}
Create a new template grey-thumb
that creates 400x400 square greyscale images:
$ curl -X POST -u <token>:unused -F 'name=grey-thumb' \
-F 'description=Defines a greyscale thumbnail with a black fill' \
-F 'template={ "colorspace":{"value":"gray"}, "width":{"value":400}, "height":{"value":400}, "fill":{"value":"black"} }' \
'https://images.example.com/api/v1/admin/templates/'
{
"data": {
"description": "Defines a greyscale thumbnail with a black fill",
"id": 3,
"name": "grey-thumb",
"template": {
"colorspace": { "value": "gray" },
"fill": { "value": "black" },
"height": { "value": 400 },
"width": { "value": 400 }
}
},
"message": "OK",
"status": 200
}
Delete the template that was just created:
$ curl -X DELETE -u <token>:unused 'https://images.example.com/api/v1/admin/templates/3/'
{
"data": null,
"message": "OK",
"status": 200
}
Lists all user accounts, or gets, creates, updates, or deletes a single user account.
/api/v1/admin/users/
forGET
(list users) andPOST
/api/v1/admin/users/[user id]/
forGET
,PUT
, andDELETE
GET
POST
PUT
DELETE
- For
GET
(list users):status
- Optional, integer - A filter for whether to return active and/or deleted users, default1
, with possible values:-1
orany
- return both active and deleted users0
- return only deleted users1
- return only active users (default)
first_name
- Mandatory, text - The user's first namelast_name
- Mandatory, text - The user's last nameemail
- Mandatory, text - The user's email addressusername
- Mandatory, text - A unique username for the accountpassword
- Mandatory forPOST
, optional forPUT
, text - The account passwordauth_type
- Mandatory, integer - Should be set to1
allow_api
- Mandatory, boolean - Whether this account should be allowed to request an API authentication token
- The current user can
GET
andPUT
their own user account - But otherwise user administration permission is required
A list of user objects (for the list users URL), or a single user object
(for all other URLs). The user's status
field has value 1
for active,
or 0
for deleted.
List all active users:
$ curl -u <token>:unused 'https://images.example.com/api/v1/admin/users/'
{
"data": [
{
"allow_api": false,
"auth_type": 1,
"email": "",
"first_name": "Administrator",
"id": 1,
"last_name": "",
"status": 1,
"username": "admin"
},
{
"allow_api": true,
"auth_type": 1,
"email": "",
"first_name": "Matt",
"id": 2,
"last_name": "Fozard",
"status": 1,
"username": "matt"
}
],
"message": "OK",
"status": 200
}
List all deleted users:
$ curl -u <token>:unused 'https://images.example.com/api/v1/admin/users/?status=0'
...
Retrieve a single user:
$ curl -u <token>:unused 'https://images.example.com/api/v1/admin/users/2/'
{
"data": {
"allow_api": true,
"auth_type": 1,
"email": "",
"first_name": "Matt",
"id": 2,
"last_name": "Fozard",
"status": 1,
"username": "matt"
},
"message": "OK",
"status": 200
}
Update user details:
$ curl -X PUT -u <token>:unused -F 'first_name=Matthew' -F 'last_name=Fozard' -F 'username=mattfoo' -F 'email=matt@quru.com' -F 'auth_type=1' -F 'allow_api=true' 'https://images.example.com/api/v1/admin/users/2/'
{
"data": {
"allow_api": true,
"auth_type": 1,
"email": "matt@quru.com",
"first_name": "Matthew",
"id": 2,
"last_name": "Fozard",
"status": 1,
"username": "mattfoo"
},
"message": "OK",
"status": 200
}
Lists all user groups, or gets, creates, updates, or deletes a single group. Groups are used to define the system-wide access permissions for logged in users. The special system group Public defines access permissions for anonymous (not logged in) users. You can use the folder permissions API to define folder-level access controls.
/api/v1/admin/groups/
forGET
(list groups) andPOST
/api/v1/admin/groups/[group id]/
forGET
,PUT
, andDELETE
GET
POST
PUT
DELETE
- None
name
- Mandatory, text - the unique name of the groupdescription
- Mandatory, text - a description of the groupgroup_type
- Mandatory, integer - set to1
for required system groups that must not be deleted, set to2
for normal, user-defined groupsaccess_folios
- Mandatory, boolean - Whether the group allows the creation of portfoliosaccess_reports
- Mandatory, boolean - Whether the group provides access to reportsaccess_admin_users
- Mandatory, boolean - Whether the group provides user administration permission (and basic group administration)access_admin_files
- Mandatory, boolean - Whether the group provides file administration permission (change or delete any file or folder, regardless of folder permissions)access_admin_folios
- Mandatory, boolean - Whether the group provides portfolio administration permission (create, change and delete any user's portfolios)access_admin_permissions
- Mandatory, boolean - Whether the group provides permissions administration (and full group administration)access_admin_all
- Mandatory, boolean - Whether the group provides super user permission (full access to everything)
- User administration permission is required for
GET
, or toPUT
an updated group name or description - Permissions administration permission is additionally required for
POST
orDELETE
, or toPUT
updated permissions flags for a group
A list of group objects (for the list groups URL), a single group object (for most other URLs), or nothing (after a delete).
List all groups:
$ curl -u <token>:unused 'https://images.example.com/api/v1/admin/groups/'
{
"data": [
{
"description": "Provides full administration access",
"group_type": 1,
"id": 3,
"name": "Administrators",
"permissions": {
"admin_all": true,
"admin_files": true,
"admin_folios": true,
"admin_permissions": true,
"admin_users": true,
"folios": true,
"group_id": 3,
"reports": true
}
},
{
"description": "Provides the default access rights for known users",
"group_type": 1,
"id": 2,
"name": "Normal users",
"permissions": {
"admin_all": false,
"admin_files": false,
"admin_folios": false,
"admin_permissions": false,
"admin_users": false,
"folios": false,
"group_id": 2,
"reports": false
}
},
{
"description": "Provides the access rights for unknown users",
"group_type": 1,
"id": 1,
"name": "Public",
"permissions": {
"admin_all": false,
"admin_files": false,
"admin_folios": false,
"admin_permissions": false,
"admin_users": false,
"folios": false,
"group_id": 1,
"reports": false
}
}
],
"message": "OK",
"status": 200
}
Create a new Website editors group that grants access to reports and permission to change or delete all files and folders:
$ curl -X POST -u <token>:unused -F 'name=Website editors' -F 'description=Access to reports and to change any file or folder' -F 'group_type=2' -F 'access_folios=false' -F 'access_reports=true' -F 'access_admin_users=false' -F 'access_admin_files=true' -F 'access_admin_folios=false' -F 'access_admin_permissions=false' -F 'access_admin_all=false' 'https://images.example.com/api/v1/admin/groups/'
{
"data": {
"description": "Access to reports and to change any file or folder",
"group_type": 2,
"id": 7,
"name": "Website editors",
"permissions": {
"admin_all": false,
"admin_files": true,
"admin_folios": false,
"admin_permissions": false,
"admin_users": false,
"folios": false,
"group_id": 7,
"reports": true
},
"users": []
},
"message": "OK",
"status": 200
}
Delete the group that was just created:
$ curl -X DELETE -u <token>:unused 'https://images.example.com/api/v1/admin/groups/7/'
{
"data": null,
"message": "OK",
"status": 200
}
Adds a user to a group or removes a user from a group. Use the groups API to list the members of a group.
/api/v1/admin/groups/[group id]/members/
forPOST
/api/v1/admin/groups/[group id]/members/[user id]/
forDELETE
POST
DELETE
user_id
- Mandatory, integer - The ID of the user to add to the group
- User administration permission is required as a minimum
- Permissions administration permission is additionally required to add a user to a group that itself grants permissions administration or super user
No return value.
List the members of the Web editors group ID 4
:
$ curl -u <token>:unused 'https://images.example.com/api/v1/admin/groups/4/'
{
"data": {
"description": "Those that are editing the web pages and managing the /web directory of this instance",
"group_type": 2,
"id": 4,
"name": "Web editors",
"permissions": {
"admin_all": false,
"admin_files": false,
"admin_folios": false,
"admin_permissions": false,
"admin_users": false,
"folios": true,
"group_id": 4,
"reports": true
},
"users": [
{
"allow_api": false,
"auth_type": 1,
"email": "jc@quru.com",
"first_name": "JC",
"id": 3,
"last_name": "",
"status": 1,
"username": "jc"
},
{
"allow_api": false,
"auth_type": 1,
"email": "",
"first_name": "Jenny",
"id": 2,
"last_name": "Darcs",
"status": 1,
"username": "jenny"
}
]
},
"message": "OK",
"status": 200
}
Remove one of the members from the group:
$ curl -X DELETE -u <token>:unused 'https://images.example.com/api/v1/admin/groups/4/members/2/'
{
"data": null,
"message": "OK",
"status": 200
}
Get the group again, showing the updated member list:
$ curl -u <token>:unused 'https://images.example.com/api/v1/admin/groups/4/'
{
"data": {
"description": "Those that are editing the web pages and managing the /web directory of this instance",
"group_type": 2,
"id": 4,
"name": "Web editors",
"permissions": {
"admin_all": false,
"admin_files": false,
"admin_folios": false,
"admin_permissions": false,
"admin_users": false,
"folios": true,
"group_id": 4,
"reports": true
},
"users": [
{
"allow_api": false,
"auth_type": 1,
"email": "jc@quru.com",
"first_name": "JC",
"id": 3,
"last_name": "",
"status": 1,
"username": "jc"
}
]
},
"message": "OK",
"status": 200
}
Lists all defined folder permissions, or gets, creates, updates, or deletes a single permission for a particular folder and group.
Folder permissions are hierarchical, meaning that if you set a permission for /myfolder
, that
rule will be inherited by /myfolder/subfolder1
, /myfolder/subfolder2
, and so on. Similarly,
the permission you define for the root folder /
acts as the default permission for all other
folders.
The permission record for the root folder /
and the Public group determines whether your
images default to being publicly visible or not.
If a group has file administration permission enabled, this overrides the normal folder permissions and grants members of the group full access to all folders.
/api/v1/admin/permissions/
forGET
(list permissions) andPOST
/api/v1/admin/permissions/[permission id]/
forGET
,PUT
, andDELETE
GET
POST
PUT
DELETE
- None
group_id
- Mandatory, integer - the ID of the group to set a folder permission forfolder_id
- Mandatory, integer - the ID of the folder to set a permission foraccess
- Mandatory, integer - the permission level to set:0
- No access10
- View images20
- View and download images30
- Edit image metadata (plus the above)40
- Upload files to the folder (plus the above)50
- Delete files from the folder (plus the above)60
- Create new sub-folders (plus the above)70
- Delete the entire folder (plus the above)
Note that group_id
and folder_id
are not changed during a PUT
operation.
- Permissions administration
A list of folder permission objects (for the list URL), a single folder permission object (for most other URLs), or nothing (after a delete).
List all defined folder permissions:
$ curl -u <token>:unused 'https://images.example.com/api/v1/admin/permissions/'
{
"data": [
{
"access": 70,
"folder_id": 1,
"group_id": 3,
"id": 3
},
{
"access": 20,
"folder_id": 1,
"group_id": 1,
"id": 1
},
{
"access": 20,
"folder_id": 1,
"group_id": 2,
"id": 2
}
],
"message": "OK",
"status": 200
}
Allow any logged in user to upload images by default:
$ curl -X PUT -u <token>:unused -F 'group_id=2' -F 'folder_id=1' -F 'access=40' 'https://images.example.com/api/v1/admin/permissions/2/'
{
"data": {
"access": 40,
"folder_id": 1,
"group_id": 2,
"id": 2
},
"message": "OK",
"status": 200
}
Moves, renames, or deletes an image file on disk, and updates the associated metadata and audit trail. Use the upload API to create a new file.
/api/v1/admin/filesystem/images/[image id]/
PUT
DELETE
path
- Mandatory, text - the new path and filename for the image file. If the folder path changes, the file will be moved. If only the filename changes, the file will be renamed.
- Either file administration permission or
- For
PUT
when renaming, upload permission for the folder that contains the image - For
PUT
when moving, delete permission for the folder that currently contains the image, and upload permission for the destination folder - For
DELETE
, delete file permission for the folder that contains the image
The image's updated database object.
To move image ID 141
myimage.jpg to the web
folder:
$ curl -X PUT -u <token>:unused -F 'path=/web/myimage.jpg' 'https://images.example.com/api/v1/admin/filesystem/images/141/'
{
"data": {
"description": "the updated description of my sample image",
"download": true,
"filename": "myimage.jpg",
"folder": {
"id": 24,
"name": "/web",
"parent_id": 1,
"path": "/web",
"status": 1
},
"folder_id": 24,
"height": 1951,
"id": 141,
"src": "web/myimage.jpg",
"status": 1,
"supported": true,
"title": "my sample image",
"url": "https://images.example.com/image?src=web/myimage.jpg",
"width": 3000
},
"message": "OK",
"status": 200
}
Then to delete the file:
$ curl -X DELETE -u <token>:unused 'https://images.example.com/api/v1/admin/filesystem/images/141/'
{
"data": {
"description": "the updated description of my sample image",
"download": true,
"filename": "myimage.jpg",
"folder": {
"id": 24,
"name": "/web",
"parent_id": 1,
"path": "/web",
"status": 1
},
"folder_id": 24,
"height": 1951,
"id": 141,
"src": "web/myimage.jpg",
"status": 0,
"supported": true,
"title": "my sample image",
"url": "https://images.example.com/image?src=web/myimage.jpg",
"width": 3000
},
"message": "OK",
"status": 200
}
Finds a folder by path or database ID, also listing its sub-folders. Or creates, moves, renames, or deletes a disk folder (and all the files within), updating the associated metadata.
Moving, renaming or deleting a folder is a recursive operation that also affects all the sub-folders and files it contains, and can therefore take a long time. In the same way note that if you rename a folder, this changes the paths of all the images contained within.
/api/v1/admin/filesystem/folders/
forGET
(by path) andPOST
/api/v1/admin/filesystem/folders/[folder id]/
forGET
,PUT
andDELETE
GET
POST
PUT
DELETE
- For
GET
by path:path
- Mandatory, text - the path of a disk folder to retrieve.
- For
GET
by path or by ID:status
- Optional, integer - A filter for whether to return present and/or deleted sub-folders, default1
, with possible values:-1
orany
- return both present and deleted sub-folders0
- return only deleted sub-folders1
- return only present sub-folders (default)
path
- Mandatory, text - the new path for the disk folder. If the parent part of the folder path changes, the folder will be moved. If only the folder's own name changes, the folder will be renamed.
- Either file administration permission or
- For
GET
, view permission for the requested folder - For
POST
, create sub-folder permission for the nearest existing parent folder - For
PUT
when renaming, create sub-folder permission for the parent folder - For
PUT
when moving, full delete permission for the current parent folder, and create sub-folder permission for the destination parent folder - For
DELETE
, full delete permission for the parent folder
For GET
, returns the folder's database object including one level of sub-folders
in the children
attribute. Each folder's status
field has value 1
for active,
or 0
for deleted.
For POST
, returns the new folder's database object.
For PUT
and DELETE
, if the function completes in less than 30 seconds,
returns the folder's updated database object. If however the function is still
ongoing after 30 seconds, returns status 202
and a task object that you can
track using the system tasks API. The task ID in this case is found
in the returned task object's id
field.
List the sub-folders of the /search/path
folder:
$ curl -u <token>:unused 'https://images.example.com/api/v1/admin/filesystem/folders/?path=/search/path'
{
"data": {
"children": [
{
"id": 49,
"name": "/search/path/child1",
"parent_id": 44,
"path": "/search/path/child1",
"status": 1
},
{
"id": 45,
"name": "/search/path/child2",
"parent_id": 44,
"path": "/search/path/child2",
"status": 1
}
],
"id": 44,
"name": "/search/path",
"parent": {
"id": 42,
"name": "/search",
"parent_id": 1,
"path": "/search",
"status": 1
},
"parent_id": 42,
"path": "/search/path",
"status": 1
},
"message": "OK",
"status": 200
}
Create a new folder /test_images/mynewfolder
:
$ curl -X POST -u <token>:unused -F 'path=/test_images/mynewfolder/' 'https://images.example.com/api/v1/admin/filesystem/folders/'
{
"data": {
"id": 3,
"name": "/test_images/mynewfolder",
"parent_id": 2,
"path": "/test_images/mynewfolder",
"status": 1
},
"message": "OK",
"status": 200
}
Delete the folder that was just created:
$ curl -X DELETE -u <token>:unused 'https://images.example.com/api/v1/admin/filesystem/folders/3/'
{
"data": {
"id": 3,
"name": "/test_images/mynewfolder",
"parent_id": 2,
"path": "/test_images/mynewfolder",
"status": 0
},
"message": "OK",
"status": 200
}
If the operation takes more than 30 seconds, status 202
and an ongoing task
object are returned. In this case the task ID is the object's id
field, so
288
in this example:
$ curl -X PUT -u <token>:unused -F 'path=/renamed-large-folder' 'https://images.example.com/api/v1/admin/filesystem/folders/23/'
{
"data": {
"error_log_level": "error",
"funcname": "move_folder",
"id": 288,
"keep_for": 10,
"keep_until": null,
"lock_id": "6008_1",
"log_level": "info",
"name": "Move disk folder ID 23",
"params": {
"folder_id": 23,
"path": "/renamed-large-folder"
},
"priority": 10,
"result": null,
"status": 1,
"user": {
"allow_api": true,
"auth_type": 1,
"email": "matt@quru.com",
"first_name": "Matt",
"id": 2,
"last_name": "Fozard",
"status": 1,
"username": "matt"
},
"user_id": 2
},
"message": "OK task accepted",
"status": 202
}
Initiates or polls the status of a background task.
/api/v1/admin/tasks/[function name]/
forPOST
/api/v1/admin/tasks/[task id]/
forGET
GET
POST
- None
- These are specific to the task function:
- For function
purge_system_stats
, which physically deletes system-level statistics older than a given date:before_time
- Mandatory, text - Date in format 'yyyy-mm-dd' beyond which the system statistics should be purged
- For function
purge_image_stats
, which physically deletes image-level statistics older than a given date:before_time
- Mandatory, text - Date in format 'yyyy-mm-dd' beyond which the image statistics should be purged
- For function
purge_deleted_folder_data
, which physically deletes image and folder data that are only marked as deleted (this includes archived image audit trails):path
- Mandatory, text - The folder path in which to purge (recursively) the deleted database records. Specify the root folder/
to purge everything.
- For function
- Either super user or
- For
GET
, the user that owns the task
The task object including its status, or null
if the task has completed and
no longer exists.
The following task status values exist:
0
- New, awaiting processing1
- In progress2
- Complete, with the (task dependent) return value inside theresult
attribute
Once complete, a task will remain in the database so that a duplicate task cannot
run again for keep_for
seconds (until keep_until
time UTC is reached).
If keep_for
is 0
(and keep_until
is null
), the task will be deleted within
a few seconds of completion, after which a status 404
will be returned when that
task is requested.
Get the task with ID 301
:
$ curl -u <token>:unused 'https://images.example.com/api/v1/admin/tasks/301/'
{
"data": {
"error_log_level": "error",
"funcname": "purge_deleted_folder_data",
"id": 301,
"keep_for": 0,
"keep_until": null,
"lock_id": null,
"log_level": "info",
"name": "Purge deleted data",
"params": {
"folder_id": 2
},
"priority": 20,
"result": null,
"status": 2,
"user": {
"allow_api": true,
"auth_type": 1,
"email": "matt@quru.com",
"first_name": "Matt",
"id": 2,
"last_name": "Fozard",
"status": 1,
"username": "matt"
},
"user_id": 2
},
"message": "OK",
"status": 200
}
Then trying again after a few seconds:
$ curl -u <token>:unused 'https://images.example.com/api/v1/admin/tasks/301/'
{
"data": null,
"message": "The requested item was not found (301)",
"status": 404
}