jeCheckDevelopers
Get an API key

GETList tasks

GET /tasks

Tasks visible to the token, newest first. Closed tasks are included; filter with status. Deleted tasks are never returned.

Token scoperead
Permission Any employee; results follow the token's visibility
MCP tooltasks_list · read-only

Query parameters

page integer
Page number, starting from 1. Default 1. Minimum 1.
per_page integer
Items per page (max 100). Default 25. Value 1–100.
status array<string>
Filter by status: new, in_progress, review, approval, done, rejected.
priority array<string>
Filter by priority: urgent, high, medium, low.
location_ids array<integer>
Only these locations.
assignee_id integer
Only tasks where this user is an executor.
author_id integer
Only tasks created by this user.
team_id integer
Only tasks of this team.
project_id integer
Only tasks of this project.
source string
How the task was created.
manualautohaccprequesthrprocessroutine
due_from date
Due date from (inclusive).
due_to date
Due date to (inclusive).
overdue boolean
Only open tasks past their due date.
updated_since date-time
Only tasks changed after this moment — use for incremental sync.
search string
Search in title and description. Maximum length 200.
sort string
Default created_desc.
created_desccreated_ascupdated_descdue_asc

Responses

StatusDescription
200OK — a page of results with meta
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Plan without API access
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl 'https://app.jecheck.io/api/ext/v1/tasks?assignee_id=42' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/tasks?assignee_id=42', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
  },
});
const { data, meta } = await res.json();
import os, requests

res = requests.get(
    "https://app.jecheck.io/api/ext/v1/tasks",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    params={"assignee_id":42},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);

$res = $client->request('GET', 'tasks', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'query' => [
        'assignee_id' => 42,
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "tasks_list",
        "arguments": {
            "assignee_id": 42
        }
    }
}
Response 200
{
  "data": [
    {
      "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
      "key": "OPS-42",
      "title": "Replace the broken fridge seal",
      "status": "in_progress",
      "priority": "high",
      "assignees": [
        {
          "id": 311,
          "uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
          "name": "Aigerim Sadykova"
        }
      ],
      "watchers": [],
      "author": {
        "id": 120,
        "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
        "name": "Daniyar Omarov"
      },
      "location": {
        "id": 12,
        "name": "Abay Ave"
      },
      "team_id": null,
      "project_id": null,
      "due_date": "2026-11-10",
      "tags": [
        "Equipment"
      ],
      "source": "auto",
      "needs_photo": true,
      "needs_review": true,
      "comments_count": 2,
      "files_count": 1,
      "subtasks": {
        "done": 1,
        "total": 3
      },
      "audit_id": 99812,
      "created_at": "2026-11-03T10:24:00+05:00",
      "updated_at": "2026-11-03T12:01:00+05:00",
      "completed_at": null,
      "url": "https://app.jecheck.io/ui/tasks?task=3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 25,
    "total": 1,
    "has_more": false
  }
}

GETRetrieve a task

GET /tasks/{uuid}

Full task card: description, subtasks, files (signed links valid for 1 hour), comments and the statuses the token may set now.

Token scoperead
Permission Any employee; results follow the token's visibility
MCP tooltasks_get · read-only

Path parameters

uuid uuid Required
Task UUID.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Plan without API access
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl 'https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
  },
});
const { data } = await res.json();
import os, requests

res = requests.get(
    "https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);

$res = $client->request('GET', 'tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "tasks_get",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
        }
    }
}
Response 200
{
  "data": {
    "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
    "key": "OPS-42",
    "title": "Replace the broken fridge seal",
    "status": "in_progress",
    "priority": "high",
    "assignees": [
      {
        "id": 311,
        "uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
        "name": "Aigerim Sadykova"
      }
    ],
    "watchers": [],
    "author": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "location": {
      "id": 12,
      "name": "Abay Ave"
    },
    "team_id": null,
    "project_id": null,
    "due_date": "2026-11-10",
    "tags": [
      "Equipment"
    ],
    "source": "auto",
    "needs_photo": true,
    "needs_review": true,
    "comments_count": 2,
    "files_count": 1,
    "subtasks": {
      "done": 1,
      "total": 3
    },
    "audit_id": 99812,
    "created_at": "2026-11-03T10:24:00+05:00",
    "updated_at": "2026-11-03T12:01:00+05:00",
    "completed_at": null,
    "url": "https://app.jecheck.io/ui/tasks?task=3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
    "description": "Seal on fridge #2 is torn, temperature rises to +9 °C.",
    "start_date": null,
    "estimate_minutes": null,
    "allowed_statuses": [
      "in_progress",
      "review"
    ],
    "can_delete": false,
    "audit": {
      "id": 99812,
      "checklist": "Kitchen daily check",
      "score": 82,
      "date": "2026-11-03T09:40:00+05:00"
    },
    "subtask_items": [
      {
        "id": 501,
        "title": "Order the seal",
        "done": true
      }
    ],
    "files": [
      {
        "id": 77,
        "name": "fridge.jpg",
        "size": 184220,
        "is_image": true,
        "url": "https://app.jecheck.io/ui/tasks/files/77?signature=…",
        "created_at": "2026-11-03T10:30:00+05:00"
      }
    ],
    "comments": [
      {
        "id": 9001,
        "author": {
          "id": 311,
          "uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
          "name": "Aigerim Sadykova"
        },
        "text": "Seal ordered, arrives tomorrow.",
        "file": null,
        "created_at": "2026-11-03T11:00:00+05:00"
      }
    ]
  }
}

POSTCreate a task

POST /tasks

Creates a task with the same rules as the web app: notifications go to assignees, a task with a team and no assignee lands in the team queue (auto-assignment if enabled).

Token scopewrite
Permission Any employee; results follow the token's visibility
MCP tooltasks_create
Content typemultipart/form-data application/json

Request body

title string Required
Task title. Length 2–512.
description string | null
Plain-text description. Maximum length 20000.
priority string
Priority, default medium.
urgenthighmediumlow
assignee_ids array<integer>
Executors (user ids). Maximum items 20.
watcher_ids array<integer>
Watchers (user ids). Maximum items 50.
location_id integer | null
Location id. Must be one of the locations where the token may create tasks.
team_id integer | null
Team (department) id — the task goes to the team queue if no assignee.
due_date date | null
Due date, YYYY-MM-DD.
tags array<string>
Tags, up to 10. Maximum items 10.
project_id integer | null
Project id (requires editor role in the project).
start_date date | null
Start date (projects, Gantt).
estimate_minutes integer | null
Estimate, minutes. Value 0–100000.
status string
Initial status, default new.
newin_progressreviewdonerejected
subtasks array<string>
Checklist items to create with the task. Maximum items 50.
files array<file>
Attachments (multipart files[]; in MCP — objects with name and content_base64). Maximum items 10.

Responses

StatusDescription
201Created
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X POST 'https://app.jecheck.io/api/ext/v1/tasks' \
  -H 'Authorization: Bearer $JECHECK_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "Replace the broken fridge seal",
    "description": "Seal on fridge #2 is torn, temperature rises to +9 °C.",
    "priority": "urgent",
    "assignee_ids": [
        12,
        14
    ]
}'
const res = await fetch('https://app.jecheck.io/api/ext/v1/tasks', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "title": "Replace the broken fridge seal",
      "description": "Seal on fridge #2 is torn, temperature rises to +9 °C.",
      "priority": "urgent",
      "assignee_ids": [
          12,
          14
      ]
  }),
});
const { data } = await res.json();
import os, requests

res = requests.post(
    "https://app.jecheck.io/api/ext/v1/tasks",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    json={"title":"Replace the broken fridge seal","description":"Seal on fridge #2 is torn, temperature rises to +9 °C.","priority":"urgent","assignee_ids":[12,14]},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);

$res = $client->request('POST', 'tasks', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'json' => [
        'title' => 'Replace the broken fridge seal',
        'description' => 'Seal on fridge #2 is torn, temperature rises to +9 °C.',
        'priority' => 'urgent',
        'assignee_ids' => [
            12,
            14,
        ],
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "tasks_create",
        "arguments": {
            "title": "Replace the broken fridge seal",
            "description": "Seal on fridge #2 is torn, temperature rises to +9 °C.",
            "priority": "urgent",
            "assignee_ids": [
                12,
                14
            ]
        }
    }
}
Response 201
{
  "data": {
    "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
    "key": "OPS-42",
    "title": "Replace the broken fridge seal",
    "status": "in_progress",
    "priority": "high",
    "assignees": [
      {
        "id": 311,
        "uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
        "name": "Aigerim Sadykova"
      }
    ],
    "watchers": [],
    "author": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "location": {
      "id": 12,
      "name": "Abay Ave"
    },
    "team_id": null,
    "project_id": null,
    "due_date": "2026-11-10",
    "tags": [
      "Equipment"
    ],
    "source": "auto",
    "needs_photo": true,
    "needs_review": true,
    "comments_count": 2,
    "files_count": 1,
    "subtasks": {
      "done": 1,
      "total": 3
    },
    "audit_id": 99812,
    "created_at": "2026-11-03T10:24:00+05:00",
    "updated_at": "2026-11-03T12:01:00+05:00",
    "completed_at": null,
    "url": "https://app.jecheck.io/ui/tasks?task=3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
    "description": "Seal on fridge #2 is torn, temperature rises to +9 °C.",
    "start_date": null,
    "estimate_minutes": null,
    "allowed_statuses": [
      "in_progress",
      "review"
    ],
    "can_delete": false,
    "audit": {
      "id": 99812,
      "checklist": "Kitchen daily check",
      "score": 82,
      "date": "2026-11-03T09:40:00+05:00"
    },
    "subtask_items": [
      {
        "id": 501,
        "title": "Order the seal",
        "done": true
      }
    ],
    "files": [
      {
        "id": 77,
        "name": "fridge.jpg",
        "size": 184220,
        "is_image": true,
        "url": "https://app.jecheck.io/ui/tasks/files/77?signature=…",
        "created_at": "2026-11-03T10:30:00+05:00"
      }
    ],
    "comments": [
      {
        "id": 9001,
        "author": {
          "id": 311,
          "uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
          "name": "Aigerim Sadykova"
        },
        "text": "Seal ordered, arrives tomorrow.",
        "file": null,
        "created_at": "2026-11-03T11:00:00+05:00"
      }
    ]
  }
}

PATCHUpdate a task

PATCH /tasks/{uuid}

Partial update: send only the fields to change. Arrays (assignee_ids, watcher_ids, tags) replace the current values.

Token scopewrite
Permission Any employee; results follow the token's visibility
MCP tooltasks_update

Path parameters

uuid uuid Required
Task UUID.

Request body

title string
Task title. Length 2–512.
description string | null
Plain-text description. Maximum length 20000.
priority string
Priority.
urgenthighmediumlow
assignee_ids array<integer>
Executors (user ids). Maximum items 20.
watcher_ids array<integer>
Watchers (user ids). Maximum items 50.
location_id integer | null
Location id. Must be one of the locations where the token may create tasks.
team_id integer | null
Team (department) id — the task goes to the team queue if no assignee.
due_date date | null
Due date, YYYY-MM-DD.
tags array<string>
Tags, up to 10. Maximum items 10.
project_id integer | null
Project id (requires editor role in the project).
start_date date | null
Start date (projects, Gantt).
estimate_minutes integer | null
Estimate, minutes. Value 0–100000.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X PATCH 'https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b' \
  -H 'Authorization: Bearer $JECHECK_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "Replace the broken fridge seal",
    "description": "Seal on fridge #2 is torn, temperature rises to +9 °C.",
    "priority": "urgent",
    "assignee_ids": [
        12,
        14
    ]
}'
const res = await fetch('https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "title": "Replace the broken fridge seal",
      "description": "Seal on fridge #2 is torn, temperature rises to +9 °C.",
      "priority": "urgent",
      "assignee_ids": [
          12,
          14
      ]
  }),
});
const { data } = await res.json();
import os, requests

res = requests.patch(
    "https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    json={"title":"Replace the broken fridge seal","description":"Seal on fridge #2 is torn, temperature rises to +9 °C.","priority":"urgent","assignee_ids":[12,14]},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);

$res = $client->request('PATCH', 'tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'json' => [
        'title' => 'Replace the broken fridge seal',
        'description' => 'Seal on fridge #2 is torn, temperature rises to +9 °C.',
        'priority' => 'urgent',
        'assignee_ids' => [
            12,
            14,
        ],
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "tasks_update",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
            "title": "Replace the broken fridge seal",
            "description": "Seal on fridge #2 is torn, temperature rises to +9 °C.",
            "priority": "urgent",
            "assignee_ids": [
                12,
                14
            ]
        }
    }
}
Response 200
{
  "data": {
    "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
    "key": "OPS-42",
    "title": "Replace the broken fridge seal",
    "status": "in_progress",
    "priority": "high",
    "assignees": [
      {
        "id": 311,
        "uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
        "name": "Aigerim Sadykova"
      }
    ],
    "watchers": [],
    "author": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "location": {
      "id": 12,
      "name": "Abay Ave"
    },
    "team_id": null,
    "project_id": null,
    "due_date": "2026-11-10",
    "tags": [
      "Equipment"
    ],
    "source": "auto",
    "needs_photo": true,
    "needs_review": true,
    "comments_count": 2,
    "files_count": 1,
    "subtasks": {
      "done": 1,
      "total": 3
    },
    "audit_id": 99812,
    "created_at": "2026-11-03T10:24:00+05:00",
    "updated_at": "2026-11-03T12:01:00+05:00",
    "completed_at": null,
    "url": "https://app.jecheck.io/ui/tasks?task=3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
    "description": "Seal on fridge #2 is torn, temperature rises to +9 °C.",
    "start_date": null,
    "estimate_minutes": null,
    "allowed_statuses": [
      "in_progress",
      "review"
    ],
    "can_delete": false,
    "audit": {
      "id": 99812,
      "checklist": "Kitchen daily check",
      "score": 82,
      "date": "2026-11-03T09:40:00+05:00"
    },
    "subtask_items": [
      {
        "id": 501,
        "title": "Order the seal",
        "done": true
      }
    ],
    "files": [
      {
        "id": 77,
        "name": "fridge.jpg",
        "size": 184220,
        "is_image": true,
        "url": "https://app.jecheck.io/ui/tasks/files/77?signature=…",
        "created_at": "2026-11-03T10:30:00+05:00"
      }
    ],
    "comments": [
      {
        "id": 9001,
        "author": {
          "id": 311,
          "uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
          "name": "Aigerim Sadykova"
        },
        "text": "Seal ordered, arrives tomorrow.",
        "file": null,
        "created_at": "2026-11-03T11:00:00+05:00"
      }
    ]
  }
}

POSTChange task status

POST /tasks/{uuid}/status

Moves the task to another status. Tasks of the corrective-action loop allow only allowed_statuses from the task card (e.g. a photo "after" is required before review). approval is set by process routes only.

Token scopewrite
Permission Any employee; results follow the token's visibility
MCP tooltasks_status

Path parameters

uuid uuid Required
Task UUID.

Request body

status string Required
newin_progressreviewdonerejected

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
404not_found — The record does not exist or is not visible to the token
422validation_failed — The transition is not allowed for this task (see allowed_statuses)
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X POST 'https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/status' \
  -H 'Authorization: Bearer $JECHECK_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "status": "new"
}'
const res = await fetch('https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/status', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "status": "new"
  }),
});
const { data } = await res.json();
import os, requests

res = requests.post(
    "https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/status",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    json={"status":"new"},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);

$res = $client->request('POST', 'tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/status', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'json' => [
        'status' => 'new',
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "tasks_status",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
            "status": "new"
        }
    }
}
Response 200
{
  "data": {
    "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
    "key": "OPS-42",
    "title": "Replace the broken fridge seal",
    "status": "in_progress",
    "priority": "high",
    "assignees": [
      {
        "id": 311,
        "uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
        "name": "Aigerim Sadykova"
      }
    ],
    "watchers": [],
    "author": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "location": {
      "id": 12,
      "name": "Abay Ave"
    },
    "team_id": null,
    "project_id": null,
    "due_date": "2026-11-10",
    "tags": [
      "Equipment"
    ],
    "source": "auto",
    "needs_photo": true,
    "needs_review": true,
    "comments_count": 2,
    "files_count": 1,
    "subtasks": {
      "done": 1,
      "total": 3
    },
    "audit_id": 99812,
    "created_at": "2026-11-03T10:24:00+05:00",
    "updated_at": "2026-11-03T12:01:00+05:00",
    "completed_at": null,
    "url": "https://app.jecheck.io/ui/tasks?task=3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
    "description": "Seal on fridge #2 is torn, temperature rises to +9 °C.",
    "start_date": null,
    "estimate_minutes": null,
    "allowed_statuses": [
      "in_progress",
      "review"
    ],
    "can_delete": false,
    "audit": {
      "id": 99812,
      "checklist": "Kitchen daily check",
      "score": 82,
      "date": "2026-11-03T09:40:00+05:00"
    },
    "subtask_items": [
      {
        "id": 501,
        "title": "Order the seal",
        "done": true
      }
    ],
    "files": [
      {
        "id": 77,
        "name": "fridge.jpg",
        "size": 184220,
        "is_image": true,
        "url": "https://app.jecheck.io/ui/tasks/files/77?signature=…",
        "created_at": "2026-11-03T10:30:00+05:00"
      }
    ],
    "comments": [
      {
        "id": 9001,
        "author": {
          "id": 311,
          "uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
          "name": "Aigerim Sadykova"
        },
        "text": "Seal ordered, arrives tomorrow.",
        "file": null,
        "created_at": "2026-11-03T11:00:00+05:00"
      }
    ]
  }
}

DELDelete a task

DELETE /tasks/{uuid}

Soft-deletes the task. Allowed to the author or with the tasks.delete permission.

Token scopewrite
Permission Any employee; results follow the token's visibility
MCP tooltasks_delete · destructive

Path parameters

uuid uuid Required
Task UUID.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
  },
});
const { data } = await res.json();
import os, requests

res = requests.delete(
    "https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);

$res = $client->request('DELETE', 'tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "tasks_delete",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
        }
    }
}
Response 200
{
  "data": {
    "deleted": true
  }
}

POSTDuplicate a task

POST /tasks/{uuid}/duplicate
Token scopewrite
Permission Any employee; results follow the token's visibility
MCP tooltasks_duplicate

Path parameters

uuid uuid Required
Task UUID.

Responses

StatusDescription
201Created
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X POST 'https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/duplicate' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/duplicate', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
  },
});
const { data } = await res.json();
import os, requests

res = requests.post(
    "https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/duplicate",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);

$res = $client->request('POST', 'tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/duplicate', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "tasks_duplicate",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
        }
    }
}
Response 201
{
  "data": {
    "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
    "key": "OPS-42",
    "title": "Replace the broken fridge seal",
    "status": "in_progress",
    "priority": "high",
    "assignees": [
      {
        "id": 311,
        "uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
        "name": "Aigerim Sadykova"
      }
    ],
    "watchers": [],
    "author": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "location": {
      "id": 12,
      "name": "Abay Ave"
    },
    "team_id": null,
    "project_id": null,
    "due_date": "2026-11-10",
    "tags": [
      "Equipment"
    ],
    "source": "auto",
    "needs_photo": true,
    "needs_review": true,
    "comments_count": 2,
    "files_count": 1,
    "subtasks": {
      "done": 1,
      "total": 3
    },
    "audit_id": 99812,
    "created_at": "2026-11-03T10:24:00+05:00",
    "updated_at": "2026-11-03T12:01:00+05:00",
    "completed_at": null,
    "url": "https://app.jecheck.io/ui/tasks?task=3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
    "description": "Seal on fridge #2 is torn, temperature rises to +9 °C.",
    "start_date": null,
    "estimate_minutes": null,
    "allowed_statuses": [
      "in_progress",
      "review"
    ],
    "can_delete": false,
    "audit": {
      "id": 99812,
      "checklist": "Kitchen daily check",
      "score": 82,
      "date": "2026-11-03T09:40:00+05:00"
    },
    "subtask_items": [
      {
        "id": 501,
        "title": "Order the seal",
        "done": true
      }
    ],
    "files": [
      {
        "id": 77,
        "name": "fridge.jpg",
        "size": 184220,
        "is_image": true,
        "url": "https://app.jecheck.io/ui/tasks/files/77?signature=…",
        "created_at": "2026-11-03T10:30:00+05:00"
      }
    ],
    "comments": [
      {
        "id": 9001,
        "author": {
          "id": 311,
          "uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
          "name": "Aigerim Sadykova"
        },
        "text": "Seal ordered, arrives tomorrow.",
        "file": null,
        "created_at": "2026-11-03T11:00:00+05:00"
      }
    ]
  }
}

POSTTake a task from the team queue

POST /tasks/{uuid}/take

Assigns a queued team task to the acting user (must be a member of the team).

Token scopewrite
Permission Any employee; results follow the token's visibility
MCP tooltasks_take

Path parameters

uuid uuid Required
Task UUID.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X POST 'https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/take' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/take', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
  },
});
const { data } = await res.json();
import os, requests

res = requests.post(
    "https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/take",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);

$res = $client->request('POST', 'tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/take', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "tasks_take",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
        }
    }
}
Response 200
{
  "data": {
    "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
    "key": "OPS-42",
    "title": "Replace the broken fridge seal",
    "status": "in_progress",
    "priority": "high",
    "assignees": [
      {
        "id": 311,
        "uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
        "name": "Aigerim Sadykova"
      }
    ],
    "watchers": [],
    "author": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "location": {
      "id": 12,
      "name": "Abay Ave"
    },
    "team_id": null,
    "project_id": null,
    "due_date": "2026-11-10",
    "tags": [
      "Equipment"
    ],
    "source": "auto",
    "needs_photo": true,
    "needs_review": true,
    "comments_count": 2,
    "files_count": 1,
    "subtasks": {
      "done": 1,
      "total": 3
    },
    "audit_id": 99812,
    "created_at": "2026-11-03T10:24:00+05:00",
    "updated_at": "2026-11-03T12:01:00+05:00",
    "completed_at": null,
    "url": "https://app.jecheck.io/ui/tasks?task=3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
    "description": "Seal on fridge #2 is torn, temperature rises to +9 °C.",
    "start_date": null,
    "estimate_minutes": null,
    "allowed_statuses": [
      "in_progress",
      "review"
    ],
    "can_delete": false,
    "audit": {
      "id": 99812,
      "checklist": "Kitchen daily check",
      "score": 82,
      "date": "2026-11-03T09:40:00+05:00"
    },
    "subtask_items": [
      {
        "id": 501,
        "title": "Order the seal",
        "done": true
      }
    ],
    "files": [
      {
        "id": 77,
        "name": "fridge.jpg",
        "size": 184220,
        "is_image": true,
        "url": "https://app.jecheck.io/ui/tasks/files/77?signature=…",
        "created_at": "2026-11-03T10:30:00+05:00"
      }
    ],
    "comments": [
      {
        "id": 9001,
        "author": {
          "id": 311,
          "uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
          "name": "Aigerim Sadykova"
        },
        "text": "Seal ordered, arrives tomorrow.",
        "file": null,
        "created_at": "2026-11-03T11:00:00+05:00"
      }
    ]
  }
}

POSTBulk update tasks

POST /tasks/bulk

Applies the same change to up to 200 tasks. Tasks that cannot be changed (rules of the loop, permissions) are skipped; the response says how many were updated.

Token scopewrite
Permission Any employee; results follow the token's visibility
MCP tooltasks_bulk · destructive

Request body

uuids array<string> Required
Task UUIDs. Items 1–200.
status string
newin_progressreviewdonerejected
priority string
urgenthighmediumlow
due_date date | null
assignee_ids array<integer>
Maximum items 20.
location_id integer | null
team_id integer | null
delete boolean
Delete the tasks instead of updating.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X POST 'https://app.jecheck.io/api/ext/v1/tasks/bulk' \
  -H 'Authorization: Bearer $JECHECK_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "uuids": [
        "example"
    ],
    "status": "new",
    "priority": "urgent",
    "due_date": "2026-11-01"
}'
const res = await fetch('https://app.jecheck.io/api/ext/v1/tasks/bulk', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "uuids": [
          "example"
      ],
      "status": "new",
      "priority": "urgent",
      "due_date": "2026-11-01"
  }),
});
const { data } = await res.json();
import os, requests

res = requests.post(
    "https://app.jecheck.io/api/ext/v1/tasks/bulk",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    json={"uuids":["example"],"status":"new","priority":"urgent","due_date":"2026-11-01"},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);

$res = $client->request('POST', 'tasks/bulk', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'json' => [
        'uuids' => [
            'example',
        ],
        'status' => 'new',
        'priority' => 'urgent',
        'due_date' => '2026-11-01',
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "tasks_bulk",
        "arguments": {
            "uuids": [
                "example"
            ],
            "status": "new",
            "priority": "urgent",
            "due_date": "2026-11-01"
        }
    }
}
Response 200
{
  "data": {
    "updated": 18,
    "requested": 20
  }
}

GETGet task history

GET /tasks/{uuid}/history

Audit trail of the task: creation, status changes, reassignment, due date changes, comments by automation.

Token scoperead
Permission Any employee; results follow the token's visibility
MCP tooltasks_history · read-only

Path parameters

uuid uuid Required
Task UUID.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Plan without API access
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl 'https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/history' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/history', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
  },
});
const { data } = await res.json();
import os, requests

res = requests.get(
    "https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/history",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);

$res = $client->request('GET', 'tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/history', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "tasks_history",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
        }
    }
}
Response 200
{
  "data": [
    {
      "type": "status",
      "payload": {
        "from": "new",
        "to": "in_progress"
      },
      "actor": "user",
      "user": "Aigerim Sadykova",
      "created_at": "2026-11-03T11:00:00+05:00"
    }
  ]
}

GETList task comments

GET /tasks/{uuid}/comments
Token scoperead
Permission Any employee; results follow the token's visibility
MCP tooltasks_comments_list · read-only

Path parameters

uuid uuid Required
Task UUID.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Plan without API access
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl 'https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/comments' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/comments', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
  },
});
const { data } = await res.json();
import os, requests

res = requests.get(
    "https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/comments",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);

$res = $client->request('GET', 'tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/comments', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "tasks_comments_list",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
        }
    }
}
Response 200
{
  "data": [
    {
      "id": 9001,
      "author": {
        "id": 311,
        "uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
        "name": "Aigerim Sadykova"
      },
      "text": "Seal ordered, arrives tomorrow.",
      "file": null,
      "created_at": "2026-11-03T11:00:00+05:00"
    }
  ]
}

POSTAdd a comment

POST /tasks/{uuid}/comments

Adds a comment from the acting user. Participants are notified as in the web app.

Token scopewrite
Permission Any employee; results follow the token's visibility
MCP tooltasks_comments_create

Path parameters

uuid uuid Required
Task UUID.

Request body

text string Required
Length 1–10000.

Responses

StatusDescription
201Created
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X POST 'https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/comments' \
  -H 'Authorization: Bearer $JECHECK_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "text": "Seal on fridge #2 is torn, temperature rises to +9 °C."
}'
const res = await fetch('https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/comments', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "text": "Seal on fridge #2 is torn, temperature rises to +9 °C."
  }),
});
const { data } = await res.json();
import os, requests

res = requests.post(
    "https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/comments",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    json={"text":"Seal on fridge #2 is torn, temperature rises to +9 °C."},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);

$res = $client->request('POST', 'tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/comments', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'json' => [
        'text' => 'Seal on fridge #2 is torn, temperature rises to +9 °C.',
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "tasks_comments_create",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
            "text": "Seal on fridge #2 is torn, temperature rises to +9 °C."
        }
    }
}
Response 201
{
  "data": {
    "id": 9001,
    "author": {
      "id": 311,
      "uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
      "name": "Aigerim Sadykova"
    },
    "text": "Seal ordered, arrives tomorrow.",
    "file": null,
    "created_at": "2026-11-03T11:00:00+05:00"
  }
}

PATCHEdit a comment

PATCH /tasks/comments/{id}

Only the author of the comment can edit it.

Token scopewrite
Permission Any employee; results follow the token's visibility
MCP tooltasks_comments_update

Path parameters

id integer Required
Comment id.

Request body

text string Required
Length 1–10000.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X PATCH 'https://app.jecheck.io/api/ext/v1/tasks/comments/42' \
  -H 'Authorization: Bearer $JECHECK_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "text": "Seal on fridge #2 is torn, temperature rises to +9 °C."
}'
const res = await fetch('https://app.jecheck.io/api/ext/v1/tasks/comments/42', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "text": "Seal on fridge #2 is torn, temperature rises to +9 °C."
  }),
});
const { data } = await res.json();
import os, requests

res = requests.patch(
    "https://app.jecheck.io/api/ext/v1/tasks/comments/42",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    json={"text":"Seal on fridge #2 is torn, temperature rises to +9 °C."},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);

$res = $client->request('PATCH', 'tasks/comments/42', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'json' => [
        'text' => 'Seal on fridge #2 is torn, temperature rises to +9 °C.',
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "tasks_comments_update",
        "arguments": {
            "id": 42,
            "text": "Seal on fridge #2 is torn, temperature rises to +9 °C."
        }
    }
}
Response 200
{
  "data": {
    "id": 9001,
    "author": {
      "id": 311,
      "uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
      "name": "Aigerim Sadykova"
    },
    "text": "Seal ordered, arrives tomorrow.",
    "file": null,
    "created_at": "2026-11-03T11:00:00+05:00"
  }
}

DELDelete a comment

DELETE /tasks/comments/{id}
Token scopewrite
Permission Any employee; results follow the token's visibility
MCP tooltasks_comments_delete · destructive

Path parameters

id integer Required
Comment id.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/tasks/comments/42' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/tasks/comments/42', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
  },
});
const { data } = await res.json();
import os, requests

res = requests.delete(
    "https://app.jecheck.io/api/ext/v1/tasks/comments/42",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);

$res = $client->request('DELETE', 'tasks/comments/42', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "tasks_comments_delete",
        "arguments": {
            "id": 42
        }
    }
}
Response 200
{
  "data": {
    "deleted": true
  }
}

POSTAdd a subtask

POST /tasks/{uuid}/subtasks
Token scopewrite
Permission Any employee; results follow the token's visibility
MCP tooltasks_subtasks_create

Path parameters

uuid uuid Required
Task UUID.

Request body

title string Required
Length 1–500.

Responses

StatusDescription
201Created
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X POST 'https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/subtasks' \
  -H 'Authorization: Bearer $JECHECK_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "Replace the broken fridge seal"
}'
const res = await fetch('https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/subtasks', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "title": "Replace the broken fridge seal"
  }),
});
const { data } = await res.json();
import os, requests

res = requests.post(
    "https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/subtasks",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    json={"title":"Replace the broken fridge seal"},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);

$res = $client->request('POST', 'tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/subtasks', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'json' => [
        'title' => 'Replace the broken fridge seal',
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "tasks_subtasks_create",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
            "title": "Replace the broken fridge seal"
        }
    }
}
Response 201
{
  "data": {
    "id": 502,
    "title": "Install the seal",
    "done": false
  }
}

PATCHUpdate a subtask

PATCH /tasks/subtasks/{id}

Rename a subtask or mark it done / not done.

Token scopewrite
Permission Any employee; results follow the token's visibility
MCP tooltasks_subtasks_update

Path parameters

id integer Required
Subtask id.

Request body

title string
Length 1–500.
done boolean

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X PATCH 'https://app.jecheck.io/api/ext/v1/tasks/subtasks/42' \
  -H 'Authorization: Bearer $JECHECK_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "Replace the broken fridge seal",
    "done": true
}'
const res = await fetch('https://app.jecheck.io/api/ext/v1/tasks/subtasks/42', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "title": "Replace the broken fridge seal",
      "done": true
  }),
});
const { data } = await res.json();
import os, requests

res = requests.patch(
    "https://app.jecheck.io/api/ext/v1/tasks/subtasks/42",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    json={"title":"Replace the broken fridge seal","done":True},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);

$res = $client->request('PATCH', 'tasks/subtasks/42', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'json' => [
        'title' => 'Replace the broken fridge seal',
        'done' => true,
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "tasks_subtasks_update",
        "arguments": {
            "id": 42,
            "title": "Replace the broken fridge seal",
            "done": true
        }
    }
}
Response 200
{
  "data": {
    "id": 502,
    "title": "Install the seal",
    "done": true
  }
}

DELDelete a subtask

DELETE /tasks/subtasks/{id}
Token scopewrite
Permission Any employee; results follow the token's visibility
MCP tooltasks_subtasks_delete · destructive

Path parameters

id integer Required
Subtask id.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/tasks/subtasks/42' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/tasks/subtasks/42', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
  },
});
const { data } = await res.json();
import os, requests

res = requests.delete(
    "https://app.jecheck.io/api/ext/v1/tasks/subtasks/42",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);

$res = $client->request('DELETE', 'tasks/subtasks/42', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "tasks_subtasks_delete",
        "arguments": {
            "id": 42
        }
    }
}
Response 200
{
  "data": {
    "deleted": true
  }
}

GETList task files

GET /tasks/{uuid}/files

Attachments with signed download links (valid for 1 hour, no token needed).

Token scoperead
Permission Any employee; results follow the token's visibility
MCP tooltasks_files_list · read-only

Path parameters

uuid uuid Required
Task UUID.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Plan without API access
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl 'https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/files' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/files', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
  },
});
const { data } = await res.json();
import os, requests

res = requests.get(
    "https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/files",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);

$res = $client->request('GET', 'tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/files', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "tasks_files_list",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
        }
    }
}
Response 200
{
  "data": [
    {
      "id": 77,
      "name": "fridge.jpg",
      "size": 184220,
      "is_image": true,
      "url": "https://app.jecheck.io/ui/tasks/files/77?signature=…",
      "created_at": "2026-11-03T10:30:00+05:00"
    }
  ]
}

POSTUpload files to a task

POST /tasks/{uuid}/files

Multipart upload, field files[], up to 10 files. In MCP pass files as objects with name and content_base64.

Token scopewrite
Permission Any employee; results follow the token's visibility
MCP tooltasks_files_upload
Content typemultipart/form-data application/json

Path parameters

uuid uuid Required
Task UUID.

Request body

files array<file> Required
Items 1–10.

Responses

StatusDescription
201Created
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X POST 'https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/files' \
  -H 'Authorization: Bearer $JECHECK_TOKEN' \
  -F 'files[][email protected]'
const form = new FormData();
form.append('files[]', fileInput.files[0]);

const res = await fetch('https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/files', {
  method: 'POST',
  headers: { Authorization: `Bearer ${process.env.JECHECK_TOKEN}` },
  body: form,
});
const { data } = await res.json();
import os, requests

res = requests.post(
    "https://app.jecheck.io/api/ext/v1/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/files",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    data=[],
    files=[("files[]", open("photo.jpg", "rb"))],
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);

$res = $client->request('POST', 'tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/files', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'multipart' => [
        ['name' => 'files[]', 'contents' => fopen('photo.jpg', 'r')],
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "tasks_files_upload",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
        }
    }
}
Response 201
{
  "data": [
    {
      "id": 77,
      "name": "fridge.jpg",
      "size": 184220,
      "is_image": true,
      "url": "https://app.jecheck.io/ui/tasks/files/77?signature=…",
      "created_at": "2026-11-03T10:30:00+05:00"
    }
  ]
}

DELDelete a task file

DELETE /tasks/files/{id}
Token scopewrite
Permission Any employee; results follow the token's visibility
MCP tooltasks_files_delete · destructive

Path parameters

id integer Required
File id.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/tasks/files/42' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/tasks/files/42', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
  },
});
const { data } = await res.json();
import os, requests

res = requests.delete(
    "https://app.jecheck.io/api/ext/v1/tasks/files/42",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);

$res = $client->request('DELETE', 'tasks/files/42', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "tasks_files_delete",
        "arguments": {
            "id": 42
        }
    }
}
Response 200
{
  "data": {
    "deleted": true
  }
}

GETList task tags

GET /tasks/tags

Tag suggestions and tags already used in the company.

Token scoperead
Permission Any employee; results follow the token's visibility
MCP tooltasks_tags · read-only

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Plan without API access
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl 'https://app.jecheck.io/api/ext/v1/tasks/tags' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/tasks/tags', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
  },
});
const { data } = await res.json();
import os, requests

res = requests.get(
    "https://app.jecheck.io/api/ext/v1/tasks/tags",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);

$res = $client->request('GET', 'tasks/tags', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "tasks_tags",
        "arguments": {}
    }
}
Response 200
{
  "data": [
    "Equipment",
    "Kitchen",
    "Cleaning"
  ]
}