API and integrations: reference
The reference is intended for an integration developer. A step-by-step instruction for a user is in the process “Integrations”.
Access methods
| Method | What it is for | Authentication |
|---|---|---|
| REST API | Reading and changing data from scripts and services | An API key in the header Authorization: Bearer thor_sk_… |
| MCP | Reading data by AI assistants (read-only) | An API key |
| Webhook | Receiving events in your system | The signature X-Assist-Signature |
Addresses
- REST API:
https://<cabinet address>/api. - MCP:
https://<cabinet address>/api/mcp(Streamable HTTP, stateless). - Health check:
GET /healthandGET /readywithout authentication.
Authentication
- Create an API key on the “API keys” page. Choose a role: the key gets the permissions of exactly this role.
- Save the token of the form
thor_sk_<identifier>.<secret>: it is shown once. - Pass the token in every request:
Authorization: Bearer thor_sk_….
For requests with a key, the X-Requested-With header is not needed. Managing the keys themselves with a key is impossible: the response is 403.
Common headers
| Header | When | Value |
|---|---|---|
Authorization | Always | Bearer thor_sk_<id>.<secret> |
Content-Type | For POST and PATCH with a body | application/json |
Accept-Language | Optional | ru or en: the message language |
Idempotency-Key | Recommended for POST, PUT, PATCH, DELETE | A unique string up to 255 characters |
Idempotency. Repeating a request with the same key and body returns the stored response. The same key with a different body: error 409 IDEMPOTENCY_MISMATCH. It does not work for file uploads (multipart/form-data).
Data format
- Identifiers: UUIDs in lowercase.
- Date and time: ISO 8601 with a time zone, for example
2026-10-28T12:00:00.000Z. - Calendar days (start and end of tasks and releases):
YYYY-MM-DD. - Description: a BlockNote document (JSON) or
null. - Estimates and durations: minutes (an integer).
Pagination. Lists respond with an object { items, pagination: { limit, offset, total, hasMore } }. Parameters limit and offset. Task trees use a cursor: nextCursor.
Permissions
Each method checks the key role's permissions and the record scope. The current key's permissions are returned by GET /api/me in the permissions field. A 403 error means insufficient permissions, not an authentication problem. A 404 error may mean the record is outside the role's scope.
Limits
| Zone | Limit |
|---|---|
/api/auth/* | 40 requests per minute per address |
Other /api/* | 180 requests per minute per address |
On exceeding, the response is 429 RATE_LIMITED with the headers x-ratelimit-limit, x-ratelimit-remaining, x-ratelimit-reset, retry-after.
Error format
{ "error": { "code": "VALIDATION_ERROR", "message": "Invalid request body", "details": {} } }
| HTTP | Code | When |
|---|---|---|
| 400 | VALIDATION_ERROR | An invalid body or request parameters |
| 401 | UNAUTHORIZED | No or invalid key or session |
| 403 | FORBIDDEN | No permission |
| 404 | NOT_FOUND | The record is not found or outside the scope |
| 409 | CONFLICT, IDEMPOTENCY_MISMATCH | A data conflict, a repeat with a different body |
| 429 | RATE_LIMITED | The limit is exceeded |
| 500 | INTERNAL | An unhandled error |
A stage transition that did not pass a gate returns an error with details.failures and the hint hint.
Main methods
The needed permission is stated for the key's role.
Profile
| Method | Path | Description |
|---|---|---|
| GET | /api/me | The profile, role, and permissions of the key |
| GET | /api/me/my-work | The “My work” tasks |
Projects, releases, tasks
| Method | Path | Description | Permission |
|---|---|---|---|
| GET | /api/projects | The project list. Parameters q, kind, stageKey, limit, offset | Projects: view |
| POST | /api/projects | Create a project | Projects: create |
| GET | /api/projects/:id/releases | A project's releases | Releases: view |
| POST | /api/projects/:id/releases | Create a release | Releases: create |
| PATCH | /api/releases/:id | Change a release | Releases: update |
| POST | /api/releases/:id/move-stage | Move a release | Releases: update |
| GET | /api/projects/:id/tasks | A project's task tree | Tasks: view |
| POST | /api/projects/:id/tasks | Create a task | Tasks: create |
| POST | /api/releases/:id/tasks | Create a task in a release | Tasks: create |
| GET | /api/tasks/:id | Get a task | Tasks: view |
| PATCH | /api/tasks/:id | Change a task | Tasks: update |
| POST | /api/tasks/:id/move-stage | Move a task: body {"stageKey":"in_progress","confirmed":true} | Tasks: update |
| GET | /api/tasks/:id/allowed-transitions | Allowed transitions | Tasks: view |
| DELETE | /api/tasks/:id | Delete a task | Tasks: delete |
| GET | /api/search?q=… | Global search | View permissions |
Hours and comments
| Method | Path | Description |
|---|---|---|
| GET | /api/tracks | The track list |
| POST | /api/tracks | Create a track: taskId, workTypeId, description, durationMinutes, startedAt, endedAt, with the permission also userId |
| GET | /api/work-types | Work types |
| POST | /api/entity-comments | A comment: entityType (task, release, project), entityId, body |
Notifications and reports
| Method | Path | Description |
|---|---|---|
| GET | /api/notifications | The notification feed |
| POST | /api/notifications/:id/read | Mark as read |
| GET | /api/reports/tracks/duration-matrix | The “Track hours” report (.csv and .xlsx are available) |
| GET | /api/reports/tracks/time-allocation | The “Time allocation” report |
| GET | /api/resources/plan-fact?yearMonth=YYYY-MM | Plan–fact |
Examples
Create a task:
curl -X POST "https://<address>/api/projects/<PROJECT_ID>/tasks" \
-H "Authorization: Bearer thor_sk_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: crm-import-001" \
-d '{"title": "Task from CRM", "estimateMinutes": 120}'
Log time:
curl -X POST "https://<address>/api/tracks" \
-H "Authorization: Bearer thor_sk_..." \
-H "Content-Type: application/json" \
-d '{"taskId": "<TASK_ID>", "workTypeId": "<WORK_TYPE_ID>", "description": "Integration work", "durationMinutes": 60, "startedAt": "2026-10-28T09:00:00.000Z", "endedAt": "2026-10-28T10:00:00.000Z"}'
Move a task to a stage:
curl -X POST "https://<address>/api/tasks/<TASK_ID>/move-stage" \
-H "Authorization: Bearer thor_sk_..." \
-H "Content-Type: application/json" \
-d '{"stageKey": "in_progress", "confirmed": true}'
The time logging rules are the same as in the interface: “Rules and limits”.
MCP for AI assistants
The MCP server works read-only. Authorization is by an API key only. GET and DELETE requests return 405.
| Tool | What it returns |
|---|---|
whoami | The key's user, role, collections with scope |
list_fields | Task and project fields |
list_projects, get_project | Projects; a project card with the team and areas of responsibility (by projectId or prefix) |
list_tasks, get_task | Tasks across all projects with filters; a task card (by taskId or a key like RGM-30) |
list_users | Users; with projectId — the project team |
list_time_tracks | Time tracks and the total in minutes |
list_field_tracks | The history of field values |
Lists accept limit (1–100, 50 by default) and offset. Dates in responses: ISO 8601.
Webhook
A webhook is configured by a user on the profile's “Notification channels” tab: “Your notification settings”.
- Assist sends one HTTPS POST per event.
- The address must be publicly available. Private and local addresses are rejected.
- The secret is shown once on creation.
- Signature: the
X-Assist-Signatureheader containssha256=and the hexadecimal HMAC-SHA256 of the exact request body, computed with the webhook secret.
An example of signature verification (Python):
import hmac, hashlib
def is_valid(body: bytes, header: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, header)
Limitations
- Keys are created and revoked only in the interface.
- Deletion of tasks, projects, releases, and tracks is soft: records are marked as deleted.
- Stage transitions may be blocked by a gate. Pass
confirmed: trueafter the conditions are met. - Additional fields from the constructor are passed as top-level fields of the request body and are checked against the catalog and field permissions.
- The full list of methods and request body schemas is maintained by the Assist development team. Ask the administrator for the “REST API (integration)” document.