Administration API
This article and the rest of the API documentation in this section are written for a technical audience — integrators and developers connecting external systems to Tickiti. Familiarity with HTTP, REST, JSON and bearer-token authentication is assumed.
The Administration API exposes the Administration screens — system settings, branding, custom domain, AI assistant, users & queue permissions, teams, API keys, licence status, storage management and diagnostics. Every endpoint runs as the token’s owner and is gated by the administration ability plus the owner’s admin role; a few are additionally restricted to sysadmin and keep their in-app password re-check.
Abilities and conventions
administration:read— read endpoints.administration:write— create / update / action endpoints. Write implies read.
All endpoints are POST and JSON. Custom-domain and AI-assistant updates require the owner to be a sysadmin and to supply the operator’s current_password in the body, exactly as the screens do. Reads never return secrets (the AI key, mailbox passwords, remote tokens). The registration eligibility service token is write-only: the system settings return only registration_eligibility_token_set, true when one is stored. Seat limits and the sysadmin-only role flags on user changes are enforced as in the UI.
Endpoints
| Method & path | Ability | Purpose |
|---|---|---|
| POST /api/v1/administration/system | administration:read | System settings |
| POST /api/v1/administration/system/update | administration:write | Update system options |
| POST /api/v1/administration/branding | administration:read | Branding settings |
| POST /api/v1/administration/branding/update | administration:write | Update branding (names, colours, logo sizes) |
| POST /api/v1/administration/branding/app-logo | administration:write | Upload the app logo (multipart) |
| POST /api/v1/administration/branding/email-logo | administration:write | Upload the email logo (multipart) |
| POST /api/v1/administration/branding/reset-app-logo | administration:write | Reset the app logo |
| POST /api/v1/administration/branding/reset-email-logo | administration:write | Reset the email logo |
| POST /api/v1/administration/custom-domain | administration:read (sysadmin) | Custom-domain state |
| POST /api/v1/administration/custom-domain/update | administration:write (sysadmin + password) | Set the custom domain |
| POST /api/v1/administration/ai-assistant | administration:read (sysadmin) | AI-assistant settings/stats |
| POST /api/v1/administration/ai-assistant/update | administration:write (sysadmin + password) | Update AI-assistant settings |
| POST /api/v1/administration/users | administration:read | List users + queues |
| POST /api/v1/administration/users/create | administration:write | Create a user (seat-limited) |
| POST /api/v1/administration/users/{user}/update | administration:write | Update a user’s roles and settings |
| POST /api/v1/administration/users/{user}/queues/{queue} | administration:write | Upsert a queue permission |
| POST /api/v1/administration/users/{user}/queues/{queue}/detach | administration:write | Remove a queue permission |
| POST /api/v1/administration/teams | administration:read | List teams, their members and what uses them |
| POST /api/v1/administration/teams/create | administration:write | Create a team |
| POST /api/v1/administration/teams/update | administration:write | Rename a team or change its members |
| POST /api/v1/administration/teams/delete | administration:write | Delete a team that nothing uses |
| POST /api/v1/administration/api-tokens | administration:read | List API keys, and the abilities this token may grant |
| POST /api/v1/administration/api-tokens/create | administration:write | Create an API key (only abilities this token holds) |
| POST /api/v1/administration/api-tokens/update | administration:write | Change a key’s abilities, IP allow-list or name |
| POST /api/v1/administration/api-tokens/revoke | administration:write | Revoke an API key |
| POST /api/v1/administration/licence | administration:read | Licence status + disk utilisation |
| POST /api/v1/administration/storage/retention | administration:write | Update sent-mail retention |
| POST /api/v1/administration/storage/delete-orphaned | administration:write | Delete orphaned attachment files |
| POST /api/v1/administration/storage/delete-closed | administration:write | Delete attachments on old closed tickets |
| POST /api/v1/administration/diagnostics | administration:read | List/fetch diagnostics (if enabled) |
| POST /api/v1/administration/diagnostics/fetch | administration:read | Fetch a file from a diagnostic bundle |
| POST /api/v1/administration/diagnostics/upload | administration:write | Upload a diagnostic bundle (multipart) |
| POST /api/v1/administration/diagnostics/update | administration:write | Update diagnostic metadata |
Users
The user endpoints work like Administration → User admin (see User management).
- users — optional body
q(matches name or email),staff_only(defaulttrue: staff and CRM users only;falseincludes customers) anduser_id. Returnsusers, each withid,name,email,is_staff,is_admin,is_sysadmin,is_superuser,is_api_user,can_crm,tonic_notificationsandemail_verified_at;queues(id,name,is_inbox_capable); andselected_user: the user named byuser_id, ornull.selected_userhas the same fields plus itsqueueswith their permissions, and two booleans:two_factor_required(Must use two-factor) andtwo_factor_enrolled(the user has set up two-factor sign-in). Theusersrows do not carry the two-factor fields; to read them, pass the user’suser_id. The authenticator secret is never returned. - users/create — body
name,email,is_staff,is_adminandtonic_notifications, optionalcan_crm, andis_sysadminwhen the token’s owner is a sysadmin. It does not taketwo_factor_required: set that with users/{user}/update once the user exists. The new user is sent a welcome email. Returnsokanduser_id. - users/{user}/update — body
is_staff,is_adminandtonic_notifications(always required: send the current values of those you are not changing), plus any ofis_api_user,can_crm,two_factor_requiredand, when the token’s owner is a sysadmin,is_sysadmin.two_factor_required(boolean) is Must use two-factor: it takes effect while System settings → Who must use two-factor sign-in is Selected users or All staff. Setting it tofalsedoes not remove a two-factor sign-in the user has already set up. Returnsokanduser_id.
Fields not listed are ignored, including is_sysadmin when the token’s owner is not a sysadmin. Making a user staff when every licensed agent seat is in use returns 422.
Teams
The team endpoints work like Administration → Teams. A team is a named group of staff that a ticket can be assigned to. A ticket assigned to a team holds the team’s key, team:<id>, in assigned_to_email, and every member counts as its assignee. Assign tickets to a team by sending its key as assigned_to_email to the Create ticket API or the Reply to ticket API; the keys can also be listed with POST /api/v1/tickets/teams, which needs only the tickets ability. Only staff are members: a user who stops being staff stays on the team’s member list, with is_staff false, but no longer receives its tickets.
The team endpoints use the response envelope described in the API overview: a success is {"ok": true, "data": {…}}. Every id they return — team, member and staff — is a string, as in tickets/teams; ids in a request may be strings or numbers.
- teams — no body. Returns
teams, in name order, each withid,name,key(team:<id>),members(id,name,email,is_staff),ticket_count(the tickets assigned to the team, closed ones included, deleted ones not),unclosed_count, and three booleans that say what else names the team:has_perspectives(a perspective filters on it),has_quick_actions(a quick action assigns to it or matches on it) andhas_interventions(an intervention assigns to it). It also returnsstaff(id,name,email): the users who can be members.
{
"ok": true,
"data": {
"teams": [
{
"id": "4",
"name": "Billing",
"key": "team:4",
"members": [
{ "id": "12", "name": "Jordan Lee", "email": "[email protected]", "is_staff": true },
{ "id": "15", "name": "Sam Dixon", "email": "[email protected]", "is_staff": true }
],
"ticket_count": 18,
"unclosed_count": 3,
"has_perspectives": true,
"has_quick_actions": false,
"has_interventions": false
}
],
"staff": [
{ "id": "12", "name": "Jordan Lee", "email": "[email protected]" },
{ "id": "15", "name": "Sam Dixon", "email": "[email protected]" },
{ "id": "21", "name": "Priya Sharma", "email": "[email protected]" }
]
}
}- teams/create — body
name(up to 255 characters, unique, and notUnassignedin any capitalisation) anduser_ids: the members, as ids fromstaff.user_idsis required; send[]for a team with no members. Returnsteam: the new team, in the same shape as an entry ofteams, key included. - teams/update — body
team_id,nameanduser_ids, all required: send the current name to keep it.user_idsreplaces the membership, so send every member the team should have. The member ids from teams can be sent back as they were read: a member whoseis_staffisfalseis accepted and removed from the team, because only staff are members. A user who is not staff and not already a member is refused. A staff member who joins becomes a participant on the team’s unclosed tickets, so they hear about updates; a member who leaves is not removed as a participant. Returnsteamas it is after the change. - teams/delete — body
team_id. A team that is in use is kept: while any ticket is assigned to it (closed tickets included), or a perspective, quick action or intervention names it, the call returns422with"error": "refused"and amessagesaying which, for exampleCannot delete: 3 ticket(s) are assigned to Billing.Reassign those tickets and change those settings first; the counts and flags from teams show what remains. Deleted tickets do not keep a team: any that are still assigned to it are set toUnassignedwhen the team is deleted, so a ticket restored later is unassigned. Deleting the team also removes its memberships, and a draft that would have assigned its ticket to the team leaves the assignee unchanged instead. Returnsdeleted(the team’s id) andunassigned_deleted_tickets(how many deleted tickets were set toUnassigned).
{
"ok": false,
"error": "refused",
"message": "Cannot delete: 3 ticket(s) are assigned to Billing."
}An unknown team_id, a missing or duplicate name, or a user_ids entry that is neither a staff member nor already a member returns 422 with "error": "validation_failed" and errors naming each field. It is JSON whether or not the request sends Accept: application/json. For a non-staff id the message is Only staff can be team members.
{
"ok": false,
"error": "validation_failed",
"errors": {
"user_ids.1": ["Only staff can be team members."]
}
}API keys
The API-key endpoints manage the keys listed on Administration → API keys (see Authentication and tokens). One rule applies on top of the screen’s: a token can only grant abilities it holds itself. A key created or changed through the API can receive only the calling token’s own abilities (holding write covers read), so the API narrows and rotates keys; a key with wider access is created on the screen.
- api-tokens — returns
tokens, each withid,name,owner(Systemor the owner’s email),abilities,allowed_ip,last_used_at,expires_at,created_atandis_this_token(true for the key making the call), plusgrantable: the abilities this token may grant. - api-tokens/create — body
name(up to 255 characters),owner(systemor a staff user’s id),abilities(one or more) and optionalallowed_ip(a single address the key will only work from). The owner must hold the role each ability requires. The response carries the bearer token once, alongside the stored key:
{
"ok": true,
"plain_text_token": "27|Xq4rT9…",
"token": {
"id": 27,
"name": "Sales Portal — tickets read/write",
"abilities": ["tickets:write"],
"last_used_at": null,
"created_at": "2026-10-04T10:15:02.000000Z",
"allowed_ip": null
}
}- api-tokens/update — body
idplus any ofabilities(replaces the list; the owner must hold the role each needs),allowed_ip(an address, or null to remove the restriction) andname. Returnsid,name,abilitiesandallowed_ip. - api-tokens/revoke — body
id. The key stops working at once. Returnsrevoked(the id) andwas_this_token, true when a token revoked itself.
Granting an ability the calling token does not hold returns 403 forbidden with a message naming the missing abilities. An unknown key returns 404 not_found; an owner who lacks a required role returns 422 validation_failed.
Not exposed
Some actions are intentionally unavailable over the API, even role-gated, because the blast radius of a leaked token is too high:
- Licence register / unregister — can deactivate the whole instance. Read-only status is available above.
- Deleting a user — create and role changes are available; deletion is UI-only.
- Resetting a user’s two-factor sign-in — a token that could remove a user’s second factor would undo its protection. A system administrator resets it in User admin.