REST/JSON services
Presentation
iTop provides a REST/JSON interface which allows third party applications to remotely interact with iTop for retrieving, creating or updating iTop objects. This interface is based on a set of simple HTTP POST requests. The data passed to and retrieved from iTop are encoded in JSON using the UTF-8 character set.
Such requests can be performed from any programming language capable os issuing HTTP/POSTs and manipulating JSON encoded data. Requests can even be run directly in javascript inside any web page by the mean of cross-site scripting (iTop supports both CORS and JSON-P). An example of such cross-site scripting in javascript is given in the REST JSON Playground.
You can also find the complete documentation on Postman.
The URL to POST the requests looks like:
<itop-root>/webservices/rest.php?version=1.3
Such requests expect the following parameters to be passed:
-
auth_user
-
auth_pwd
-
json_data
In fact, the HTTP method can be either POST or GET (this is needed for JSON-P support). POST and HTTPS are recommended for security reasons (to avoid passing the credentials in clear text) and also because GET imposes a limit on the size of the input data. HTTP Basic authentication is supported.
Who can access it:
REST Services User
.-
As REST web services can easily be put in a loop, users must have
write access
andbulk write
on the classes they modify. Applying a stimulus is a modification. -
Make sure that your scripts using REST web services have
REST Services User
profile. -
Your users with
Administrator
profile won't have access to REST without thisREST Services User
additional profile.
If you want to emulate the previous behavior (i.e. allow any
user to access the REST web services) add the configuration
parameter secure_rest_services
and set it to
false
.
Parameters: Let's have a look at all the parameters of this HTTP service:
Argument | Description | Defaut value |
---|---|---|
version | Version of the API. It is a way to make sure that the targetted iTop server can deliver some functionality, and it ensures stability for your scripts: as long as a version is available, the operations will remain unchanged, with the exception of the following cases: bug fixes, modification in the returned messages, new elements into the returned JSON structure. | - |
auth_user | User login | - |
auth_pwd | User password | - |
json_data | either a string containing the requested operation
in JSON format. or (new in 3.0) @<path> where you provide the JSON operation file with path, for CLI excution |
|
callback | If set, then JSON-P (JSON with padding) is used |
These parameters apply to any type of operation that is requested.
Parameters in a PHP array form
Since 2.7.1 and 3.0.0 parameters can be sent using the PHP array syntax :
auth_user=my_user&auth_pwd=my_password&json_data%5Boperation%5D=core%2Fget&json_data%5Bclass%5D=ServiceChange&json_data%5Bkey%5D=SELECT+ServiceChange+WHERE+id%3D1&json_data%5Boutput_fields%5D=request_state
See PR #99
Parameters in a file
Since 3.0.0, for test, you can write your JSON operation in a file for CLI execution
- my-json-operation.json
-
{ "operation":"core/create", "comment":"Synchronization from blah...", "class":"UserRequest", "output_fields":"id, friendlyname", "fields": { "org_id":"SELECT Organization WHERE name = 'Demo'", "caller_id":{"name":"monet","first_name":"claude"}, "title":"issue blah", "description":"something happened" } }
You can then use the following Curl command to execute this operation on command line interface
curl -X POST -F 'version=1.3' -F 'auth_user=admin' -F 'auth_pwd=admin' http://localhost/itop/webservices/rest.php -F 'json_data=@./my-json-operation.json'
Operation: list_operations
The first operation you should be familiar with is: list_operations. This command returns the list of all possible operations.
The syntax of the json_data input is as simplest as could be:
{ "operation": "list_operations" }
The reply will look like:
{ "version": "1.2", "operations": [ { "verb": "core/create", "description": "Create an object", "extension": "CoreServices" }, { "verb": "core/update", "description": "Update an object", "extension": "CoreServices" }, { "verb": "core/get", "description": "Search for objects", "extension": "CoreServices" } ], "code": 0, "message": "Operations: 3" }
Note that the part:
{ "code": 0, "message": "Everything went well" }
…is common to all the services delivered by rest.php, the other information returned depends on the requested operation.
Error codes
The error codes are available in applicationextension.inc.php, as constants of the class RestResult:
Value | Constant | Meaning |
---|---|---|
0 | OK | No issue has been encountered |
1 | UNAUTHORIZED | Missing/wrong credentials or the user does not have enough rights to perform the requested operation |
2 | MISSING_VERSION | The parameter 'version' is missing |
3 | MISSING_JSON | The parameter 'json_data' is missing |
4 | INVALID_JSON | The input structure is not a valid JSON string |
5 | MISSING_AUTH_USER | The parameter 'auth_user' is missing |
6 | MISSING_AUTH_PWD | The parameter 'auth_pwd' is missing or you are using url login type and it's not allowed on the Configuration file of your iTop |
10 | UNSUPPORTED_VERSION | No operation is available for the specified version |
11 | UNKNOWN_OPERATION | The requested operation is not valid for the specified version |
12 | UNSAFE | The requested operation cannot be performed because it can cause data (integrity) loss |
100 | INTERNAL_ERROR | The operation could not be performed, see the message for troubleshooting |
Core services
The core service are generic services. They are the equivalent of the iTop Core PHP APIs: DBObject, DBObjectSearch and DBObjectSet.
Using this services, you can manipulate any kind of data, provided you know enough of the classes and their attributes.
How to specify a key
A key is a mean to identify an object. This type of specification can be used to determine the target object for the operation, and it used to determine the value of a external key (or “foreign key”).
Three forms are allowed:
-
Specify the id of the object (as a number):
... "key": 123
-
Specify a search query (OQL):
... "key": "SELECT UserRequest WHERE caller_name LIKE \"monnet\""
-
Specify search criteria (all criteria are combined with a AND operator):
... "key": { "name": "Monnet", "first_name": "Claude" }
How to specify a value
The value of an attribute is given in a format which depends on the attribute type.
Here is an example that illustrates some cases:
"name": "Monnet", "first_name": "Claude", "age": 80, "picture": { "data": "iVBORw0KGgoAAAAN.......AAAAElFTkSuQmCC", "filename": "smiley.png", "mimetype": "image/png" }
Scalars
For most of the attribute types, the value is simply a scalar.
For the external keys, the value is a key (see definition above).
For text fields formatted as pure text, new lines are specified by the mean of “\”.
Example:
"name": "Monnet", "description": "A famous french artist.\nLaunched the impressionism trend." "presentation": "<p>A famous french artist</p><p>Launched the <em>impressionism</em> trend.</p>" "age": 80, "org_id": "SELECT Organization WHERE name = 'Demo'", "location_id": 3, "supervisor_id": { "name": "Foo", "first_name": "John" }
Blobs
For Blobs (i.e. binary data), the value is given as an array of three items: data, filename and mimetype.
-
'data' is the binary data that has been base 64 encoded (see PHP/base64_encode)
-
'filename' is the name of the original file. Its purpose is provide a default file name in case the file gets further downloaded.
-
'mimetype' must match the format of the file so that iTop can display it correctly.
Example:
"picture": { "data": "iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAIAAAC0tAIdAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACmSURBVChTfZHRDYMwDESzQ2fqhHx3C3ao+MkW/WlnaFxfzk7sEnE6JHJ+NgaKZN2zLHVN2ssfkae0Da7FQ5PRk/ve4Hcx19Ie6CEGuh/6vMgNhwanHVUNbt73lUDbYJ+6pg8b3+m2RehsVPdMXyvQY+OVkB+Rrv64lUjb3nq+aCA6v4leRqtfaIgimr53atBy9PlfUhoh3fFCNDmErv9FWR6ylBL5AREbmHBnFj5lAAAAAElFTkSuQmCC", "filename": "smiley.png", "mimetype": "image/png" }
Case Log
Since iTop 2.0.3, 3 syntaxes are possible for populating “CaseLog” fields: shorthand syntax, single item or whole log.
Shorthand syntax
If a simple text string is supplied, the text will be added as a new entry in the case log with the current date & time and the current user, and the text will be implicitely considered as formatted in HTML.
Example:
"public_log": "blah blah blah",
Rich syntax
If a structure with an entry named add_item
is
supplied, one can specify additional information:
-
user name (defaults to the credentials used for the REST/JSON API)
-
date/time of the entry (defaults to “now”)
-
format of the comment (defaults to “html”, can be set to “text”)
Example:
"public_log": { "add_item": { "date": "yyyy-mm-dd hh:mm:ss", "user_login": "jfoo", "message": "The first line\nAnother line", "format":"text" } },
Full syntax
If an array named items
is suplied, the whole
content of the case log will be replaced by the supplied
entries.
Example:
"public_log": { "items": [ { "date": "yyyy-mm-dd hh:mm:ss", "user_login": "jfoo", "message": "<p>The first line</p><p>A second line</p>" }, { "date": "yyyy-mm-dd hh:mm:ss", "user_login": "jfoo", "message": "<p>The first line</p><p>A second line</p>", "format": "html" }, { "date": "yyyy-mm-dd hh:mm:ss", "user_login": "jfoo", "message": "blah blah blah", "format": "text" } ] },
Link sets
For link sets, the value is an array of object definitions.
Example:
"contacts_list": [ { "role": "artist", "contact_id": { "finalclass": "Person", "name": "monet", "first_name": "claude" } }, { "role": "Basket-ball", "contact_id": "SELECT Team WHERE name = 'San Antonio Spurs'" }, { "contact_id": 1234 } ]
Response
The format for the response of core/… operations is the following:
{ "objects": { "objectclass::objectkey": { ... } }, "code": 0, "message": "Found: 1" }
Where each object is the form:
{ "code": 0, "message": "", "class": "Person", "key": 1234, "fields": { "id": 1234, "name": "My last name", "status": "Active", "org_id": 123, ..... ..... ..... } }
If no objects are to be returned, you'll get :
"objects": null
The list of attributes given can be controlled by the mean of
the parameter output_fields
(when available). The
parameter output_fields
can have the following
forms:
-
A list of attribute codes separated by a coma (e.g.: “name, status, org_id”). Only attributes of the queried class can be given here.
-
* means all the attributes of the queried class
-
*+ (since 2.0.3) means all the attributes of each object found (subclasses may have more attributes than the queried class)
*+
by
*%2B
, that could do the job.Operation: core/get
Searches for a list of objects.
Example:
Passing the following json_data
:
{ "operation": "core/get", "class": "Person", "key": "SELECT Person WHERE email LIKE '%.com'", "output_fields": "friendlyname, email" }
or, using another form of “key”:
{ "operation": "core/get", "class": "Person", "key": 1, "output_fields": "*" }
*_list
fields in the output_fields
: you
would get all the fields of the linked objects,
including AttributeBlob and linkedset fields !This would probably return more data than you need and cause a memory_limit on the server side.
Since 2.6.1 (PR #25, thanks to Dennis Lassiter !), pagination is handled using two new parameters :
-
limit (int): Amount of results to return (default: 0 = no limit)
-
page (int): Page number to return (cannot be < 1)
Records ordering can be controlled using the classes/class/properties/order datamodel XML node.
Example :
{ "operation": "core/get", "class": "Person", "key": "SELECT Person", "output_fields": "friendlyname, email" "limit": "5", "page": "2" }
If you use an OQL for key you should query the same class, otherwise only the keys of the first returned class will be used to filter the requested class.
Operation: core/create
Creates a new object of the given class
Passing the following json_data
:
{ "operation": "core/create", "comment": "Synchronization from blah...", "class": "UserRequest", "output_fields": "id, friendlyname", "fields": { "org_id": "SELECT Organization WHERE name = \"Demo\"", "caller_id": { "name": "monet", "first_name": "claude" }, "title": "Houston, got a problem!", "description": "The fridge is empty" } }
… will result in a new User Request being created.
Some attributes have a special format:
-
Link sets: only indirect link sets are currently supported, see the example given above
-
Blobs: document contents (e.g. DocumentFile/file) must be in the form
{data: base64-encoded-data, mimetype: …, filename: …}
-
Case logs: three forms are allowed.
-
Passing a string is equivalent to adding a new message from within the GUI: the message is recorded on behalf of the current user (credentials used to invoke the web service).
-
Passing a structure in the form {add_item: {message: 'blah', user_id: 123, date:'2012-02-28 10:30'}} adds a single message too. user_id and date are optionals, defaulting respectively to the current user and the current date and time. Specifying user_id requires that the credentials used to invoke the service have Administrator rights, otherwise the operation would fail with UNAUTHORIZED error code.
-
Passing a structure in the form {items: [ {message: 'blah'} ]} sets the entire log.
-
Example of a response:
{ "code": 0, "message": "", "objects": { "UserRequest::123": { "code": 0, "message": "created", "class": "UserRequest", "key": 29, "fields": { "id": 29, "friendlyname": "R-000029" } } } }
Operation: core/update
Updates one object
Passing the following json_data
:
{ "operation": "core/update", "comment": "Synchronization from blah...", "class": "UserRequest", "key": { "description": "The fridge is empty" }, "output_fields": "friendlyname, title, contacts_list", "fields": { "contacts_list": [ { "role": "pizza delivery", "contact_id": { "finalclass": "Person", "name": "monet", "first_name": "claude" } } ] } }
… will update the User Request (identified by its description “The fridge is empty”) by setting the contact list to one contact (Claude Monet) and the role 'pizza delivery'.
key
specification matches more
than one object the update will fail with the error: Several
items found (xx) for query…
.Operation: core/apply_stimulus
Updates one object and applies a stimulus to change the state of the object
Passing the following json_data
:
{ "operation": "core/apply_stimulus", "comment": "Synchronization from blah...", "class": "UserRequest", "key": 15, "stimulus": "ev_assign", "output_fields": "friendlyname, title, status, contacts_list", "fields": { "team_id": 18, "agent_id": 57 } }
… will update the User Request (identified by its key “15”) by
setting the agent_id
and team_id
fields
(which are mandatory for the state assigned
) and then
will apply the stimulus ev_assign
that causes the
ticket to transition from the state new
to the state
assigned
.
key
specification matches more than one object the update will fail
with the error: Several items found (xx) for
query…
.Operation: core/delete
Delete a set of objects
Passing the following json_data
:
{ "operation": "core/delete", "comment": "Cleanup for customer Demo", "class": "UserRequest", "key": { "org_id": 2 }, "simulate": false }
… will delete User Request of the customer #2.
simulate: true
to
finetune your scriptEach object reported has a deletion status code and a message giving additional information. The status codes are defined in core/restservices.class.inc.php, as constants of the class RestDelete:
Value | Constant | Meaning |
---|---|---|
0 | OK | Object deleted as per the initial request |
1 | ISSUE | General issue (user rights or … ?) |
2 | AUTO_DELETE | Must be deleted to preserve database integrity |
3 | AUTO_DELETE_ISSUE | Must be deleted to preserve database integrity, but that is NOT possible |
4 | REQUEST_EXPLICITELY | Must be deleted to preserve database integrity, but this must be requested explicitely |
5 | AUTO_UPDATE | Must be updated to preserve database integrity |
6 | AUTO_UPDATE_ISSUE | Must be updated to preserve database integrity, but that is NOT possible |
Operation: core/get_related
Searches for related objects.
Given an object or a list of objects, searches for other objects that are impacting or impacted by those objects.
Passing the following json_data
:
{ "operation": "core/get_related", "class": "Server", "key": 1, "relation": "impacts", "depth": 4, "redundancy": true, "direction": "down" }
… will search for all of the CIs that Server::1 does impact. The search depth is limited to 4 iterations (defaults to 20).
The results will be in the form:
{ "objects": { "objectclass::objectkey": { ... } }, "relations": { "origin-class::origin-key": [ { "key": "destination-class::destination-key" } ] }, "code": 0, "message": "Scope: 1; Found: Server=4, VirtualMachine=3, Farm=1" }
Operation: core/check_credentials
Checks a user login + password.
Passing the following json_data
:
{ "operation": "core/check_credentials", "user": "john", "password": "abc123" }
… will reply (if everything went well)…
{ "code": 0, "message": "", "authorized": true }
check_credentials
returns authorized:
false
.Examples and playground
If you have an iTop already installed (version 2.0.1+), then click here to test the REST API.
Here is the corresponding code: jsfiddle playground
Example of how you can integrate REST/JSON calls: using bash and wget
Create User with Profile
When a n:n relationship is required for an object to be created,
then the creation of that object must include the creation of the
link object. It's seldom in the iTop standard Datamodel today, but
it still exist for creating a User object.
The syntax to use is a bit tricky as the userid
cannot be provided for the link creation:
json_data:{
"operation": "core/create",
"comment": "Created",
"class": "UserLocal",
"output_fields": "id",
"fields": {
"contactid": 169,
"login": "MyUser123",
"password": "123456",
"language": "EN US",
"status": "enabled",
"profile_list": [{"profileid": *MyProfileID*}]
}
}
Managing attachment
Managing inline image
How to add services
It is possible to extend the services by developping a module (or extension) that declares a class (included in your custom module) implementing the interface iRestServiceProvider.
As soon as your module is installed, your custom services will
be available and listed with
operation=list_operations
.
Changes history
iTop version | JSON REST version | Changes |
---|---|---|
2.0.1 | 1.0 | Created |
2.0.2 | 1.1 | * Added 'key' to the returned object information
(required some parsing in 1.0), * Turned the object search criteria into a strict search (as opposed to a loose search: contains …), * Allow to reset an external key (set to 0, meaning “undefined”) |
2.0.3 | 1.2 | * Fully handle the case logs (could be entirely
read or written), * Enums/GET giving the raw value not the localized label, * Allow the HTTP basic authentication method, * Added the verb core/check_credentials, * Improved the error reporting (missing authentication arguments, wrong class for writing a link set), * Added the option *+ to output all the fields of the
object (not only the fields of the queried class),* Fixed the report on object deletion |
2.2.0 | 1.3 | * Verb get_related : added the options
redundancy and direction to take into
account the redundancy in the impact analysis.* For security reasons, the use of REST/JSON webservices by user accounts with the profile Portal User is now
disabled. If you use one of the webservices only to check
the credentials of a user, adjust your code to use the
core/check_credentials operation.* For security reasons, the operations core/get and
core/get_related are now only allowed to users having
the bulk read privilege on the specified class of
objects. |
2.5.2, 2.6.1, 2.7.0 | 1.4 | Verb core/get : added pagination parameters limit and page |