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 (optional, depending on the login mode)
  • auth_pwd (optional, depending on the login mode)
  • 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.

What can be access:

Any iTop object can be created, read, modified and deleted through this API
Those actions can only be performed on a single object at a time, except read

Who can access it:

The access to the REST web services is restricted to the users having the profile REST Services User.
  • As REST web services can easily be put in a loop, users must have write access and bulk 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 this REST 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.

Authentication

See how to authenticate to a web service to select the relevant authentication mode and adjust the HTTP request accordingly.

Testing the API can be done by the mean of a browser, but in this case you will have to adjust allowed_login_types to enable url within the Configuration file of your iTop.

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 (form login_type must be enabled):

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 “\”.

Starting with iTop 2.3 the ticket description is formatted in HTML. It is possible to alter the datamodel and turn the description field back into a pure text field, or you will have to transform your data into HTML (carrier returns transformed into <br> tags and escaping HTML entities like '<' or '&'.

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

Starting with iTop 2.3 case logs are formatted in HTML. Therefore, the shorthand syntax expects the comment to be formatted in HTML.

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"
      }
   ]
},

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)
If you are using http GET with a json_data parameter, some web server may replace the + within the json_data, by a space and thus breaks the query. If you suspect this behavior, replace the *+ 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": "*"
}
Try to avoid *_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"
}
You can only return objects from a single class
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'.

Multiple (bulk) updates are not supported If the 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.

Multiple (bulk) apply_stimulus are not supported in this first version. If the 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.

A deletion may imply the deletion and/or update of other objects which are linked to the deleted objects. All the objects are listed in the report.
Use simulate: true to finetune your script

Each 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

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"
}
The search can be performed on a list of objects. Simply specify the input parameter 'key' as an OQL like “SELECT Server” and all CIs related to any server will be considered. In the results sumary, this is what is referred to as “scope”.

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
}
Starting with iTop 2.3.0 it is possible to deactivate an account (by setting its status to “Disabled”). When an account is disabled, 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
latest/advancedtopics/rest_json.txt · Last modified: 2024/10/23 17:37 by 127.0.0.1
Back to top
Contact us