HTTP API v1 — Developer documentation
Overview
The API is intended for machine-to-machine access using OAuth2 client credentials.
All protected routes expect Authorization: Bearer … and should be called with
Accept: application/json.
Authentication
Obtaining a token
POST https://next.integeri.com/oauth/token
Content-Type: application/json
{
"grant_type": "client_credentials",
"client_id": "<ApiClient UUID> ",
"client_secret": "<ApiClient secret> ",
"scope": "*"
}
The response includes access_token, token_type, expires_in, etc.
HTTP status & error format
JSON errors for api/* and when Accept: application/json
| Code | Typical cause | Body (simplified) |
|---|---|---|
| 401 | Missing/invalid token | {"message":"Unauthenticated."} |
| 403 | Policy / permission / inactive service user | {"message":"…"} |
| 404 | Unknown route or model | {"message":"…"} |
| 405 | Wrong HTTP method | {"message":"Method not allowed."} |
| 422 | Validation | {"message":"…","errors":{…}} |
| 429 | Rate limit | {"message":"Too many requests."} |
| 500 | Server error | Generic message in production; detail possible in development |
Lists: pagination, sorting, filters
Shared query parameters for GET …/locations, GET …/teams, GET …/users :
| Parameter | Description |
|---|---|
page | Page number |
per_page | Items per page, 1–100 |
sort | Comma-separated fields; prefix - for descending |
state | active or inactive (locations, teams, users) |
search | Text search (behaviour varies by resource) |
Allowed sort fields
- Locations:
id,state,created_at,updated_at,order_position - Teams:
id,state,created_at,updated_at,order_position - Users:
id,state,username,created_at,updated_at
Additional filters
GET /locations:includeGET /teams:location_id,includeGET /users:team_id,location_id,role,includeGET /courses:state(defaults toactive),search(title),type(see Courses endpoint)GET /users/{user}/assigned-courses,GET /users/{user}/certificated-courses: no filters
List responses use paginated JSON with data, links, meta.
Optional: include
Comma-separated list; unknown segments are ignored.
| GET | Segments | Effect (short) |
|---|---|---|
/locations | teams | Embeds teams on each location resource |
/teams | users, instruction | Members and recurring instruction (course) |
/users | locations | Extra locations array (deduplicated via team→location) |
Endpoints: Auth
Base path: https://next.integeri.com/api/v1 — all require a bearer token.
GET /auth/me
200 — service user, OAuth client, token metadata
{
"data": {
"service_user": {
"id": 1,
"username": "…",
"company_id": 1,
"roles": ["company.admin", …]
},
"client": { "id": "…", "name": "…" },
"token": {
"expires_at": "2026-01-01T12:00:00+00:00",
"scopes": ["*"]
}
}
}
POST /auth/logout
200 — revoke current access token
{ "message": "Token revoked." }
Endpoints: Locations
| Path | Description | Status | |
|---|---|---|---|
| GET | /locations | List | 200 |
| POST | /locations | Create | 201 |
| GET | /locations/{location} | Detail | 200 |
| PUT/PATCH | /locations/{location} | Update | 200 |
| POST | /locations/{location}/deactivate | Deactivate | 200 |
| PUT | /locations/order-positions | Reorder multiple locations | 200 |
| PUT | /locations/{location}/teams/order-positions | Reorder teams at a location | 200 |
POST /locations — body (validation)
name— required, string, max 255description,street,zip_city, …country— max 2 charactersadmin_user_ids[],trainer_admin_user_ids[]— optional user IDs
PATCH /locations/{id}
Same fields as store; all optional unless your client sends a full PUT requiring name.
PUT /locations/order-positions
Requirement: permission to reorder locations. Body: {"locations": [{"id": 1, "order_position": 10}, …]} — reorders company locations
PUT /locations/{location}/teams/order-positions
Requirement: permission to reorder teams and view access to the location. Body: {"teams": [{"id": 5, "order_position": 20}, …]}.
Endpoints: Teams
| Path | Description | Status | |
|---|---|---|---|
| GET | /teams | List | 200 |
| POST | /teams | Create | 201 |
| GET | /teams/{team} | Detail | 200 |
| PUT/PATCH | /teams/{team} | Update | 200 |
| POST | /teams/{team}/deactivate | Deactivate | 200 |
| POST | /teams/{team}/users | Attach users | 200 |
| DELETE | /teams/{team}/users/{user} | Detach user | 204 |
POST /teams — body
name— requiredlocation_id— required, must exist inlocationsdescription, contact fields,admin_user_ids[],trainer_admin_user_ids[]— optional
POST /teams/{team}/users
user_ids— required array of user IDsnext_instruction_date— optional,Y-m-dforce— optional boolean
Endpoints: Users
| Path | Description | Status | |
|---|---|---|---|
| GET | /users | List | 200 |
| POST | /users | Create | 201 |
| GET | /users/{user} | Detail | 200 |
| PUT/PATCH | /users/{user} | Update | 200 |
| POST | /users/{user}/activate | Activate | 200 |
| POST | /users/{user}/deactivate | Deactivate | 200 |
| POST | /users/{user}/reset-password | Reset password | 200 JSON |
| PUT | /users/{user}/roles | Sync roles | 200 |
| POST | /users/{user}/course-assignments | Assign an existing course | 201 |
| POST | /users/{user}/qualifications | Record a manual qualification | 201 |
| GET | /users/{user}/assigned-courses | Open assignments (with is_overdue) | 200 |
| GET | /users/{user}/certificated-courses | Completed assignments incl. certificate URL | 200 |
| GET | /users/{user}/{assignment}/course/{course}-{lang}.pdf | Download certificate PDF | 200 |
POST /users — body (excerpt)
salutation—m,f,dfirst_name,last_name— requiredemail,mobile_number,username,password(min 8),language,birthday(Y-m-d),driving_classes(A,CE,D,...)team_ids[],roles[],send_credentials(boolean)id— optional in service/import flows; interpreted asuser_idfor email unique validation
The service layer may derive usernames from name/birthday; omitting optional birthday is allowed.
inspect errors on 422.
PUT /users/{user}/roles
{ "roles": ["company.admin", "company.employee"] }
POST /users/{user}/reset-password
send_email— optional boolean (defaults towardtrue)
Without email delivery the response may include a temporary password.
Endpoints: Courses
Active courses visible to the calling service user: Integeri courses plus the calling company's own courses.
| Path | Description | Status | |
|---|---|---|---|
| GET | /courses | Active courses (paginated) | 200 |
Requirement: permission to view courses. Query parameters: page, per_page (1–100), state (active/inactive, default active), search (title), optional type (see below).
GET /courses — query parameter type
qualification— qualification / manual user approval.operator— operator training courses only .trainer— trainer training courses only .operator_recurring— recurring operator instruction courses only .
Without type, only the usual visibility rules apply. type further narrows the visible set; it can be combined with search and state.
Endpoints: Content video (process)
Creates a teleprompter / synthesis video with
prompter_text —
either attached to an existing content node or as new content in the recurring instruction course of an active base course.
| Path | Description | Status | |
|---|---|---|---|
| POST | /contentvideos/create | Create video / optional new content+course node under base course | 201 |
Requirement: permission to create content; the target base course must belong to the service user's company (or be a shared Integeri base course).
Otherwise 403 or 422 under errors.course_id.
POST /contentvideos/create — JSON body
prompter_text— required string (max 14000 chars), stored as the video’s prompter text.name— optional string (max 255 chars). Title of the new content node whencontent_node_idis omitted. Without it, the title is derived from the prompter text.content_node_id— optional positive int. If set, the content node must exist; the video is linked there. Otherwise a new content node is created in the target course.api_base_course_id— optional: positive int of a company API-Kollektion (must be listed incompany.video_settings['api-courses']) or-1to provision a new collection. Overrides the collection linked to the OAuth client. Whencourse_id,api_base_course_id, andteam_idare all omitted, the client’sapi_base_course_idis used.course_id— optional positive int. Must be an active base course or recurring instruction course .team_id— optional positive int. When set and neithercourse_idnorapi_base_course_id(including-1) is given, the team's recurring course (teams.recurring_course_id) is used. Typical Make.com flow: create the team first, then post the video withteam_id.
Errors 422: unknown content_node_id; invalid/inactive course; course not a registered API-Kollektion (api_base_course_id); unknown team or team without recurring course; company mismatch; API client without linked collection; base course not allowed. 403 if permission to create content is missing .
Success 201 JSON data: content_node_video_id, content_node_id, course_id, course_node_id (set only when a new course node was created), estimated_video_length (estimated duration in seconds from the prompter text .
Endpoints: Course assignments (per user)
| Path | Description | Status | |
|---|---|---|---|
| POST | /users/{user}/course-assignments | Assign an existing course to a user | 201 |
| POST | /users/{user}/qualifications | Record a manual qualification | 201 |
| GET | /users/{user}/assigned-courses | Open assignments (with is_overdue) | 200 |
| GET | /users/{user}/certificated-courses | Completed assignments incl. certificate URL | 200 |
| GET | /users/{user}/{assignment}/course/{course}-{lang}.pdf | Download certificate PDF | 200 |
POST /users/{user}/course-assignments
Requirement: permission to create course assignments and view access to the target user.
course_id is validated for visibility (own company or shared Integeri course) and
for state = active.
Assignment state is forced to assigned, type to manual.
POST /api/v1/users/42/course-assignments
Content-Type: application/json
Authorization: Bearer …
{
"course_id": 23,
"deadline_date": "2026-06-30" // optional, Y-m-d or ISO-8601
}
Response 201: full CourseAssignment resource (see below).
POST /users/{user}/qualifications
Requirement: permission to create course assignments and view access to the target user.
course_id must be an active course with manual qualification enabled
(list via GET /courses?type=qualification).
Creates an assignment with state = success and type = approval.
File uploads are not supported in API v1 (web UI only).
POST /api/v1/users/42/qualifications
Content-Type: application/json
Authorization: Bearer …
{
"course_id": 15,
"finish_date": "2024-06-01", // optional, Y-m-d, max. today
"valid_period": "2y", // optional, e.g. 30d, 6m, 2y; required if course may_change_valid_period
"assignment_id": 99 // optional; update existing approval assignment
}
Response 201: CourseAssignment resource (state=success, assignment_type=approval).
Recommended workflow
- List qualification courses:
GET /courses?type=qualification. - Resolve the target user ID (e.g. from
GET /usersor your import). - Record the qualification:
POST /users/{user}/qualificationswithcourse_idand optionalfinish_date/valid_period. - Verify the result: response contains the new assignment; completed entries appear under
GET /users/{user}/certificated-courseswithentry_type = qualification_approval.
JSON body — fields
| Field | Required | Description |
|---|---|---|
course_id | yes | Active qualification course (manual qualification enabled), visible to the service user's company (Integeri or own company course). |
finish_date | no | Qualification date (Y-m-d), at most today. Defaults to the current date when omitted. |
valid_period | conditional | Validity duration, format ^\d+[d|w|m|y]$ (e.g. 30d, 6m, 2y). Required when the course has may_change_valid_period = 1; otherwise the course's valid_period is applied. |
assignment_id | no | Update an existing approval assignment for the same user (dates/validity). Must belong to the target user and have type = approval. |
Behaviour & prerequisites
- On create (without
assignment_id): assignment withstate = success,type = approval,result_percent = 100; a certificate is generated automatically . - The qualification course must be fully configured (with course content) . Without that, certificate creation fails → response 422 under
errors.qualification. - Existing valid
approvalassignments for the same user and course are superseded on create (valid_until = yesterday). - If the course is also an operator training course, a recurring operator assignment may be triggered — same as the web UI.
After success, the qualification appears in GET /users/{user}/certificated-courses
(entry_type = qualification_approval, download_url when a certificate PDF exists).
Validation errors (422)
course_id— unknown, inactive, not a qualification course, or foreign company course.finish_date— invalid date or in the future.valid_period— missing when required by the course, or invalid format.assignment_id— assignment missing, wrong user, or notapprovaltype.qualification— business error when recording the qualification .
Machine training prerequisites (operator / trainer)
If the course being assigned is an operator training or a trainer training , the user's course prerequisites (age requirement, prior qualification, fitness status, etc.) are validated.
If any prerequisite fails, the API responds with 422 Unprocessable Entity.
The failing conditions are returned as localised messages under errors.course_id:
{
"message": "The given data was invalid.",
"ok": 0,
"id": 0,
"errors": {
"course_id": [
"The age requirement (24 years) for the user is not met.",
"Missing successful completion of the training 'Industrial truck / forklift - operator'."
]
}
}
Non-machine courses skip this additional check.
GET /users/{user}/assigned-courses
Requirement: permission to view course assignments and view access to the target user. Returns all open assignments (state assigned, inprogress, done, plus success
while still inside an ongoing group/operator training). The is_overdue flag marks entries whose
deadline_date is in the past.
GET /users/{user}/certificated-courses
Requirement: permission to view completed courses and view access to the target user. Returns completed assignments as certificated_course resources with localized
state_label (same wording as the web certificate list — not raw
success/failed). The download_url field points to the API PDF route
GET /users/{user}/{assignment}/course/{course}-{lang}.pdf for generated certificates, or to a
signed upload file URL — same rules as the web certificate list .
Note: repetitions and group/operator-training assignments are deduplicated server-side
GET /users/{user}/{assignment}/course/{course}-{lang}.pdf
Requirement: permission to view completed courses and view access to the target user. Returns the certificate as a PDF file (same download rules as the integeri web UI).
Only for completed assignments (state = success or failed) whose
user_id, assignment ID and course ID match the URL.
{lang} is a two-letter language code (e.g. de, en).
GET /api/v1/users/42/99/course/15-de.pdf
Authorization: Bearer …
Response 200: PDF file.
JSON resource fields
Summary only;
Location
id, type (= location), state, description, company_id, contact, admin_user_ids, trainer_admin_user_ids, teams_count, optional teams with include=teams, timestamps.
Team
id, type (= team), state, description, location_id, contact, assignees, users_count, optional users / instruction, timestamps.
User
id, type (= user), state, username, contact/profile fields, company_id, team_ids, roles, optional locations with include=locations, timestamps.
Course
id, type (= course), title, description,
allow_user_approval_date (boolean), valid_period, number_of_questions,
minimal_success_points, state, company_id (null for Integeri courses).
CourseAssignment
Used for POST /users/{user}/course-assignments, POST /users/{user}/qualifications, and GET /users/{user}/assigned-courses.
id,type(=course_assignment),user_idstate—assigned,inprogress,done,success,failed,notshownupassignment_type—manual,recurring,approvaldeadline_date,valid_until,begin_date,finish_date(ISO-8601 orY-m-d)result_percent— percentage of correctly answered questions, ornullis_overdue— boolean,truewhendeadline_date < now()course—{id, title, short_type, scope_id, type}trainer—{id, full_name}ornullcreator—{id, full_name}ornullcreated_at,updated_at
CertificatedCourse
Used for GET /users/{user}/certificated-courses (completed assignments ).
id,user_identry_type—certificated_course(formanual),qualification_approval(forapproval),operator_training(operator group),trainer_training(trainer course)state_label— localized short result (training/instruction wording), no rawstateassignment_type— DB assignment typefinish_date,valid_until,result_percentis_group_operator_training— booleancourse—{id, title, short_type}download_url— API PDF URL (/api/v1/users/…/course/{course}-{lang}.pdf) or signed upload URLcreated_at,updated_at
References
- PHP mini SDK (ZIP):
/docs/api/integeri-sdk-php.zip - Make.com integration (PDF):
/docs/api/integeri-api-make-com.pdf— team/video flow and certificate PDF download