Audit planner
Planned audits: the calendar of scheduled inspections with computed statuses (planned, in progress, overdue, missed, done), audit plans and recurring series across locations, rescheduling, reassigning, cancelling and marking as done, and plan templates.
GET List planned audits
GET /planner/audits
Planned audits (calendar entries) in a date range, ordered by date. The status is computed on read: done — marked manually (done_by: manual) or matched by a conducted audit of the same checklist and location within the window date ± tolerance (done_by: audit, audit_id); planned, inprogress (today, start time passed), overdue (date passed, window still open), missed (window closed). Visible: locations where the token has planner.view or planner.manage, plus audits assigned to the token user.
Token scope read
Permission
Any employee; results follow the token's visibility
MCP tool planner_audits_list · read-only
Query parameters
page
integer
Page number, starting from 1.
Default 1. Minimum 1.
per_page
integer
Items per page (max 100).
Default 25. Value 1–100.
date_from
date
From date (inclusive); default — today.
date_to
date
To date (inclusive); default — 30 days after date_from; the range is limited to 366 days.
location_ids
array<integer>
Only these locations.
auditor_ids
array<integer>
Only these auditors.
checklist_ids
array<integer>
Only these checklists.
status
array<string>
Filter by status: planned, inprogress, overdue, missed, done.
mine
boolean
Only audits assigned to the token user.
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
Request
cURL
Node.js
Python
PHP
MCP
Copy
curl 'https://app.jecheck.io/api/ext/v1/planner/audits?date_from=2026-11-01' \
-H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/planner/audits?date_from=2026-11-01', {
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/planner/audits",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
params={"date_from":"2026-11-01"},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('GET', 'planner/audits', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'query' => [
'date_from' => '2026-11-01',
],
]);
$data = json_decode($res->getBody(), true)['data'];
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "planner_audits_list",
"arguments": {
"date_from": "2026-11-01"
}
}
}
{
"data": [
{
"id": 48211,
"date": "2026-11-05",
"time": "09:00",
"duration_min": 60,
"checklist": {
"id": 5845,
"name": "Daily dining room check"
},
"location": {
"id": 12,
"name": "Abay Ave"
},
"auditor": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"status": "planned",
"done_by": null,
"audit_id": null,
"audit_date": null,
"window_from": "2026-11-04",
"window_to": "2026-11-06",
"plan_key": "0b7c1f9e-2d4a-4f6b-8e3c-5a9d7b1c2e4f",
"series_id": 1842,
"url": "https://app.jecheck.io/ui/planner?date=2026-11-05"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 1,
"has_more": false
}
}
GET Retrieve a planned audit
GET /planner/audits/{id}
Token scope read
Permission
Any employee; results follow the token's visibility
MCP tool planner_audits_get · read-only
Path parameters
id
integer
Required
Planned audit id.
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
Request
cURL
Node.js
Python
PHP
MCP
Copy
curl 'https://app.jecheck.io/api/ext/v1/planner/audits/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/planner/audits/42', {
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/planner/audits/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('GET', 'planner/audits/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "planner_audits_get",
"arguments": {
"id": 42
}
}
}
{
"data": {
"id": 48211,
"date": "2026-11-05",
"time": "09:00",
"duration_min": 60,
"checklist": {
"id": 5845,
"name": "Daily dining room check"
},
"location": {
"id": 12,
"name": "Abay Ave"
},
"auditor": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"status": "planned",
"done_by": null,
"audit_id": null,
"audit_date": null,
"window_from": "2026-11-04",
"window_to": "2026-11-06",
"plan_key": "0b7c1f9e-2d4a-4f6b-8e3c-5a9d7b1c2e4f",
"series_id": 1842,
"url": "https://app.jecheck.io/ui/planner?date=2026-11-05"
}
}
POST Reschedule a planned audit
POST /planner/audits/{id}/reschedule
Moves the planned audit to another date and/or time; reminders are sent again. Requires planner.manage on its location.
Token scope write
Permission
Any employee; results follow the token's visibility
MCP tool planner_audits_reschedule
Path parameters
id
integer
Required
Planned audit id.
Request body
date
date
Required
New date.
time
string
New start time HH:MM (kept if omitted).
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
Request
cURL
Node.js
Python
PHP
MCP
Copy
curl -X POST 'https://app.jecheck.io/api/ext/v1/planner/audits/42/reschedule' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"date": "2026-11-01",
"time": "string"
}'
const res = await fetch('https://app.jecheck.io/api/ext/v1/planner/audits/42/reschedule', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"date": "2026-11-01",
"time": "string"
}),
});
const { data } = await res.json();
import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/planner/audits/42/reschedule",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"date":"2026-11-01","time":"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', 'planner/audits/42/reschedule', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'date' => '2026-11-01',
'time' => 'string',
],
]);
$data = json_decode($res->getBody(), true)['data'];
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "planner_audits_reschedule",
"arguments": {
"id": 42,
"date": "2026-11-01",
"time": "string"
}
}
}
{
"data": {
"id": 48211,
"date": "2026-11-05",
"time": "09:00",
"duration_min": 60,
"checklist": {
"id": 5845,
"name": "Daily dining room check"
},
"location": {
"id": 12,
"name": "Abay Ave"
},
"auditor": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"status": "planned",
"done_by": null,
"audit_id": null,
"audit_date": null,
"window_from": "2026-11-04",
"window_to": "2026-11-06",
"plan_key": "0b7c1f9e-2d4a-4f6b-8e3c-5a9d7b1c2e4f",
"series_id": 1842,
"url": "https://app.jecheck.io/ui/planner?date=2026-11-05"
}
}
POST Reassign a planned audit
POST /planner/audits/{id}/reassign
Assigns the planned audit to another auditor; the checklist must be available to them. Requires planner.manage on its location.
Token scope write
Permission
Any employee; results follow the token's visibility
MCP tool planner_audits_reassign
Path parameters
id
integer
Required
Planned audit id.
Request body
auditor_id
integer
Required
New auditor (user id).
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
Request
cURL
Node.js
Python
PHP
MCP
Copy
curl -X POST 'https://app.jecheck.io/api/ext/v1/planner/audits/42/reassign' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"auditor_id": 42
}'
const res = await fetch('https://app.jecheck.io/api/ext/v1/planner/audits/42/reassign', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"auditor_id": 42
}),
});
const { data } = await res.json();
import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/planner/audits/42/reassign",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"auditor_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('POST', 'planner/audits/42/reassign', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'auditor_id' => 42,
],
]);
$data = json_decode($res->getBody(), true)['data'];
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "planner_audits_reassign",
"arguments": {
"id": 42,
"auditor_id": 42
}
}
}
{
"data": {
"id": 48211,
"date": "2026-11-05",
"time": "09:00",
"duration_min": 60,
"checklist": {
"id": 5845,
"name": "Daily dining room check"
},
"location": {
"id": 12,
"name": "Abay Ave"
},
"auditor": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"status": "planned",
"done_by": null,
"audit_id": null,
"audit_date": null,
"window_from": "2026-11-04",
"window_to": "2026-11-06",
"plan_key": "0b7c1f9e-2d4a-4f6b-8e3c-5a9d7b1c2e4f",
"series_id": 1842,
"url": "https://app.jecheck.io/ui/planner?date=2026-11-05"
}
}
POST Mark a planned audit as done
POST /planner/audits/{id}/complete
Manual "done" mark (e.g. the audit was done on paper). Allowed with planner.manage on the location or to the assigned auditor.
Token scope write
Permission
Any employee; results follow the token's visibility
MCP tool planner_audits_complete
Path parameters
id
integer
Required
Planned audit id.
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
Request
cURL
Node.js
Python
PHP
MCP
Copy
curl -X POST 'https://app.jecheck.io/api/ext/v1/planner/audits/42/complete' \
-H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/planner/audits/42/complete', {
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/planner/audits/42/complete",
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', 'planner/audits/42/complete', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "planner_audits_complete",
"arguments": {
"id": 42
}
}
}
{
"data": {
"id": 48211,
"date": "2026-11-05",
"time": "09:00",
"duration_min": 60,
"checklist": {
"id": 5845,
"name": "Daily dining room check"
},
"location": {
"id": 12,
"name": "Abay Ave"
},
"auditor": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"status": "planned",
"done_by": null,
"audit_id": null,
"audit_date": null,
"window_from": "2026-11-04",
"window_to": "2026-11-06",
"plan_key": "0b7c1f9e-2d4a-4f6b-8e3c-5a9d7b1c2e4f",
"series_id": 1842,
"url": "https://app.jecheck.io/ui/planner?date=2026-11-05"
}
}
POST Remove the manual done mark
POST /planner/audits/{id}/uncomplete
The status is computed again. Fails with 422 if the audit was not marked manually.
Token scope write
Permission
Any employee; results follow the token's visibility
MCP tool planner_audits_uncomplete
Path parameters
id
integer
Required
Planned audit id.
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
Request
cURL
Node.js
Python
PHP
MCP
Copy
curl -X POST 'https://app.jecheck.io/api/ext/v1/planner/audits/42/uncomplete' \
-H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/planner/audits/42/uncomplete', {
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/planner/audits/42/uncomplete",
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', 'planner/audits/42/uncomplete', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "planner_audits_uncomplete",
"arguments": {
"id": 42
}
}
}
{
"data": {
"id": 48211,
"date": "2026-11-05",
"time": "09:00",
"duration_min": 60,
"checklist": {
"id": 5845,
"name": "Daily dining room check"
},
"location": {
"id": 12,
"name": "Abay Ave"
},
"auditor": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"status": "planned",
"done_by": null,
"audit_id": null,
"audit_date": null,
"window_from": "2026-11-04",
"window_to": "2026-11-06",
"plan_key": "0b7c1f9e-2d4a-4f6b-8e3c-5a9d7b1c2e4f",
"series_id": 1842,
"url": "https://app.jecheck.io/ui/planner?date=2026-11-05"
}
}
DEL Cancel a planned audit
DELETE /planner/audits/{id}
Removes one planned audit from its plan. A done audit cannot be cancelled. Requires planner.manage on its location.
Token scope write
Permission
Any employee; results follow the token's visibility
MCP tool planner_audits_cancel · destructive
Path parameters
id
integer
Required
Planned audit id.
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
Request
cURL
Node.js
Python
PHP
MCP
Copy
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/planner/audits/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/planner/audits/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/planner/audits/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', 'planner/audits/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "planner_audits_cancel",
"arguments": {
"id": 42
}
}
}
{
"data": {
"deleted": true
}
}
GET List audit plans
GET /planner/plans
Active plans whose locations are all within the token's planner.manage permission. A plan is a set of recurring series of one checklist on several locations.
Token scope read
Permission
planner.manage
MCP tool planner_plans_list · read-only
Responses
Status Description
200 OK
401 unauthorized — Missing, invalid, revoked or expired token
403 forbidden · insufficient_scope · plan_required — Token lacks planner.manage
429 rate_limited — Too many requests — retry after Retry-After seconds
Request
cURL
Node.js
Python
PHP
MCP
Copy
curl 'https://app.jecheck.io/api/ext/v1/planner/plans' \
-H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/planner/plans', {
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/planner/plans",
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', 'planner/plans', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "planner_plans_list",
"arguments": {}
}
}
{
"data": [
{
"key": "0b7c1f9e-2d4a-4f6b-8e3c-5a9d7b1c2e4f",
"title": "Weekly hall check",
"checklist": {
"id": 5845,
"name": "Daily dining room check"
},
"locations": [
{
"id": 12,
"name": "Abay Ave"
},
{
"id": 14,
"name": "Dostyk Plaza"
}
],
"auditor": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"recur": "weekly",
"weekdays": [
1,
4
],
"month_days": [],
"time": "09:00",
"duration_min": 60,
"start_date": "2026-11-03",
"end_date": "2027-02-03",
"tolerance_days": 1,
"notify": {
"email": true,
"day1": true,
"hour1": false,
"escalate": true
},
"series_ids": [
1842,
1843
]
}
]
}
GET Retrieve an audit plan
GET /planner/plans/{key}
Token scope read
Permission
planner.manage
MCP tool planner_plans_get · read-only
Path parameters
key
string
Required
Plan key (UUID, or s<id> for older single-series plans).
Responses
Status Description
200 OK
401 unauthorized — Missing, invalid, revoked or expired token
403 forbidden · insufficient_scope · plan_required — Token lacks planner.manage
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
Request
cURL
Node.js
Python
PHP
MCP
Copy
curl 'https://app.jecheck.io/api/ext/v1/planner/plans/string' \
-H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/planner/plans/string', {
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/planner/plans/string",
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', 'planner/plans/string', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "planner_plans_get",
"arguments": {
"key": "string"
}
}
}
{
"data": {
"key": "0b7c1f9e-2d4a-4f6b-8e3c-5a9d7b1c2e4f",
"title": "Weekly hall check",
"checklist": {
"id": 5845,
"name": "Daily dining room check"
},
"locations": [
{
"id": 12,
"name": "Abay Ave"
},
{
"id": 14,
"name": "Dostyk Plaza"
}
],
"auditor": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"recur": "weekly",
"weekdays": [
1,
4
],
"month_days": [],
"time": "09:00",
"duration_min": 60,
"start_date": "2026-11-03",
"end_date": "2027-02-03",
"tolerance_days": 1,
"notify": {
"email": true,
"day1": true,
"hour1": false,
"escalate": true
},
"series_ids": [
1842,
1843
]
}
}
POST Create an audit plan
POST /planner/plans
Creates a plan: one series per location with planned audits generated by the recurrence rule. Requires planner.manage on every location of the plan. The response contains the plan and how many audits were scheduled.
Token scope write
Permission
planner.manage
MCP tool planner_plans_create
Request body
title
string | null
Plan title; default "Plan: ".
Maximum length 255.
checklist_id
integer
Required
Checklist to audit.
location_ids
array<integer>
Required
Locations — one series per location.
Minimum items 1.
auditor_id
integer
Required
Auditor (user id); the checklist must be available to them.
recur
string
Required
none — once on start_date, daily, weekdays (Mon–Fri), weekly (on weekdays), monthly (on month_days).
nonedailyweekdaysweeklymonthly
weekdays
array<integer>
For weekly: days of week, 0 = Sunday … 6 = Saturday.
month_days
array<integer>
For monthly: days of month 1–31.
time
string
Start time HH:MM, default 09:00.
duration_min
integer
Planned duration, minutes (default 60).
Value 5–1440.
start_date
date
Required
First day of the plan.
end_date
date | null
Last day; default depends on the recurrence.
tolerance_days
integer
An audit conducted within ± this many days of the planned date counts; default depends on the frequency.
Value 0–14.
notify
object
Notifications.
email
boolean
Email the auditor about the plan.
day1
boolean
Remind a day before.
hour1
boolean
Remind an hour before.
escalate
boolean
Notify managers about missed audits.
Responses
Status Description
201 Created
401 unauthorized — Missing, invalid, revoked or expired token
403 forbidden · insufficient_scope · plan_required — Token lacks planner.manage, is read-only
422 validation_failed — Invalid parameters — see error.fields
429 rate_limited — Too many requests — retry after Retry-After seconds
Request
cURL
Node.js
Python
PHP
MCP
Copy
curl -X POST 'https://app.jecheck.io/api/ext/v1/planner/plans' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"title": "Replace the broken fridge seal",
"checklist_id": 42,
"location_ids": [
12,
14
],
"auditor_id": 42,
"recur": "none",
"start_date": "2026-11-01"
}'
const res = await fetch('https://app.jecheck.io/api/ext/v1/planner/plans', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"title": "Replace the broken fridge seal",
"checklist_id": 42,
"location_ids": [
12,
14
],
"auditor_id": 42,
"recur": "none",
"start_date": "2026-11-01"
}),
});
const { data } = await res.json();
import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/planner/plans",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"title":"Replace the broken fridge seal","checklist_id":42,"location_ids":[12,14],"auditor_id":42,"recur":"none","start_date":"2026-11-01"},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('POST', 'planner/plans', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'title' => 'Replace the broken fridge seal',
'checklist_id' => 42,
'location_ids' => [
12,
14,
],
'auditor_id' => 42,
'recur' => 'none',
'start_date' => '2026-11-01',
],
]);
$data = json_decode($res->getBody(), true)['data'];
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "planner_plans_create",
"arguments": {
"title": "Replace the broken fridge seal",
"checklist_id": 42,
"location_ids": [
12,
14
],
"auditor_id": 42,
"recur": "none",
"start_date": "2026-11-01"
}
}
}
{
"data": {
"plan": {
"key": "0b7c1f9e-2d4a-4f6b-8e3c-5a9d7b1c2e4f",
"title": "Weekly hall check",
"checklist": {
"id": 5845,
"name": "Daily dining room check"
},
"locations": [
{
"id": 12,
"name": "Abay Ave"
},
{
"id": 14,
"name": "Dostyk Plaza"
}
],
"auditor": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"recur": "weekly",
"weekdays": [
1,
4
],
"month_days": [],
"time": "09:00",
"duration_min": 60,
"start_date": "2026-11-03",
"end_date": "2027-02-03",
"tolerance_days": 1,
"notify": {
"email": true,
"day1": true,
"hour1": false,
"escalate": true
},
"series_ids": [
1842,
1843
]
},
"scheduled": 28
}
}
PUT Update an audit plan
PUT /planner/plans/{key}
Replaces the plan settings. Past audits stay as they are; upcoming ones (from today, except done) are regenerated. Removed locations lose their series, added ones get new series. Requires planner.manage on the old and new locations. upcoming — planned audits from today.
Token scope write
Permission
planner.manage
MCP tool planner_plans_update
Path parameters
key
string
Required
Plan key (UUID, or s<id> for older single-series plans).
Request body
title
string | null
Plan title; default "Plan: ".
Maximum length 255.
checklist_id
integer
Required
Checklist to audit.
location_ids
array<integer>
Required
Locations — one series per location.
Minimum items 1.
auditor_id
integer
Required
Auditor (user id); the checklist must be available to them.
recur
string
Required
none — once on start_date, daily, weekdays (Mon–Fri), weekly (on weekdays), monthly (on month_days).
nonedailyweekdaysweeklymonthly
weekdays
array<integer>
For weekly: days of week, 0 = Sunday … 6 = Saturday.
month_days
array<integer>
For monthly: days of month 1–31.
time
string
Start time HH:MM, default 09:00.
duration_min
integer
Planned duration, minutes (default 60).
Value 5–1440.
start_date
date
Required
First day of the plan.
end_date
date | null
Last day; default depends on the recurrence.
tolerance_days
integer
An audit conducted within ± this many days of the planned date counts; default depends on the frequency.
Value 0–14.
notify
object
Notifications.
email
boolean
Email the auditor about the plan.
day1
boolean
Remind a day before.
hour1
boolean
Remind an hour before.
escalate
boolean
Notify managers about missed audits.
Responses
Status Description
200 OK
401 unauthorized — Missing, invalid, revoked or expired token
403 forbidden · insufficient_scope · plan_required — Token lacks planner.manage, 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
Request
cURL
Node.js
Python
PHP
MCP
Copy
curl -X PUT 'https://app.jecheck.io/api/ext/v1/planner/plans/string' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"title": "Replace the broken fridge seal",
"checklist_id": 42,
"location_ids": [
12,
14
],
"auditor_id": 42,
"recur": "none",
"start_date": "2026-11-01"
}'
const res = await fetch('https://app.jecheck.io/api/ext/v1/planner/plans/string', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"title": "Replace the broken fridge seal",
"checklist_id": 42,
"location_ids": [
12,
14
],
"auditor_id": 42,
"recur": "none",
"start_date": "2026-11-01"
}),
});
const { data } = await res.json();
import os, requests
res = requests.put(
"https://app.jecheck.io/api/ext/v1/planner/plans/string",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"title":"Replace the broken fridge seal","checklist_id":42,"location_ids":[12,14],"auditor_id":42,"recur":"none","start_date":"2026-11-01"},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('PUT', 'planner/plans/string', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'title' => 'Replace the broken fridge seal',
'checklist_id' => 42,
'location_ids' => [
12,
14,
],
'auditor_id' => 42,
'recur' => 'none',
'start_date' => '2026-11-01',
],
]);
$data = json_decode($res->getBody(), true)['data'];
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "planner_plans_update",
"arguments": {
"key": "string",
"title": "Replace the broken fridge seal",
"checklist_id": 42,
"location_ids": [
12,
14
],
"auditor_id": 42,
"recur": "none",
"start_date": "2026-11-01"
}
}
}
{
"data": {
"plan": {
"key": "0b7c1f9e-2d4a-4f6b-8e3c-5a9d7b1c2e4f",
"title": "Weekly hall check",
"checklist": {
"id": 5845,
"name": "Daily dining room check"
},
"locations": [
{
"id": 12,
"name": "Abay Ave"
},
{
"id": 14,
"name": "Dostyk Plaza"
}
],
"auditor": {
"id": 311,
"uuid": "1e2d3c4b-5a69-4788-9a0b-1c2d3e4f5a6b",
"name": "Aigerim Sadykova"
},
"recur": "weekly",
"weekdays": [
1,
4
],
"month_days": [],
"time": "09:00",
"duration_min": 60,
"start_date": "2026-11-03",
"end_date": "2027-02-03",
"tolerance_days": 1,
"notify": {
"email": true,
"day1": true,
"hour1": false,
"escalate": true
},
"series_ids": [
1842,
1843
]
},
"upcoming": 18
}
}
DEL Delete an audit plan
DELETE /planner/plans/{key}
Stops the plan: its series are retired and upcoming planned audits (except done) are removed; history stays. removed — how many upcoming audits were removed.
Token scope write
Permission
planner.manage
MCP tool planner_plans_delete · destructive
Path parameters
key
string
Required
Plan key (UUID, or s<id> for older single-series plans).
Responses
Status Description
200 OK
401 unauthorized — Missing, invalid, revoked or expired token
403 forbidden · insufficient_scope · plan_required — Token lacks planner.manage, 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
Request
cURL
Node.js
Python
PHP
MCP
Copy
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/planner/plans/string' \
-H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/planner/plans/string', {
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/planner/plans/string",
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', 'planner/plans/string', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "planner_plans_delete",
"arguments": {
"key": "string"
}
}
}
{
"data": {
"deleted": true,
"removed": 12
}
}
GET List plan templates
GET /planner/templates
Saved plan settings shared in the company, to create similar plans quickly.
Token scope read
Permission
planner.manage
MCP tool planner_templates_list · read-only
Responses
Status Description
200 OK
401 unauthorized — Missing, invalid, revoked or expired token
403 forbidden · insufficient_scope · plan_required — Token lacks planner.manage
429 rate_limited — Too many requests — retry after Retry-After seconds
Request
cURL
Node.js
Python
PHP
MCP
Copy
curl 'https://app.jecheck.io/api/ext/v1/planner/templates' \
-H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/planner/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/planner/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', 'planner/templates', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "planner_templates_list",
"arguments": {}
}
}
{
"data": [
{
"id": 7,
"name": "Weekly hall check",
"settings": {
"title": "Weekly hall check",
"checklist_id": 5845,
"location_ids": [
12,
14
],
"auditor_id": 311,
"recur": "weekly",
"weekdays": [
1,
4
],
"month_days": [],
"time": "09:00",
"duration_min": 60,
"tolerance_days": 1,
"notify": {
"email": true,
"day1": true,
"hour1": false,
"escalate": true
}
}
}
]
}
POST Save a plan template
POST /planner/templates
Token scope write
Permission
planner.manage
MCP tool planner_templates_create
Request body
name
string
Required
Template name.
Length 1–255.
settings
object
Required
Any subset of the plan fields (same names as in planner.plans.create).
checklist_id
integer | null
location_ids
array<integer>
auditor_id
integer | null
recur
string | null
nonedailyweekdaysweeklymonthly
month_days
array<integer>
time
string | null
Maximum length 5.
duration_min
integer | null
Value 5–1440.
tolerance_days
integer | null
Value 0–14.
Responses
Status Description
201 Created
401 unauthorized — Missing, invalid, revoked or expired token
403 forbidden · insufficient_scope · plan_required — Token lacks planner.manage, is read-only
422 validation_failed — Invalid parameters — see error.fields
429 rate_limited — Too many requests — retry after Retry-After seconds
Request
cURL
Node.js
Python
PHP
MCP
Copy
curl -X POST 'https://app.jecheck.io/api/ext/v1/planner/templates' \
-H 'Authorization: Bearer $JECHECK_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "Replace the broken fridge seal",
"settings": {
"title": "Replace the broken fridge seal",
"checklist_id": 42,
"location_ids": [
12,
14
]
}
}'
const res = await fetch('https://app.jecheck.io/api/ext/v1/planner/templates', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Replace the broken fridge seal",
"settings": {
"title": "Replace the broken fridge seal",
"checklist_id": 42,
"location_ids": [
12,
14
]
}
}),
});
const { data } = await res.json();
import os, requests
res = requests.post(
"https://app.jecheck.io/api/ext/v1/planner/templates",
headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
json={"name":"Replace the broken fridge seal","settings":{"title":"Replace the broken fridge seal","checklist_id":42,"location_ids":[12,14]}},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);
$res = $client->request('POST', 'planner/templates', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
'json' => [
'name' => 'Replace the broken fridge seal',
'settings' => [
'title' => 'Replace the broken fridge seal',
'checklist_id' => 42,
'location_ids' => [
12,
14,
],
],
],
]);
$data = json_decode($res->getBody(), true)['data'];
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "planner_templates_create",
"arguments": {
"name": "Replace the broken fridge seal",
"settings": {
"title": "Replace the broken fridge seal",
"checklist_id": 42,
"location_ids": [
12,
14
]
}
}
}
}
{
"data": {
"id": 7,
"name": "Weekly hall check",
"settings": {
"title": "Weekly hall check",
"checklist_id": 5845,
"location_ids": [
12,
14
],
"auditor_id": 311,
"recur": "weekly",
"weekdays": [
1,
4
],
"month_days": [],
"time": "09:00",
"duration_min": 60,
"tolerance_days": 1,
"notify": {
"email": true,
"day1": true,
"hour1": false,
"escalate": true
}
}
}
}
DEL Delete a plan template
DELETE /planner/templates/{id}
Token scope write
Permission
planner.manage
MCP tool planner_templates_delete · destructive
Path parameters
id
integer
Required
Template id.
Responses
Status Description
200 OK
401 unauthorized — Missing, invalid, revoked or expired token
403 forbidden · insufficient_scope · plan_required — Token lacks planner.manage, 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
Request
cURL
Node.js
Python
PHP
MCP
Copy
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/planner/templates/42' \
-H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/planner/templates/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/planner/templates/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', 'planner/templates/42', [
'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "planner_templates_delete",
"arguments": {
"id": 42
}
}
}
{
"data": {
"deleted": true
}
}