The New GLPI 11 API in Practice: OAuth2, from Token to First Ticket

We tested the GLPI 11 API v2 end to end: OAuth client, token, create, update and follow up a ticket, RSQL filter and GraphQL. The three details that cause 403 with a valid token, and a tested Postman collection to download.

In this article7 sections

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

  1. Service user: an account just for the integration, with the minimum profile it needs, in the right entity. Never an administrator.
  2. OAuth client (in Setup > OAuth clients):
  3. Grants: password for system-to-system with the service user; authorization_code when the application acts on behalf of each person who logs in; client_credentials is used by the inventory agents.
  4. Scopes: api for the API, graphql for GraphQL, user and email for the user's own data, inventory and status for specific purposes. Grant only what the integration uses.
  5. 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:

Result of each step of the new API test: with Enable API off the token is issued and calls return 403; token, create, read, PATCH and follow-up work; a scope not allowed causes 403 on the route
If the token works and everything returns 403, check the Enable API switch and the OAuth client scopes. NexTool test, October 4, 2026.
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

  1. 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.
  2. A scope that is requested but not allowed does not fail right away. We requested the user scope 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.
  3. 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): password with 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.

Frequently Asked Questions

Yes. Besides the Legacy API (v1), GLPI 11 has a new API at /api.php/v2.3 with OAuth2, structured resources, RSQL filters, GraphQL and interactive documentation at /doc.

The most common causes are the Enable API switch being off under Setup > General > API (the token is still issued) and the OAuth client missing the scope the route requires.

Create an OAuth client under Setup > OAuth clients with the password grant and the api scope, then POST to /api.php/token with client_id, client_secret and the service user credentials. The Bearer token lasts 1 hour and can be refreshed.

It still works in GLPI 11, but GLPI itself recommends using only the new API when possible. Use v2 for new integrations and plan the migration for existing ones.

password with a service user for server integrations; authorization_code when the application acts on behalf of each person; client_credentials is used by inventory agents.

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

Need help?