Changelog
Backward compatibility
Section titled “Backward compatibility”The API is versioned via the URL path (currently /v1/). Within a version, changes
are backward compatible: we add new endpoints, fields and parameters, but we do not
remove or rename existing ones and do not change their meaning. Your integration
should therefore ignore unknown fields in responses. Breaking changes would only come
with a new API version and would be announced here beforehand.
Current availability of the API is shown on the status page.
October 2026
Section titled “October 2026”- Reliable
400for duplicate users. If the username or email address is already taken when creating or editing users, the API now always answers with400and the error typeValidationError, which names the affected field infield_errors; previously such conflicts could end in a500in rare cases. Username and email address are now also unique regardless of case:annaandAnnacount as the same value. See errors and rate limiting and the API reference, section Users. expandnow requires the read scope of the embedded resource. Expanding a field via the query parameterexpandembeds the full linked object, so the API key now also needs the Read scope of that resource, for exampleusers:readfor?expand=useron participations. If the key lacks the scope, the API answers with403and the error typeMissingScope, which names the required scope. See expanding resources and access scopes.- Idempotent requests. All
POSTendpoints accept the newIdempotency-Keyheader, which makes retries safe: resending the same request with the same key returns the stored response of the first successful execution instead of executing it again. See Idempotent requests. - Access scopes for API keys. Every API key now carries access scopes that
control per resource what it may call: No access, Read or Read and write,
plus a deliberately separate right for login links. The API reference
names the required scope on every endpoint; if a key lacks one, the API answers
with
403and the new error typeMissingScope, and the new endpointGET /v1/me/returns the scopes of the key in use. Existing keys keep full access. The key list in the admin area additionally shows when each key was last used. See access scopes. - Choose your page size. All list endpoints accept the new query parameter
page_size(1 to 100; the default stays at 25). The URLs innextandpreviouskeep the chosen page size. See pagination and sorting. - Webhooks. Schulungstool can now actively notify your systems about events for
users and participations: signed
POSTrequests with retries, a 30-day delivery log and test events, configured in the admin area. See the webhooks guide and the API reference, section Webhooks. - Rate limit headers on every response. Every API response now reports the current
state of the rate limit in the headers
X-RateLimit-Limit,X-RateLimit-RemainingandX-RateLimit-Reset, so clients can pace their requests before running into a429. See errors and rate limiting. - Request IDs and API log. Every API response carries the new header
X-Request-ID; error responses repeat the ID asrequest_idin the body. Include it in support inquiries: it lets us look up the exact request in our logs. See errors and rate limiting. The admin area additionally keeps a 30-day log of the requests made with your API keys (metadata only, no request or response bodies), under Settings > Advanced settings > Developer options > API log. - New documentation site. English is now the default language, with a complete German version. The new API reference supports trying requests directly in the browser, and the schema is available for download as an OpenAPI 3.1 document (German), plus an llms.txt for AI assistants. The API itself is unchanged; all existing links to the previous documentation keep working.
- Email notification when creating participations.
Create a participation can
now trigger the notification email to the user directly: set
send_email_notification, optionally scheduled viaemail_scheduled_at. - Enforce a password change. The user object has the
new field
requires_password_change; it can be set when creating and editing users and filtered on when listing them. - Delta queries with
updated_after. The list endpoints support the new filterupdated_after: fetch only the objects changed since your last run instead of the full list; see the new guide Syncing data. Changes to group memberships now updateupdated_atof the affected user and group. Course ratings are the deliberate exception: they are anonymous, so they carry no timestamps and noupdated_afterfilter.