DEV Community

Cover image for GLPI - Closing Ticket with API
João Pedro
João Pedro

Posted on

GLPI - Closing Ticket with API

Unlike what is described in the official GLPI documentation, the system does not work as expected and does not correctly respond to the provided parameters. The documentation found at "https://YOUR_GLPI_DOMAIN.COM/apirest.php" states that some parameters should be passed in the request body, but this doesn't always work. The only method that seems to work is passing the parameters directly in the URL.

Autor: joaoprd | joaopedrord2001@gmail.com

Starting a Session

To initiate any call, we need the session_token and app-token. To generate the session_token, we make a request to "https://YOUR_GLPI_DOMAIN.COM/apirest.php/initSession" with the app-token and user_token parameters, which are available in the user account we are working with.

The following request generates the session_token:

curl --location 'https://DOMINIO_GLPI.COM/apirest.php/initSession?app-token={YOUR-APP-TOKEN}&user_token={YOUR-USER-TOKEN}'
Enter fullscreen mode Exit fullscreen mode

Ticket Search

With the session_token in hand, we can perform searches for tickets. However, according to the GLPI documentation, it appears that the endpoint does not function as per the provided examples, as it does not allow sending a payload to this endpoint, resulting in the following error:

[
    "ERROR_JSON_PAYLOAD_FORBIDDEN",
    "GET Request should not have json payload (http body); view documentation in your browser at /#ERROR_JSON_PAYLOAD_FORBIDDEN"
]
Enter fullscreen mode Exit fullscreen mode

To circumvent this limitation, we will pass the parameters directly in the URL of the request, using the link "https://YOUR_GLPI_DOMAIN.COM/apirest.php/search/Ticket". You must include the app-token and session-token to connect, and then add the desired filters to locate the necessary information.

curl --location --globoff 'https://DOMINIO_GLPI.COM/apirest.php/search/Ticket
?app-token={YOUR-APP-TOKEN}
&session_token={YOUR-SESSION-TOKEN}
&criteria[0][field]=1
&criteria[0][searchtype]=contains
&criteria[0][value]=Verifica%C3%A7%C3%A3o%20diaria
&criteria[1][link]=AND
&criteria[1][field]=12
&criteria[1][searchtype]=equals
&criteria[1][value]=2
&glpilist_limit=1000' \
--header 'Content-Type: application/json'
Enter fullscreen mode Exit fullscreen mode

"Criteria" refers to the filtering criteria, where fields are specific filters to be applied to find something. For example, "criteria[0][field]=1" is designated for the title, where we pass "criteria[0][searchtype]=contains" indicating that it contains "criteria[0][value]=Verifica%C3%A7%C3%A3o%20diaria", which, in this case, is 'Verificação diária' that was encoded. This is where the ticket title should be placed. Another filter is applied below in "criteria[1][link]=AND", where an AND is performed, indicating a new search following the previous one.

To analyze all filtering options, you can make a request to:

curl --location 'https://DOMINIO_GLPI.COM/apirest.php/listSearchOptions/Ticket?app-token={YOUR-APP-TOKEN}&session_token={YOUR-SESSION-TOKEN}' \
--data ''
Enter fullscreen mode Exit fullscreen mode

Some example responses:

{
    "common": {
        "name": "Características"
    },
    "1": {
        "name": "Título",
        "table": "glpi_tickets",
        "field": "name",
        "datatype": "itemlink",
        "nosearch": false,
        "nodisplay": false,
        "available_searchtypes": [
            "contains",
            "notcontains"
        ],
        "uid": "Ticket.name"
    },
    "21": {
        "name": "Descrição",
        "table": "glpi_tickets",
        "field": "content",
        "datatype": "text",
        "nosearch": false,
        "nodisplay": false,
        "available_searchtypes": [
            "contains",
            "notcontains"
        ],
        "uid": "Ticket.content"
    },
    "2": {
        "name": "ID",
        "table": "glpi_tickets",
        "field": "id",
        "datatype": "number",
        "nosearch": false,
        "nodisplay": false,
        "available_searchtypes": [
            "contains",
            "notcontains"
        ],
        "uid": "Ticket.id"
    },
...
Enter fullscreen mode Exit fullscreen mode

Creating a Task

With the previous request, we performed the search for tickets, which will be returned in JSON format. With this information, we can handle the necessary tasks. In this specific documentation, we will close the ticket. However, before completely closing the ticket, we need to create a task linked to the ticket that must be completed.

Some GLPI systems require specific methods for closing tickets. In the system I am working with, it is necessary to create a task and a solution before closing the ticket.

Below is the request that creates the task in the ticket (remember that the ticket I am passing was generated in the previous search in "Ticket Search"). In my automation code, I implemented a loop to process all returned tickets, but that will not be covered in this documentation.

curl --location 'https://DOMINIO_GLPI.COM/apirest.php/TicketTask?session_token={YOUR-SESSION-TOKEN}' \
--header 'app_token: {YOUR-APP-TOKEN}' \
--header 'Authorization: user_token {YOUR-USER-TOKEN}' \
--header 'Content-Type: application/json' \
--data '{
    "input": {
        "tickets_id": 2408020023, 
        "taskcategories_id": 0, 
        "content": "Verificação diária - Tarefa realizada.",
        "actiontime": 60, 
        "state": 3 
    }
}
'
Enter fullscreen mode Exit fullscreen mode

We should note that in all cases, we pass the app_token in the header, and the Authorization, which contains the user_token for API authentication.

Key points to consider are the parameters passed in the request body:

  • content: The content that will be added to the task.
  • actiontime: The time spent on the task.
  • state: The status the ticket will have after the task is created.

Closing the Ticket

With the task added to the ticket, it is only necessary to close the ticket, which follows the same process used to add the task.

The following request is used:

curl --location --request PUT 'https://DOMINIO_GLPI.COM/apirest.php/Ticket/2408020023?session_token={YOUR-SESSION-TOKEN}' \
--header 'app_token: {YOUR-APP-TOKEN}' \
--header 'Authorization: user_token {YOUR-USER-TOKEN}' \
--header 'Content-Type: application/json' \
--data '{
  "input": {
    "status": 6, 
    "solution": "<p>Chamado finallizado</p>",  
    "content": "<p>Chamado finallizado</p>",
    "solutiontypes_id": 3, 
    "solutiontemplates_id": 5  
  }
}'
'
Enter fullscreen mode Exit fullscreen mode

The status: 6 indicates the ticket is closed. For this, it is necessary to pass the solution and content as the texts for the solution. An important point in this request is the solutiontemplates_id, which must be created by the GLPI system administrator, with this ID serving as a reference for a standard solution.

Top comments (0)