GLPI 11 has two APIs: the old one, which GLPI itself now calls the "Legacy API", and a new one, with OAuth2, GraphQL and interactive documentation. We tested the new one end to end: from the token to a ticket opened, updated and given a followup. The first stumble came before any ticket: GLPI issued the token normally and then refused everything with "The High-Level API is disabled". This guide shows the path that worked, with the tested Postman collection available for download.
The Legacy API still works, and it is the one we use in the MCP server that connects Claude to GLPI. For new integrations, GLPI itself recommends the new one.
The two APIs in GLPI 11
| Legacy API (v1) | New API (v2) | |
|---|---|---|
| Endpoint | /apirest.php or /api.php/v1 |
/api.php/v2.3 (current version) |
| Authentication | App-Token + user token, then Session-Token | OAuth2 (Bearer token) |
| Format | GLPI items as they are stored in the database | Organized resources (/Assistance/Ticket, /Assistance/Ticket/{id}/Timeline) |
| Search | GLPI search criteria | RSQL filter (name=like=*toner*) and pagination in the header |
| Extras | — | GraphQL and interactive documentation at /doc |
| Status | GLPI warns: "it is recommended to use only the new API whenever possible" | Recommended for anything new |
Step 1: turn on the new API
In Setup > General > API, turn on Enable API. This switch is different from the one that turns on the Legacy API.
In our test, with it turned off, the token request worked: GLPI returned a token valid for one hour. Only on the first call did the error "The High-Level API is disabled" appear. If the token is issued and everything returns 403, start here.
Step 2: the service user and the OAuth client
- Service user: an account just for the integration, with the minimum profile it needs, in the right entity. Never an administrator.
- OAuth client (in Setup > OAuth clients):
- Grants:
passwordfor system-to-system with the service user;authorization_codewhen the application acts on behalf of each person who logs in;client_credentialsis used by the inventory agents. - Scopes:
apifor the API,graphqlfor GraphQL,userandemailfor the user's own data,inventoryandstatusfor specific purposes. Grant only what the integration uses. - Allowed IPs: restrict them to the server that will call the API.
GLPI generates the client ID and secret. Keep both in a vault, not in the code.
Step 3: from token to ticket
Request the token (valid for 1 hour, with a refresh token):
curl -X POST https://glpi.suaempresa.com.br/api.php/token \
-d grant_type=password -d client_id=$CLIENT_ID -d client_secret=$CLIENT_SECRET \
-d username=$USUARIO -d password=$SENHA -d scope="api graphql"
Open a ticket:
curl -X POST https://glpi.suaempresa.com.br/api.php/v2.3/Assistance/Ticket \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"name": "Impressora do 2o andar sem toner", "content": "Aberto pela API v2.", "urgency": 3, "type": 1}'
The rest of the path we tested:

| Action | Call | Test result |
|---|---|---|
| Token | POST /api.php/token |
Bearer, 1 hour, with refresh, in 0.3 to 0.4 s |
| Open ticket | POST /v2.3/Assistance/Ticket |
200, returns the id |
| Read | GET /v2.3/Assistance/Ticket/{id} |
Status already comes with its name ("Novo") |
| Change urgency | PATCH /v2.3/Assistance/Ticket/{id} |
200, the priority is recalculated |
| Followup | POST /v2.3/Assistance/Ticket/{id}/Timeline/Followup |
200 |
| Timeline | GET /v2.3/Assistance/Ticket/{id}/Timeline |
List with the followup |
| Search | GET /v2.3/Assistance/Ticket?filter=name=like=*toner* |
Total in the Content-Range header |
| GraphQL | POST /v2.3/GraphQL |
Only the requested fields, with pagination |
| Refresh | POST /api.php/token with refresh_token |
New token without asking for the password again |
| No token | any route | 401 |
Three details that catch people out
- The "Enable API" switch is separate from the Legacy API, and the token is issued even with the API turned off. The error only shows up later.
- A scope that is requested but not allowed does not fail right away. We requested the
userscope on a client that did not have it: the token came anyway, without that scope, and the user route returned 403. If a route returns 403 with a valid token, check the client's scopes. - The status comes as an object (
{"id": 1, "name": "Novo"}), not as a number. Anyone migrating from the Legacy API needs to adjust the code that read the status.
When to use each one
- New integration: the new API. OAuth is the industry standard, the resources are clearer and the documentation is in GLPI itself.
- Integration that already works on the Legacy API: there is no rush, but plan the migration. GLPI already shows the warning to use the new one.
- Application that acts on behalf of several people (a portal, an app):
authorization_code, so each person authorizes with their own login. - Server routine (n8n, ERP, script):
passwordwith a service user and a restricted IP.
Download the tested collection
The GLPI 11 API Postman collection has the nine calls from the table, with the token and the ticket id stored automatically from one call to the next. Fill in your GLPI address, the OAuth client and the service user.
Test run by NexTool on October 4, 2026, on a GLPI 11.0.7 test instance (API v2.3), with a service user and an OAuth client created for the test and deleted at the end. The routes and scopes were also checked against the GLPI 11 source code.
Comments
Comments on this post come from GitHub (giscus). When you load them, your browser connects to GitHub, which receives your IP address and may set its own cookies.
To load them automatically, enable functional cookies