Projects
Projects with task numbers (KEY-N), sections, board columns, milestones, custom fields, members with project roles, external guests, status updates and automation rules. Access follows the project role (viewer, commenter, editor, admin); projects.manage acts as admin in every project. Tasks themselves are managed in the Tasks section with project_id.
GETList projects
Projects the token can open: where it is a member or owner, projects open to the whole company, and with projects.manage — all projects. Ordered by status (active first), then by last change.
| Token scope | read |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_list · read-only |
Query parameters
page
integer
1. Minimum 1.
per_page
integer
25. Value 1–100.
status
array<string>
starred
boolean
member
boolean
search
string
Responses
| Status | Description |
|---|---|
| 200 | OK — a page of results with meta |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Plan without API access
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl 'https://app.jecheck.io/api/ext/v1/projects?starred=true' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects?starred=true', {
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/projects",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
params={"starred":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('GET', 'projects', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'query' => [
'starred' => true,
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_list",
"arguments": {
"starred": true
}
}
}{
"data": [
{
"id": 58,
"uuid": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
"key": "OPEN",
"name": "Opening: Abay Ave",
"description": "Launch of the new coffee shop on Abay Ave.",
"icon": "rocket_launch",
"color": "#5b54e8",
"status": "active",
"health": "on_track",
"visibility": "members",
"start_date": "2026-11-01",
"due_date": "2026-12-15",
"owner": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"role": "admin",
"created_at": "2026-10-28T09:00:00+05:00",
"updated_at": "2026-11-03T12:10:00+05:00",
"url": "https://app.jecheck.io/ui/projects/8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
"stats": {
"total": 42,
"done": 18,
"open": 23,
"overdue": 3,
"progress": 44
},
"members_count": 6,
"guests_count": 1,
"starred": true,
"last_update_at": "2026-11-02T18:00:00+05:00"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 1,
"has_more": false
}
}GETList project templates
Built-in templates and the company's own templates (saved from projects). Pass the template id as template when creating a project. Company templates are listed only with projects.create.
| Token scope | read |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_templates_list · read-only |
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Plan without API access
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl 'https://app.jecheck.io/api/ext/v1/projects/templates' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/templates', {
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/projects/templates",
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', 'projects/templates', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_templates_list",
"arguments": {}
}
}{
"data": [
{
"id": "opening",
"name": "Opening a new location",
"description": "Everything from lease to soft opening",
"icon": "storefront",
"company": false,
"tasks_count": 34,
"days": 60
}
]
}GETRetrieve a project
Project card with the acting user's role and permissions, sections, board columns, milestones, custom fields, members, guests (only for project admins with projects.guests) and progress figures.
| Token scope | read |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_get · read-only |
Path parameters
uuid
uuid
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Plan without API access
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/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/projects/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', 'projects/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": "projects_get",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
}
}
}{
"data": {
"id": 58,
"uuid": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
"key": "OPEN",
"name": "Opening: Abay Ave",
"description": "Launch of the new coffee shop on Abay Ave.",
"icon": "rocket_launch",
"color": "#5b54e8",
"status": "active",
"health": "on_track",
"visibility": "members",
"start_date": "2026-11-01",
"due_date": "2026-12-15",
"owner": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"role": "admin",
"created_at": "2026-10-28T09:00:00+05:00",
"updated_at": "2026-11-03T12:10:00+05:00",
"url": "https://app.jecheck.io/ui/projects/8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
"completed_at": null,
"starred": true,
"settings": {
"guest_scope": "all",
"time_tracking": true
},
"permissions": {
"edit": true,
"comment": true,
"manage": true,
"invite_guests": true,
"join": false
},
"sections": [
{
"id": 201,
"name": "Equipment"
}
],
"columns": [
{
"id": 301,
"name": "In progress",
"status": "in_progress",
"color": "#f59e0b",
"wip_limit": 5
}
],
"milestones": [
{
"id": 401,
"title": "Soft opening",
"description": "",
"due_date": "2026-12-01",
"done": false
}
],
"fields": [
{
"id": 501,
"name": "Supplier",
"type": "select",
"options": [
{
"id": "o_k2m9qa",
"label": "Metro",
"color": "#22c55e"
}
],
"on_card": true
}
],
"members": [
{
"user": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"role": "admin"
}
],
"guests": [
{
"id": 12,
"name": "Ivan Petrov",
"email": "[email protected]",
"company": "BuildCo",
"role": "editor",
"tasks_count": 4,
"last_seen_at": "2026-11-02T15:30:00+05:00",
"invited_at": "2026-10-29T10:00:00+05:00",
"url": "https://app.jecheck.io/pg/Ab12Cd34Ef56Gh78Ij90Kl12Mn34Op56"
}
],
"stats": {
"total": 42,
"done": 18,
"open": 23,
"overdue": 3,
"unassigned": 2,
"progress": 44,
"forecast": "2026-12-20"
}
}
}POSTCreate a project
Creates a project, empty or from a template (see projects.templates.list). The creator and the owner become project admins. Requires projects.create.
| Token scope | write |
|---|---|
| Permission |
projects.create |
| MCP tool | projects_create |
Request body
name
string
Required key
string
OPEN). Generated from the name if omitted.
Maximum length 10. description
string | null
icon
string
rocket_launch.
Maximum length 40. color
string
#5b54e8.
Maximum length 9. visibility
string
members — only members see the project; company — every employee can open it and join.
memberscompanystart_date
date | null
due_date
date | null
owner_id
integer
template
string
members
array<object>
user_id
integer
Required role
string
editor.
admineditorcommenterviewerResponses
| Status | Description |
|---|---|
| 201 | Created |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks projects.create, is read-only
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/projects' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "Replace the broken fridge seal",
"key": "string",
"description": "Seal on fridge #2 is torn, temperature rises to +9 °C.",
"icon": "string"
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Replace the broken fridge seal",
"key": "string",
"description": "Seal on fridge #2 is torn, temperature rises to +9 °C.",
"icon": "string"
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/projects",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"name":"Replace the broken fridge seal","key":"string","description":"Seal on fridge #2 is torn, temperature rises to +9 °C.","icon":"string"},
)
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', 'projects', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'name' => 'Replace the broken fridge seal',
'key' => 'string',
'description' => 'Seal on fridge #2 is torn, temperature rises to +9 °C.',
'icon' => 'string',
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_create",
"arguments": {
"name": "Replace the broken fridge seal",
"key": "string",
"description": "Seal on fridge #2 is torn, temperature rises to +9 °C.",
"icon": "string"
}
}
}{
"data": {
"id": 58,
"uuid": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
"key": "OPEN",
"name": "Opening: Abay Ave",
"description": "Launch of the new coffee shop on Abay Ave.",
"icon": "rocket_launch",
"color": "#5b54e8",
"status": "active",
"health": "on_track",
"visibility": "members",
"start_date": "2026-11-01",
"due_date": "2026-12-15",
"owner": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"role": "admin",
"created_at": "2026-10-28T09:00:00+05:00",
"updated_at": "2026-11-03T12:10:00+05:00",
"url": "https://app.jecheck.io/ui/projects/8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
"completed_at": null,
"starred": true,
"settings": {
"guest_scope": "all",
"time_tracking": true
},
"permissions": {
"edit": true,
"comment": true,
"manage": true,
"invite_guests": true,
"join": false
},
"sections": [
{
"id": 201,
"name": "Equipment"
}
],
"columns": [
{
"id": 301,
"name": "In progress",
"status": "in_progress",
"color": "#f59e0b",
"wip_limit": 5
}
],
"milestones": [
{
"id": 401,
"title": "Soft opening",
"description": "",
"due_date": "2026-12-01",
"done": false
}
],
"fields": [
{
"id": 501,
"name": "Supplier",
"type": "select",
"options": [
{
"id": "o_k2m9qa",
"label": "Metro",
"color": "#22c55e"
}
],
"on_card": true
}
],
"members": [
{
"user": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"role": "admin"
}
],
"guests": [
{
"id": 12,
"name": "Ivan Petrov",
"email": "[email protected]",
"company": "BuildCo",
"role": "editor",
"tasks_count": 4,
"last_seen_at": "2026-11-02T15:30:00+05:00",
"invited_at": "2026-10-29T10:00:00+05:00",
"url": "https://app.jecheck.io/pg/Ab12Cd34Ef56Gh78Ij90Kl12Mn34Op56"
}
],
"stats": {
"total": 42,
"done": 18,
"open": 23,
"overdue": 3,
"unassigned": 2,
"progress": 44,
"forecast": "2026-12-20"
}
}
}PATCHUpdate a project
Partial update of project settings. Requires the admin role in the project (or projects.manage). Setting status to done stamps the completion time.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_update |
Path parameters
uuid
uuid
Required Request body
name
string
key
string
OPEN). Generated from the name if omitted.
Maximum length 10. description
string | null
icon
string
rocket_launch.
Maximum length 40. color
string
#5b54e8.
Maximum length 9. visibility
string
members — only members see the project; company — every employee can open it and join.
memberscompanystart_date
date | null
due_date
date | null
owner_id
integer
status
string
activepauseddonearchivedhealth
string | null
on_trackat_riskoff_trackguest_scope
string
allassignedtime_tracking
boolean
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X PATCH 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "Replace the broken fridge seal",
"key": "string",
"description": "Seal on fridge #2 is torn, temperature rises to +9 °C.",
"icon": "string"
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Replace the broken fridge seal",
"key": "string",
"description": "Seal on fridge #2 is torn, temperature rises to +9 °C.",
"icon": "string"
}),
});
const { data } = await res.json();import os, requests
res = requests.patch(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"name":"Replace the broken fridge seal","key":"string","description":"Seal on fridge #2 is torn, temperature rises to +9 °C.","icon":"string"},
)
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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'name' => 'Replace the broken fridge seal',
'key' => 'string',
'description' => 'Seal on fridge #2 is torn, temperature rises to +9 °C.',
'icon' => 'string',
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_update",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"name": "Replace the broken fridge seal",
"key": "string",
"description": "Seal on fridge #2 is torn, temperature rises to +9 °C.",
"icon": "string"
}
}
}{
"data": {
"id": 58,
"uuid": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
"key": "OPEN",
"name": "Opening: Abay Ave",
"description": "Launch of the new coffee shop on Abay Ave.",
"icon": "rocket_launch",
"color": "#5b54e8",
"status": "active",
"health": "on_track",
"visibility": "members",
"start_date": "2026-11-01",
"due_date": "2026-12-15",
"owner": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"role": "admin",
"created_at": "2026-10-28T09:00:00+05:00",
"updated_at": "2026-11-03T12:10:00+05:00",
"url": "https://app.jecheck.io/ui/projects/8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
"completed_at": null,
"starred": true,
"settings": {
"guest_scope": "all",
"time_tracking": true
},
"permissions": {
"edit": true,
"comment": true,
"manage": true,
"invite_guests": true,
"join": false
},
"sections": [
{
"id": 201,
"name": "Equipment"
}
],
"columns": [
{
"id": 301,
"name": "In progress",
"status": "in_progress",
"color": "#f59e0b",
"wip_limit": 5
}
],
"milestones": [
{
"id": 401,
"title": "Soft opening",
"description": "",
"due_date": "2026-12-01",
"done": false
}
],
"fields": [
{
"id": 501,
"name": "Supplier",
"type": "select",
"options": [
{
"id": "o_k2m9qa",
"label": "Metro",
"color": "#22c55e"
}
],
"on_card": true
}
],
"members": [
{
"user": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"role": "admin"
}
],
"guests": [
{
"id": 12,
"name": "Ivan Petrov",
"email": "[email protected]",
"company": "BuildCo",
"role": "editor",
"tasks_count": 4,
"last_seen_at": "2026-11-02T15:30:00+05:00",
"invited_at": "2026-10-29T10:00:00+05:00",
"url": "https://app.jecheck.io/pg/Ab12Cd34Ef56Gh78Ij90Kl12Mn34Op56"
}
],
"stats": {
"total": 42,
"done": 18,
"open": 23,
"overdue": 3,
"unassigned": 2,
"progress": 44,
"forecast": "2026-12-20"
}
}
}POSTArchive a project
Moves the project to the archive (status archived). Restore it with projects.update and status: active. Requires the admin role in the project.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_archive |
Path parameters
uuid
uuid
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/archive' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/archive', {
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/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/archive",
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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/archive', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_archive",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
}
}
}{
"data": {
"id": 58,
"uuid": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
"key": "OPEN",
"name": "Opening: Abay Ave",
"description": "Launch of the new coffee shop on Abay Ave.",
"icon": "rocket_launch",
"color": "#5b54e8",
"status": "active",
"health": "on_track",
"visibility": "members",
"start_date": "2026-11-01",
"due_date": "2026-12-15",
"owner": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"role": "admin",
"created_at": "2026-10-28T09:00:00+05:00",
"updated_at": "2026-11-03T12:10:00+05:00",
"url": "https://app.jecheck.io/ui/projects/8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
"completed_at": null,
"starred": true,
"settings": {
"guest_scope": "all",
"time_tracking": true
},
"permissions": {
"edit": true,
"comment": true,
"manage": true,
"invite_guests": true,
"join": false
},
"sections": [
{
"id": 201,
"name": "Equipment"
}
],
"columns": [
{
"id": 301,
"name": "In progress",
"status": "in_progress",
"color": "#f59e0b",
"wip_limit": 5
}
],
"milestones": [
{
"id": 401,
"title": "Soft opening",
"description": "",
"due_date": "2026-12-01",
"done": false
}
],
"fields": [
{
"id": 501,
"name": "Supplier",
"type": "select",
"options": [
{
"id": "o_k2m9qa",
"label": "Metro",
"color": "#22c55e"
}
],
"on_card": true
}
],
"members": [
{
"user": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"role": "admin"
}
],
"guests": [
{
"id": 12,
"name": "Ivan Petrov",
"email": "[email protected]",
"company": "BuildCo",
"role": "editor",
"tasks_count": 4,
"last_seen_at": "2026-11-02T15:30:00+05:00",
"invited_at": "2026-10-29T10:00:00+05:00",
"url": "https://app.jecheck.io/pg/Ab12Cd34Ef56Gh78Ij90Kl12Mn34Op56"
}
],
"stats": {
"total": 42,
"done": 18,
"open": 23,
"overdue": 3,
"unassigned": 2,
"progress": 44,
"forecast": "2026-12-20"
}
}
}DELDelete a project
Deletes the project together with its tasks (soft delete) and revokes guest links. Requires the admin role in the project.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_delete · destructive |
Path parameters
uuid
uuid
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/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/projects/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', 'projects/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": "projects_delete",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
}
}
}{
"data": {
"deleted": true
}
}POSTDuplicate a project
Creates a copy with the same structure and, optionally, tasks (dates shift relative to the new start date) and people. Requires projects.create.
| Token scope | write |
|---|---|
| Permission |
projects.create |
| MCP tool | projects_duplicate |
Path parameters
uuid
uuid
Required Request body
name
string
start_date
date
tasks
boolean
true. people
boolean
false. Responses
| Status | Description |
|---|---|
| 201 | Created |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks projects.create, is read-only
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/duplicate' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "Replace the broken fridge seal",
"start_date": "2026-11-01",
"tasks": true,
"people": false
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/duplicate', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Replace the broken fridge seal",
"start_date": "2026-11-01",
"tasks": true,
"people": false
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/duplicate",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"name":"Replace the broken fridge seal","start_date":"2026-11-01","tasks":True,"people":False},
)
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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/duplicate', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'name' => 'Replace the broken fridge seal',
'start_date' => '2026-11-01',
'tasks' => true,
'people' => false,
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_duplicate",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"name": "Replace the broken fridge seal",
"start_date": "2026-11-01",
"tasks": true,
"people": false
}
}
}{
"data": {
"id": 58,
"uuid": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
"key": "OPEN",
"name": "Opening: Abay Ave",
"description": "Launch of the new coffee shop on Abay Ave.",
"icon": "rocket_launch",
"color": "#5b54e8",
"status": "active",
"health": "on_track",
"visibility": "members",
"start_date": "2026-11-01",
"due_date": "2026-12-15",
"owner": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"role": "admin",
"created_at": "2026-10-28T09:00:00+05:00",
"updated_at": "2026-11-03T12:10:00+05:00",
"url": "https://app.jecheck.io/ui/projects/8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
"completed_at": null,
"starred": true,
"settings": {
"guest_scope": "all",
"time_tracking": true
},
"permissions": {
"edit": true,
"comment": true,
"manage": true,
"invite_guests": true,
"join": false
},
"sections": [
{
"id": 201,
"name": "Equipment"
}
],
"columns": [
{
"id": 301,
"name": "In progress",
"status": "in_progress",
"color": "#f59e0b",
"wip_limit": 5
}
],
"milestones": [
{
"id": 401,
"title": "Soft opening",
"description": "",
"due_date": "2026-12-01",
"done": false
}
],
"fields": [
{
"id": 501,
"name": "Supplier",
"type": "select",
"options": [
{
"id": "o_k2m9qa",
"label": "Metro",
"color": "#22c55e"
}
],
"on_card": true
}
],
"members": [
{
"user": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"role": "admin"
}
],
"guests": [
{
"id": 12,
"name": "Ivan Petrov",
"email": "[email protected]",
"company": "BuildCo",
"role": "editor",
"tasks_count": 4,
"last_seen_at": "2026-11-02T15:30:00+05:00",
"invited_at": "2026-10-29T10:00:00+05:00",
"url": "https://app.jecheck.io/pg/Ab12Cd34Ef56Gh78Ij90Kl12Mn34Op56"
}
],
"stats": {
"total": 42,
"done": 18,
"open": 23,
"overdue": 3,
"unassigned": 2,
"progress": 44,
"forecast": "2026-12-20"
}
}
}POSTSave a project as a company template
Saves the project structure and tasks as a company template. Requires projects.create.
| Token scope | write |
|---|---|
| Permission |
projects.create |
| MCP tool | projects_templates_create |
Path parameters
uuid
uuid
Required Request body
name
string
Responses
| Status | Description |
|---|---|
| 201 | Created |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks projects.create, is read-only
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/template' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "Replace the broken fridge seal"
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/template', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Replace the broken fridge seal"
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/template",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"name":"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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/template', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'name' => 'Replace the broken fridge seal',
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_templates_create",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"name": "Replace the broken fridge seal"
}
}
}{
"data": {
"id": "6d5c4b3a-2f1e-4d0c-9b8a-7f6e5d4c3b2a",
"name": "Opening a location",
"company": true
}
}DELDelete a company template
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_templates_delete · destructive |
Path parameters
template_uuid
uuid
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/projects/templates/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/templates/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/projects/templates/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', 'projects/templates/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": "projects_templates_delete",
"arguments": {
"template_uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
}
}
}{
"data": {
"deleted": true
}
}POSTStar or unstar a project
Starred projects are shown in the side menu of the acting user.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_star |
Path parameters
uuid
uuid
Required Request body
on
boolean
true — star, false — unstar.
Default true. Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/star' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"on": true
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/star', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"on": true
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/star",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"on":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('POST', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/star', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'on' => true,
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_star",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"on": true
}
}
}{
"data": {
"starred": true
}
}POSTJoin a project
Joins a project open to the whole company as an editor.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_join |
Path parameters
uuid
uuid
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/join' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/join', {
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/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/join",
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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/join', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_join",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
}
}
}{
"data": {
"id": 58,
"uuid": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
"key": "OPEN",
"name": "Opening: Abay Ave",
"description": "Launch of the new coffee shop on Abay Ave.",
"icon": "rocket_launch",
"color": "#5b54e8",
"status": "active",
"health": "on_track",
"visibility": "members",
"start_date": "2026-11-01",
"due_date": "2026-12-15",
"owner": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"role": "admin",
"created_at": "2026-10-28T09:00:00+05:00",
"updated_at": "2026-11-03T12:10:00+05:00",
"url": "https://app.jecheck.io/ui/projects/8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
"completed_at": null,
"starred": true,
"settings": {
"guest_scope": "all",
"time_tracking": true
},
"permissions": {
"edit": true,
"comment": true,
"manage": true,
"invite_guests": true,
"join": false
},
"sections": [
{
"id": 201,
"name": "Equipment"
}
],
"columns": [
{
"id": 301,
"name": "In progress",
"status": "in_progress",
"color": "#f59e0b",
"wip_limit": 5
}
],
"milestones": [
{
"id": 401,
"title": "Soft opening",
"description": "",
"due_date": "2026-12-01",
"done": false
}
],
"fields": [
{
"id": 501,
"name": "Supplier",
"type": "select",
"options": [
{
"id": "o_k2m9qa",
"label": "Metro",
"color": "#22c55e"
}
],
"on_card": true
}
],
"members": [
{
"user": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"role": "admin"
}
],
"guests": [
{
"id": 12,
"name": "Ivan Petrov",
"email": "[email protected]",
"company": "BuildCo",
"role": "editor",
"tasks_count": 4,
"last_seen_at": "2026-11-02T15:30:00+05:00",
"invited_at": "2026-10-29T10:00:00+05:00",
"url": "https://app.jecheck.io/pg/Ab12Cd34Ef56Gh78Ij90Kl12Mn34Op56"
}
],
"stats": {
"total": 42,
"done": 18,
"open": 23,
"overdue": 3,
"unassigned": 2,
"progress": 44,
"forecast": "2026-12-20"
}
}
}GETGet project statistics
Progress, workload by assignee, milestones progress, weekly velocity (8 weeks), burn-up and the completion forecast.
| Token scope | read |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_stats · read-only |
Path parameters
uuid
uuid
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Plan without API access
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/stats' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/stats', {
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/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/stats",
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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/stats', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_stats",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
}
}
}{
"data": {
"total": 42,
"done": 18,
"open": 23,
"overdue": 3,
"unassigned": 2,
"done_week": 5,
"created_week": 7,
"due_week": 6,
"progress": 44,
"estimate_minutes": 9600,
"spent_minutes": 4100,
"workload": [
{
"user": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"open": 6,
"overdue": 1
}
],
"milestones": [
{
"id": 401,
"title": "Soft opening",
"due_date": "2026-12-01",
"done": false,
"total": 12,
"closed": 5
}
],
"velocity": [
{
"week": "2026-10-27",
"closed": 5
}
],
"burnup": [
{
"date": "2026-11-01",
"scope": 40,
"done": 15
}
],
"forecast": "2026-12-20",
"avg_per_week": 4.5
}
}GETList project activity
Latest project and task events (up to 60), newest first. Page back with before = at of the last event.
| Token scope | read |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_activity · read-only |
Path parameters
uuid
uuid
Required Query parameters
before
date-time
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Plan without API access
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/activity?before=2026-11-03T09:00:00+05:00' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/activity?before=2026-11-03T09:00:00+05:00', {
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/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/activity",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
params={"before":"2026-11-03T09:00:00+05:00"},
)
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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/activity', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'query' => [
'before' => '2026-11-03T09:00:00+05:00',
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_activity",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"before": "2026-11-03T09:00:00+05:00"
}
}
}{
"data": [
{
"scope": "task",
"type": "status",
"user": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"guest_name": null,
"payload": {
"from": "new",
"to": "in_progress"
},
"task": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"key": "OPEN-12",
"title": "Install the espresso machine"
},
"at": "2026-11-03T12:01:00+05:00"
}
]
}GETList project members
| Token scope | read |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_members_list · read-only |
Path parameters
uuid
uuid
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Plan without API access
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/members' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/members', {
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/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/members",
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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/members', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_members_list",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
}
}
}{
"data": [
{
"user": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"role": "admin"
}
]
}POSTAdd project members
Adds employees with one project role (default editor); existing members get the new role. Added people are notified. Requires the admin role in the project.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_members_add |
Path parameters
uuid
uuid
Required Request body
user_ids
array<integer>
Required role
string
editor. admineditorcommenterviewerResponses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/members' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"user_ids": [
12,
14
],
"role": "editor"
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/members', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"user_ids": [
12,
14
],
"role": "editor"
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/members",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"user_ids":[12,14],"role":"editor"},
)
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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/members', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'user_ids' => [
12,
14,
],
'role' => 'editor',
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_members_add",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"user_ids": [
12,
14
],
"role": "editor"
}
}
}{
"data": [
{
"user": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"role": "editor"
}
]
}PATCHChange a member's project role
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_members_update |
Path parameters
uuid
uuid
Required user_id
integer
Required Request body
role
string
Required admineditorcommenterviewerResponses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X PATCH 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/members/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"role": "admin"
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/members/42', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"role": "admin"
}),
});
const { data } = await res.json();import os, requests
res = requests.patch(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/members/42",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"role":"admin"},
)
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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/members/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'role' => 'admin',
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_members_update",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"user_id": 42,
"role": "admin"
}
}
}{
"data": [
{
"user": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"role": "commenter"
}
]
}DELRemove a project member
Removes a member (admin role required) or leaves the project when user_id is the acting user. The owner cannot be removed.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_members_remove · destructive |
Path parameters
uuid
uuid
Required user_id
integer
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/members/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/members/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/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/members/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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/members/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_members_remove",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"user_id": 42
}
}
}{
"data": {
"deleted": true
}
}GETList project guests
External participants with personal links (url gives access without an account — keep it secret). Requires the admin role in the project and projects.guests.
| Token scope | read |
|---|---|
| Permission |
projects.guests |
| MCP tool | projects_guests_list · read-only |
Path parameters
uuid
uuid
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks projects.guests
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/guests' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/guests', {
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/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/guests",
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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/guests', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_guests_list",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
}
}
}{
"data": [
{
"id": 12,
"name": "Ivan Petrov",
"email": "[email protected]",
"company": "BuildCo",
"role": "editor",
"tasks_count": 4,
"last_seen_at": "2026-11-02T15:30:00+05:00",
"invited_at": "2026-10-29T10:00:00+05:00",
"url": "https://app.jecheck.io/pg/Ab12Cd34Ef56Gh78Ij90Kl12Mn34Op56"
}
]
}POSTInvite a project guest
Invites a contractor or client by e-mail: they get a personal link to the project (up to 50 guests per project). Requires the admin role in the project and projects.guests.
| Token scope | write |
|---|---|
| Permission |
projects.guests |
| MCP tool | projects_guests_invite |
Path parameters
uuid
uuid
Required Request body
name
string
Required email
string
Required company
string
role
string
editor. editorcommenterviewermessage
string
locale
string
send
boolean
true. Responses
| Status | Description |
|---|---|
| 201 | Created |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks projects.guests, is read-only
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/guests' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "Replace the broken fridge seal",
"email": "[email protected]",
"company": "string",
"role": "editor"
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/guests', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Replace the broken fridge seal",
"email": "[email protected]",
"company": "string",
"role": "editor"
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/guests",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"name":"Replace the broken fridge seal","email":"[email protected]","company":"string","role":"editor"},
)
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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/guests', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'name' => 'Replace the broken fridge seal',
'email' => '[email protected]',
'company' => 'string',
'role' => 'editor',
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_guests_invite",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"name": "Replace the broken fridge seal",
"email": "[email protected]",
"company": "string",
"role": "editor"
}
}
}{
"data": {
"id": 12,
"name": "Ivan Petrov",
"email": "[email protected]",
"company": "BuildCo",
"role": "editor",
"tasks_count": 4,
"last_seen_at": "2026-11-02T15:30:00+05:00",
"invited_at": "2026-10-29T10:00:00+05:00",
"url": "https://app.jecheck.io/pg/Ab12Cd34Ef56Gh78Ij90Kl12Mn34Op56"
}
}PATCHUpdate a project guest
Changes the role, name or company; resend re-sends the invitation, rotate issues a new link (the old one stops working).
| Token scope | write |
|---|---|
| Permission |
projects.guests |
| MCP tool | projects_guests_update |
Path parameters
uuid
uuid
Required guest_id
integer
Required Request body
role
string
editorcommenterviewername
string
company
string | null
resend
boolean
rotate
boolean
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks projects.guests, is read-only
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X PATCH 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/guests/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"role": "editor",
"name": "Replace the broken fridge seal",
"company": "string",
"resend": true
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/guests/42', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"role": "editor",
"name": "Replace the broken fridge seal",
"company": "string",
"resend": true
}),
});
const { data } = await res.json();import os, requests
res = requests.patch(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/guests/42",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"role":"editor","name":"Replace the broken fridge seal","company":"string","resend":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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/guests/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'role' => 'editor',
'name' => 'Replace the broken fridge seal',
'company' => 'string',
'resend' => true,
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_guests_update",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"guest_id": 42,
"role": "editor",
"name": "Replace the broken fridge seal",
"company": "string",
"resend": true
}
}
}{
"data": {
"id": 12,
"name": "Ivan Petrov",
"email": "[email protected]",
"company": "BuildCo",
"role": "editor",
"tasks_count": 4,
"last_seen_at": "2026-11-02T15:30:00+05:00",
"invited_at": "2026-10-29T10:00:00+05:00",
"url": "https://app.jecheck.io/pg/Ab12Cd34Ef56Gh78Ij90Kl12Mn34Op56"
}
}DELRevoke a guest link
| Token scope | write |
|---|---|
| Permission |
projects.guests |
| MCP tool | projects_guests_revoke · destructive |
Path parameters
uuid
uuid
Required guest_id
integer
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Token lacks projects.guests, is read-only
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/guests/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/guests/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/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/guests/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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/guests/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_guests_revoke",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"guest_id": 42
}
}
}{
"data": {
"deleted": true
}
}GETList project tasks (board)
Tasks of the project in board order (rank) with section, column, milestone, dates, estimate, logged time and custom field values (fields: field id → value). Closed tasks are included. Use the Tasks section for the full task card and changes.
| Token scope | read |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_tasks_list · read-only |
Path parameters
uuid
uuid
Required Query parameters
page
integer
1. Minimum 1.
per_page
integer
25. Value 1–100.
section_id
integer
column_id
integer
milestone_id
integer
status
array<string>
assignee_id
integer
Responses
| Status | Description |
|---|---|
| 200 | OK — a page of results with meta |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Plan without API access
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/tasks?section_id=42' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/tasks?section_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/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/tasks",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
params={"section_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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/tasks', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'query' => [
'section_id' => 42,
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_tasks_list",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"section_id": 42
}
}
}{
"data": [
{
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"key": "OPEN-12",
"title": "Install the espresso machine",
"status": "in_progress",
"priority": "high",
"assignees": [
{
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
}
],
"section_id": 201,
"column_id": 301,
"milestone_id": 401,
"start_date": "2026-11-04",
"due_date": "2026-11-10",
"estimate_minutes": 240,
"spent_minutes": 90,
"tags": [
"Equipment"
],
"fields": {
"501": "o_k2m9qa"
},
"guest_ids": [
12
],
"blocked_by_open": 0,
"rank": 3.5,
"completed_at": null,
"updated_at": "2026-11-03T12:01:00+05:00",
"url": "https://app.jecheck.io/ui/tasks?task=3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 1,
"has_more": false
}
}POSTMove a task on the board
Same as drag and drop: puts the task between before_uuid and after_uuid (rank), and optionally into another column (its status changes accordingly — loop rules may keep it), section or milestone. Requires the editor role.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_tasks_move |
Path parameters
uuid
uuid
Required task_uuid
uuid
Required Request body
column_id
integer
section_id
integer | null
null — no section).
milestone_id
integer | null
null — none).
before_uuid
uuid | null
after_uuid
uuid | null
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/move' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"column_id": 42,
"section_id": 42,
"milestone_id": 42,
"before_uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/move', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"column_id": 42,
"section_id": 42,
"milestone_id": 42,
"before_uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/move",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"column_id":42,"section_id":42,"milestone_id":42,"before_uuid":"3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"},
)
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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/move', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'column_id' => 42,
'section_id' => 42,
'milestone_id' => 42,
'before_uuid' => '3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b',
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_tasks_move",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"task_uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"column_id": 42,
"section_id": 42,
"milestone_id": 42,
"before_uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
}
}
}{
"data": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"status": "in_progress",
"column_id": 301,
"section_id": 201,
"milestone_id": 401,
"rank": 3.5
}
}GETGet the project part of a task
Project-specific data of a task: section, column, milestone, custom field values, guests, links to other tasks and time logs.
| Token scope | read |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_tasks_get · read-only |
Path parameters
uuid
uuid
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Plan without API access
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl 'https://app.jecheck.io/api/ext/v1/projects/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/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/projects/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', 'projects/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": "projects_tasks_get",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
}
}
}{
"data": {
"task_uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"project": {
"id": 58,
"uuid": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
"key": "OPEN",
"name": "Opening: Abay Ave"
},
"role": "editor",
"section_id": 201,
"column_id": 301,
"milestone_id": 401,
"fields": {
"501": "o_k2m9qa"
},
"guest_ids": [
12
],
"links": [
{
"id": 77,
"type": "blocked_by",
"task": {
"uuid": "5a4b3c2d-1e0f-4a9b-8c7d-6e5f4a3b2c1d",
"key": "OPEN-9",
"title": "Deliver the machine",
"status": "done",
"due_date": "2026-11-05"
}
}
],
"time_logs": [
{
"id": 901,
"minutes": 90,
"date": "2026-11-03",
"note": "Plumbing",
"user": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"guest_name": null
}
],
"spent_minutes": 90
}
}PATCHUpdate the project part of a task
Sets section, milestone, board column, custom field values (fields: field id → value; null clears; select — option id, multiselect — array of option ids, user — user id) and assigned guests. Requires the editor role.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_tasks_update |
Path parameters
uuid
uuid
Required Request body
section_id
integer | null
milestone_id
integer | null
column_id
integer
fields
object
guest_ids
array<integer>
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X PATCH 'https://app.jecheck.io/api/ext/v1/projects/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"section_id": 42,
"milestone_id": 42,
"column_id": 42,
"fields": []
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"section_id": 42,
"milestone_id": 42,
"column_id": 42,
"fields": []
}),
});
const { data } = await res.json();import os, requests
res = requests.patch(
"https://app.jecheck.io/api/ext/v1/projects/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"section_id":42,"milestone_id":42,"column_id":42,"fields":[]},
)
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', 'projects/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'section_id' => 42,
'milestone_id' => 42,
'column_id' => 42,
'fields' => [
],
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_tasks_update",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"section_id": 42,
"milestone_id": 42,
"column_id": 42,
"fields": []
}
}
}{
"data": {
"task_uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"project": {
"id": 58,
"uuid": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
"key": "OPEN",
"name": "Opening: Abay Ave"
},
"role": "editor",
"section_id": 201,
"column_id": 301,
"milestone_id": 401,
"fields": {
"501": "o_k2m9qa"
},
"guest_ids": [
12
],
"links": [
{
"id": 77,
"type": "blocked_by",
"task": {
"uuid": "5a4b3c2d-1e0f-4a9b-8c7d-6e5f4a3b2c1d",
"key": "OPEN-9",
"title": "Deliver the machine",
"status": "done",
"due_date": "2026-11-05"
}
}
],
"time_logs": [
{
"id": 901,
"minutes": 90,
"date": "2026-11-03",
"note": "Plumbing",
"user": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"guest_name": null
}
],
"spent_minutes": 90
}
}POSTLink two tasks
Adds a dependency or relation: blocks, blocked_by, relates, duplicates. Cycles of blocks are rejected.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_tasks_links_create |
Path parameters
uuid
uuid
Required Request body
other_uuid
uuid
Required type
string
Required blocksblocked_byrelatesduplicatesResponses
| Status | Description |
|---|---|
| 201 | Created |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/projects/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/links' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"other_uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"type": "blocks"
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/links', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"other_uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"type": "blocks"
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/projects/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/links",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"other_uuid":"3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b","type":"blocks"},
)
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', 'projects/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/links', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'other_uuid' => '3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b',
'type' => 'blocks',
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_tasks_links_create",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"other_uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"type": "blocks"
}
}
}{
"data": {
"task_uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"project": {
"id": 58,
"uuid": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
"key": "OPEN",
"name": "Opening: Abay Ave"
},
"role": "editor",
"section_id": 201,
"column_id": 301,
"milestone_id": 401,
"fields": {
"501": "o_k2m9qa"
},
"guest_ids": [
12
],
"links": [
{
"id": 77,
"type": "blocked_by",
"task": {
"uuid": "5a4b3c2d-1e0f-4a9b-8c7d-6e5f4a3b2c1d",
"key": "OPEN-9",
"title": "Deliver the machine",
"status": "done",
"due_date": "2026-11-05"
}
}
],
"time_logs": [
{
"id": 901,
"minutes": 90,
"date": "2026-11-03",
"note": "Plumbing",
"user": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"guest_name": null
}
],
"spent_minutes": 90
}
}DELRemove a task link
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_tasks_links_delete · destructive |
Path parameters
uuid
uuid
Required id
integer
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/projects/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/links/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/links/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/projects/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/links/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', 'projects/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/links/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_tasks_links_delete",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"id": 42
}
}
}{
"data": {
"deleted": true
}
}POSTLog time on a task
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_tasks_time_create |
Path parameters
uuid
uuid
Required Request body
minutes
integer
Required date
date
note
string
Responses
| Status | Description |
|---|---|
| 201 | Created |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/projects/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/time' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"minutes": 42,
"date": "2026-11-01",
"note": "Seal on fridge #2 is torn, temperature rises to +9 °C."
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/time', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"minutes": 42,
"date": "2026-11-01",
"note": "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/projects/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/time",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"minutes":42,"date":"2026-11-01","note":"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', 'projects/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/time', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'minutes' => 42,
'date' => '2026-11-01',
'note' => '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": "projects_tasks_time_create",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"minutes": 42,
"date": "2026-11-01",
"note": "Seal on fridge #2 is torn, temperature rises to +9 °C."
}
}
}{
"data": {
"task_uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"project": {
"id": 58,
"uuid": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
"key": "OPEN",
"name": "Opening: Abay Ave"
},
"role": "editor",
"section_id": 201,
"column_id": 301,
"milestone_id": 401,
"fields": {
"501": "o_k2m9qa"
},
"guest_ids": [
12
],
"links": [
{
"id": 77,
"type": "blocked_by",
"task": {
"uuid": "5a4b3c2d-1e0f-4a9b-8c7d-6e5f4a3b2c1d",
"key": "OPEN-9",
"title": "Deliver the machine",
"status": "done",
"due_date": "2026-11-05"
}
}
],
"time_logs": [
{
"id": 901,
"minutes": 90,
"date": "2026-11-03",
"note": "Plumbing",
"user": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"guest_name": null
}
],
"spent_minutes": 90
}
}DELDelete a time log
Own time logs can be deleted by their author; any — by project admins.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_tasks_time_delete · destructive |
Path parameters
uuid
uuid
Required id
integer
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/projects/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/time/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/time/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/projects/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/time/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', 'projects/tasks/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/time/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_tasks_time_delete",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"id": 42
}
}
}{
"data": {
"deleted": true
}
}GETList status updates
| Token scope | read |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_updates_list · read-only |
Path parameters
uuid
uuid
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Plan without API access
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/updates' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/updates', {
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/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/updates",
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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/updates', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_updates_list",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
}
}
}{
"data": [
{
"id": 31,
"health": "on_track",
"body": "Equipment delivered, staff hired.",
"stats": {
"total": 42,
"done": 18,
"open": 23,
"overdue": 3,
"progress": 44,
"forecast": "2026-12-20"
},
"author": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"created_at": "2026-11-02T18:00:00+05:00"
}
]
}POSTPost a status update
Posts a status report with health; the project health changes and members are notified. Requires the editor role.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_updates_create |
Path parameters
uuid
uuid
Required Request body
health
string
Required on_trackat_riskoff_trackbody
string
Required Responses
| Status | Description |
|---|---|
| 201 | Created |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/updates' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"health": "on_track",
"body": "string"
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/updates', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"health": "on_track",
"body": "string"
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/updates",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"health":"on_track","body":"string"},
)
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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/updates', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'health' => 'on_track',
'body' => 'string',
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_updates_create",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"health": "on_track",
"body": "string"
}
}
}{
"data": {
"id": 31,
"health": "on_track",
"body": "Equipment delivered, staff hired.",
"stats": {
"total": 42,
"done": 18,
"open": 23,
"overdue": 3,
"progress": 44,
"forecast": "2026-12-20"
},
"author": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"created_at": "2026-11-02T18:00:00+05:00"
}
}DELDelete a status update
The author or a project admin can delete an update.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_updates_delete · destructive |
Path parameters
uuid
uuid
Required id
integer
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/updates/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/updates/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/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/updates/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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/updates/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_updates_delete",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"id": 42
}
}
}{
"data": {
"deleted": true
}
}GETList automation rules
Project automation rules ("when … if … then …"). Requires the admin role in the project. Ids inside trigger, conditions and actions refer to columns, sections, milestones, fields and users of this project.
| Token scope | read |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_rules_list · read-only |
Path parameters
uuid
uuid
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Plan without API access
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules', {
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/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules",
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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_rules_list",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
}
}
}{
"data": [
{
"id": 14,
"name": "Done → notify the owner",
"enabled": true,
"trigger": {
"type": "column_changed",
"column": "305"
},
"conditions": [
{
"field": "priority",
"op": "is",
"value": "urgent"
}
],
"actions": [
{
"type": "notify",
"to": [
"owner"
],
"text": "Urgent task closed"
}
],
"runs": 12,
"last_run_at": "2026-11-03T12:01:00+05:00"
}
]
}POSTCreate an automation rule
Triggers: task_created, column_changed, status_changed, section_changed, assigned, field_changed, commented, subtasks_done, unblocked, due_soon, overdue. Conditions (up to 10) on: priority, column, section, milestone, assignee, tag, title, field with op is/not/empty/not_empty/contains. Actions (1–12): move_column, move_section, set_milestone, assign, unassign, watchers, priority, due, start, tags, field, subtasks, comment, notify, create_task. Up to 50 rules per project.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_rules_create |
Path parameters
uuid
uuid
Required Request body
name
string
trigger
object
Required column for column_changed, section for section_changed, status for status_changed, field+value for field_changed, days for due_soon, guest: true for commented.
conditions
array<object>
id — custom field id when field = field.
Maximum items 10. actions
array<object>
Required enabled
boolean
true. Responses
| Status | Description |
|---|---|
| 201 | Created |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "Replace the broken fridge seal",
"trigger": [],
"conditions": [
[]
],
"actions": [
[]
]
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Replace the broken fridge seal",
"trigger": [],
"conditions": [
[]
],
"actions": [
[]
]
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"name":"Replace the broken fridge seal","trigger":[],"conditions":[[]],"actions":[[]]},
)
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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'name' => 'Replace the broken fridge seal',
'trigger' => [
],
'conditions' => [
[
],
],
'actions' => [
[
],
],
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_rules_create",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"name": "Replace the broken fridge seal",
"trigger": [],
"conditions": [
[]
],
"actions": [
[]
]
}
}
}{
"data": {
"id": 14,
"name": "Done → notify the owner",
"enabled": true,
"trigger": {
"type": "column_changed",
"column": "305"
},
"conditions": [
{
"field": "priority",
"op": "is",
"value": "urgent"
}
],
"actions": [
{
"type": "notify",
"to": [
"owner"
],
"text": "Urgent task closed"
}
],
"runs": 12,
"last_run_at": "2026-11-03T12:01:00+05:00"
}
}PUTReplace an automation rule
Replaces the whole rule definition (same fields as on creation).
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_rules_update |
Path parameters
uuid
uuid
Required id
integer
Required Request body
name
string
trigger
object
Required column for column_changed, section for section_changed, status for status_changed, field+value for field_changed, days for due_soon, guest: true for commented.
conditions
array<object>
id — custom field id when field = field.
Maximum items 10. actions
array<object>
Required enabled
boolean
true. Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X PUT 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "Replace the broken fridge seal",
"trigger": [],
"conditions": [
[]
],
"actions": [
[]
]
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules/42', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Replace the broken fridge seal",
"trigger": [],
"conditions": [
[]
],
"actions": [
[]
]
}),
});
const { data } = await res.json();import os, requests
res = requests.put(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules/42",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"name":"Replace the broken fridge seal","trigger":[],"conditions":[[]],"actions":[[]]},
)
res.raise_for_status()
data = res.json()["data"]$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('PUT', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'name' => 'Replace the broken fridge seal',
'trigger' => [
],
'conditions' => [
[
],
],
'actions' => [
[
],
],
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_rules_update",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"id": 42,
"name": "Replace the broken fridge seal",
"trigger": [],
"conditions": [
[]
],
"actions": [
[]
]
}
}
}{
"data": {
"id": 14,
"name": "Done → notify the owner",
"enabled": true,
"trigger": {
"type": "column_changed",
"column": "305"
},
"conditions": [
{
"field": "priority",
"op": "is",
"value": "urgent"
}
],
"actions": [
{
"type": "notify",
"to": [
"owner"
],
"text": "Urgent task closed"
}
],
"runs": 12,
"last_run_at": "2026-11-03T12:01:00+05:00"
}
}POSTEnable or disable a rule
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_rules_toggle |
Path parameters
uuid
uuid
Required id
integer
Required Request body
enabled
boolean
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules/42/toggle' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"enabled": true
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules/42/toggle', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"enabled": true
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules/42/toggle",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"enabled":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('POST', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules/42/toggle', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'enabled' => true,
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_rules_toggle",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"id": 42,
"enabled": true
}
}
}{
"data": {
"id": 14,
"name": "Done → notify the owner",
"enabled": true,
"trigger": {
"type": "column_changed",
"column": "305"
},
"conditions": [
{
"field": "priority",
"op": "is",
"value": "urgent"
}
],
"actions": [
{
"type": "notify",
"to": [
"owner"
],
"text": "Urgent task closed"
}
],
"runs": 12,
"last_run_at": "2026-11-03T12:01:00+05:00"
}
}DELDelete an automation rule
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_rules_delete · destructive |
Path parameters
uuid
uuid
Required id
integer
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules/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/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules/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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_rules_delete",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"id": 42
}
}
}{
"data": {
"deleted": true
}
}GETList rule runs
Last 50 runs of the rule: when, on which task, success or the reason of failure.
| Token scope | read |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_rules_runs · read-only |
Path parameters
uuid
uuid
Required id
integer
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Plan without API access
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules/42/runs' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules/42/runs', {
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/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules/42/runs",
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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/rules/42/runs', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_rules_runs",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"id": 42
}
}
}{
"data": [
{
"trigger": "column_changed",
"ok": true,
"note": null,
"task": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"key": "OPEN-12",
"title": "Install the espresso machine"
},
"at": "2026-11-03T12:01:00+05:00"
}
]
}POSTCreate a section
Adds a section to the project. Requires the editor role in the project.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_sections_create |
Path parameters
uuid
uuid
Required Request body
name
string
Required Responses
| Status | Description |
|---|---|
| 201 | Created |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/sections' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "Replace the broken fridge seal"
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/sections', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Replace the broken fridge seal"
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/sections",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"name":"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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/sections', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'name' => 'Replace the broken fridge seal',
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_sections_create",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"name": "Replace the broken fridge seal"
}
}
}{
"data": {
"id": 201,
"name": "Equipment"
}
}PATCHUpdate a section
Partial update. Requires the editor role in the project.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_sections_update |
Path parameters
uuid
uuid
Required id
integer
Required Request body
name
string
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X PATCH 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/sections/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "Replace the broken fridge seal"
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/sections/42', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Replace the broken fridge seal"
}),
});
const { data } = await res.json();import os, requests
res = requests.patch(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/sections/42",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"name":"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('PATCH', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/sections/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'name' => 'Replace the broken fridge seal',
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_sections_update",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"id": 42,
"name": "Replace the broken fridge seal"
}
}
}{
"data": {
"id": 201,
"name": "Equipment"
}
}DELDelete a section
Tasks of the section move to move_to_id or are left without a section.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_sections_delete · destructive |
Path parameters
uuid
uuid
Required id
integer
Required Query parameters
move_to_id
integer
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/sections/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/sections/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/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/sections/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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/sections/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_sections_delete",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"id": 42
}
}
}{
"data": {
"deleted": true
}
}PUTReorder sections
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_sections_reorder |
Path parameters
uuid
uuid
Required Request body
ids
array<integer>
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X PUT 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/sections/order' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"ids": [
12,
14
]
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/sections/order', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"ids": [
12,
14
]
}),
});
const { data } = await res.json();import os, requests
res = requests.put(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/sections/order",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"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('PUT', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/sections/order', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'ids' => [
12,
14,
],
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_sections_reorder",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"ids": [
12,
14
]
}
}
}{
"data": [
{
"id": 201,
"name": "Equipment"
}
]
}POSTCreate a column
Adds a column to the project. Requires the admin role in the project.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_columns_create |
Path parameters
uuid
uuid
Required Request body
name
string
Required status
string
Required newin_progressreviewdonerejectedcolor
string | null
wip_limit
integer | null
Responses
| Status | Description |
|---|---|
| 201 | Created |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/columns' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "Replace the broken fridge seal",
"status": "new",
"color": "string",
"wip_limit": 42
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/columns', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Replace the broken fridge seal",
"status": "new",
"color": "string",
"wip_limit": 42
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/columns",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"name":"Replace the broken fridge seal","status":"new","color":"string","wip_limit":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('POST', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/columns', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'name' => 'Replace the broken fridge seal',
'status' => 'new',
'color' => 'string',
'wip_limit' => 42,
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_columns_create",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"name": "Replace the broken fridge seal",
"status": "new",
"color": "string",
"wip_limit": 42
}
}
}{
"data": {
"id": 301,
"name": "In progress",
"status": "in_progress",
"color": "#f59e0b",
"wip_limit": 5
}
}PATCHUpdate a column
Changing the column status moves its tasks to that status (normal status change with notifications).
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_columns_update |
Path parameters
uuid
uuid
Required id
integer
Required Request body
name
string
status
string
newin_progressreviewdonerejectedcolor
string | null
wip_limit
integer | null
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X PATCH 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/columns/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "Replace the broken fridge seal",
"status": "new",
"color": "string",
"wip_limit": 42
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/columns/42', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Replace the broken fridge seal",
"status": "new",
"color": "string",
"wip_limit": 42
}),
});
const { data } = await res.json();import os, requests
res = requests.patch(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/columns/42",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"name":"Replace the broken fridge seal","status":"new","color":"string","wip_limit":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('PATCH', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/columns/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'name' => 'Replace the broken fridge seal',
'status' => 'new',
'color' => 'string',
'wip_limit' => 42,
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_columns_update",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"id": 42,
"name": "Replace the broken fridge seal",
"status": "new",
"color": "string",
"wip_limit": 42
}
}
}{
"data": {
"id": 301,
"name": "In progress",
"status": "in_progress",
"color": "#f59e0b",
"wip_limit": 5
}
}DELDelete a column
Tasks of the column move to move_to_id (or a column with the same status). The last column cannot be deleted.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_columns_delete · destructive |
Path parameters
uuid
uuid
Required id
integer
Required Query parameters
move_to_id
integer
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/columns/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/columns/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/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/columns/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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/columns/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_columns_delete",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"id": 42
}
}
}{
"data": {
"deleted": true
}
}PUTReorder columns
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_columns_reorder |
Path parameters
uuid
uuid
Required Request body
ids
array<integer>
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X PUT 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/columns/order' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"ids": [
12,
14
]
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/columns/order', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"ids": [
12,
14
]
}),
});
const { data } = await res.json();import os, requests
res = requests.put(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/columns/order",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"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('PUT', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/columns/order', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'ids' => [
12,
14,
],
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_columns_reorder",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"ids": [
12,
14
]
}
}
}{
"data": [
{
"id": 301,
"name": "In progress",
"status": "in_progress",
"color": "#f59e0b",
"wip_limit": 5
}
]
}POSTCreate a milestone
Adds a milestone to the project. Requires the editor role in the project.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_milestones_create |
Path parameters
uuid
uuid
Required Request body
title
string
Required description
string | null
due_date
date | null
done
boolean
Responses
| Status | Description |
|---|---|
| 201 | Created |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/milestones' \
-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.",
"due_date": "2026-11-01",
"done": true
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/milestones', {
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.",
"due_date": "2026-11-01",
"done": true
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/milestones",
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.","due_date":"2026-11-01","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('POST', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/milestones', [
'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.',
'due_date' => '2026-11-01',
'done' => true,
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_milestones_create",
"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.",
"due_date": "2026-11-01",
"done": true
}
}
}{
"data": {
"id": 401,
"title": "Soft opening",
"description": "",
"due_date": "2026-12-01",
"done": false
}
}PATCHUpdate a milestone
Partial update. Requires the editor role in the project.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_milestones_update |
Path parameters
uuid
uuid
Required id
integer
Required Request body
title
string
description
string | null
due_date
date | null
done
boolean
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X PATCH 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/milestones/42' \
-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.",
"due_date": "2026-11-01",
"done": true
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/milestones/42', {
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.",
"due_date": "2026-11-01",
"done": true
}),
});
const { data } = await res.json();import os, requests
res = requests.patch(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/milestones/42",
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.","due_date":"2026-11-01","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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/milestones/42', [
'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.',
'due_date' => '2026-11-01',
'done' => true,
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_milestones_update",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"id": 42,
"title": "Replace the broken fridge seal",
"description": "Seal on fridge #2 is torn, temperature rises to +9 °C.",
"due_date": "2026-11-01",
"done": true
}
}
}{
"data": {
"id": 401,
"title": "Soft opening",
"description": "",
"due_date": "2026-12-01",
"done": false
}
}DELDelete a milestone
Tasks of the milestone move to move_to_id or are left without a milestone.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_milestones_delete · destructive |
Path parameters
uuid
uuid
Required id
integer
Required Query parameters
move_to_id
integer
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/milestones/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/milestones/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/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/milestones/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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/milestones/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_milestones_delete",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"id": 42
}
}
}{
"data": {
"deleted": true
}
}PUTReorder milestones
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_milestones_reorder |
Path parameters
uuid
uuid
Required Request body
ids
array<integer>
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X PUT 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/milestones/order' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"ids": [
12,
14
]
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/milestones/order', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"ids": [
12,
14
]
}),
});
const { data } = await res.json();import os, requests
res = requests.put(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/milestones/order",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"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('PUT', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/milestones/order', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'ids' => [
12,
14,
],
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_milestones_reorder",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"ids": [
12,
14
]
}
}
}{
"data": [
{
"id": 401,
"title": "Soft opening",
"description": "",
"due_date": "2026-12-01",
"done": false
}
]
}POSTCreate a field
Adds a field to the project. Requires the admin role in the project.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_fields_create |
Path parameters
uuid
uuid
Required Request body
name
string
Required type
string
Required textnumbermoneyselectmultiselectdatecheckboxuserurloptions
array<object> | null
id
string
label
string
Required color
string
on_card
boolean
Responses
| Status | Description |
|---|---|
| 201 | Created |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X POST 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/fields' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "Replace the broken fridge seal",
"type": "text",
"options": [
{
"id": "string",
"label": "string",
"color": "string"
}
],
"on_card": true
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/fields', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Replace the broken fridge seal",
"type": "text",
"options": [
{
"id": "string",
"label": "string",
"color": "string"
}
],
"on_card": true
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/fields",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"name":"Replace the broken fridge seal","type":"text","options":[{"id":"string","label":"string","color":"string"}],"on_card":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('POST', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/fields', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'name' => 'Replace the broken fridge seal',
'type' => 'text',
'options' => [
[
'id' => 'string',
'label' => 'string',
'color' => 'string',
],
],
'on_card' => true,
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_fields_create",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"name": "Replace the broken fridge seal",
"type": "text",
"options": [
{
"id": "string",
"label": "string",
"color": "string"
}
],
"on_card": true
}
}
}{
"data": {
"id": 501,
"name": "Supplier",
"type": "select",
"options": [
{
"id": "o_k2m9qa",
"label": "Metro",
"color": "#22c55e"
}
],
"on_card": true
}
}PATCHUpdate a field
Partial update. Requires the admin role in the project.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_fields_update |
Path parameters
uuid
uuid
Required id
integer
Required Request body
name
string
options
array<object> | null
id
string
label
string
Required color
string
on_card
boolean
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X PATCH 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/fields/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "Replace the broken fridge seal",
"options": [
{
"id": "string",
"label": "string",
"color": "string"
}
],
"on_card": true
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/fields/42', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Replace the broken fridge seal",
"options": [
{
"id": "string",
"label": "string",
"color": "string"
}
],
"on_card": true
}),
});
const { data } = await res.json();import os, requests
res = requests.patch(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/fields/42",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"name":"Replace the broken fridge seal","options":[{"id":"string","label":"string","color":"string"}],"on_card":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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/fields/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'name' => 'Replace the broken fridge seal',
'options' => [
[
'id' => 'string',
'label' => 'string',
'color' => 'string',
],
],
'on_card' => true,
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_fields_update",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"id": 42,
"name": "Replace the broken fridge seal",
"options": [
{
"id": "string",
"label": "string",
"color": "string"
}
],
"on_card": true
}
}
}{
"data": {
"id": 501,
"name": "Supplier",
"type": "select",
"options": [
{
"id": "o_k2m9qa",
"label": "Metro",
"color": "#22c55e"
}
],
"on_card": true
}
}DELDelete a field
Deletes the field and its values in all tasks.
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_fields_delete · destructive |
Path parameters
uuid
uuid
Required id
integer
Required Query parameters
move_to_id
integer
Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/fields/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/fields/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/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/fields/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', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/fields/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_fields_delete",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"id": 42
}
}
}{
"data": {
"deleted": true
}
}PUTReorder fields
| Token scope | write |
|---|---|
| Permission | Any employee; results follow the token's visibility |
| MCP tool | projects_fields_reorder |
Path parameters
uuid
uuid
Required Request body
ids
array<integer>
Required Responses
| Status | Description |
|---|---|
| 200 | OK |
| 401 | unauthorized — Missing, invalid, revoked or expired token
|
| 403 | forbidden · insufficient_scope · plan_required — Read-only token
|
| 404 | not_found — The record does not exist or is not visible to the token
|
| 422 | validation_failed — Invalid parameters — see error.fields
|
| 429 | rate_limited — Too many requests — retry after Retry-After seconds
|
curl -X PUT 'https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/fields/order' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"ids": [
12,
14
]
}'const res = await fetch('https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/fields/order', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"ids": [
12,
14
]
}),
});
const { data } = await res.json();import os, requests
res = requests.put(
"https://app.jecheck.io/api/ext/v1/projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/fields/order",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"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('PUT', 'projects/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/fields/order', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'ids' => [
12,
14,
],
],
]);
$data = json_decode($res->getBody(), true)['data'];{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "projects_fields_reorder",
"arguments": {
"uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
"ids": [
12,
14
]
}
}
}{
"data": [
{
"id": 501,
"name": "Supplier",
"type": "select",
"options": [
{
"id": "o_k2m9qa",
"label": "Metro",
"color": "#22c55e"
}
],
"on_card": true
}
]
}