jeCheckDevelopers
Get an API key

Instructions

Company knowledge base: folders, documents with published versions, read acknowledgements and editing. Visibility follows the document and folder permissions of the acting user ("who can view / who can edit"); content is returned as Markdown, HTML or plain text and accepted as Markdown or HTML.

Operations
GET/instructionsList instructions GET/instructions/badgeGet my reading counters GET/instructions/searchSearch instructions GET/instructions/treeGet the library tree GET/instructions/changesList instruction changes GET/instructions/by-ref/{ref}Find an instruction by external reference GET/instructions/{uuid}Retrieve an instruction GET/instructions/{uuid}/versionsList versions of an instruction GET/instructions/{uuid}/diffCompare versions GET/instructions/{uuid}/filesList instruction files POST/instructions/{uuid}/acknowledgeAcknowledge an instruction GET/instructions/{uuid}/acknowledgementsGet the acknowledgement report POST/instructions/{uuid}/remindRemind employees to read an instruction POST/instructionsCreate an instruction PATCH/instructions/{uuid}Update an instruction POST/instructions/{uuid}/publishPublish an instruction POST/instructions/{uuid}/discardDiscard draft changes POST/instructions/{uuid}/restoreRestore an old version to the draft POST/instructions/{uuid}/archiveArchive or unarchive an instruction POST/instructions/{uuid}/duplicateDuplicate an instruction POST/instructions/{uuid}/reviewedMark an instruction as reviewed DELETE/instructions/{uuid}Delete an instruction POST/instructions/{uuid}/filesUpload a file to an instruction GET/instructions/{uuid}/accessGet instruction permissions PUT/instructions/{uuid}/accessSet instruction permissions GET/instructions/foldersList folders POST/instructions/foldersCreate a folder PATCH/instructions/folders/{id}Update a folder DELETE/instructions/folders/{id}Delete a folder GET/instructions/folders/{id}/accessGet folder permissions PUT/instructions/folders/{id}/accessSet folder permissions

GETList instructions

GET /instructions

Instructions visible to the acting user, in library order. Readers get published documents; editors also get drafts and archived documents they can edit (filter with status). Read status (viewed, acknowledged, needs_ack) is for the acting user.

Token scoperead
Permission Any employee; results follow the token's visibility
MCP toolinstructions_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.
folder_id integer
Only documents directly in this folder.
root boolean
Only documents in the library root (no folder).
search string
Search in title, text, summary and tags. Maximum length 200.
status array<string>
Filter by status: draft, published, archived.
filter string
needs_ack — waiting for the acting user's acknowledgement; unread — never opened by the acting user.
needs_ackunread
tags array<string>
Only documents with any of these tags.
updated_since date-time
Only documents published (or, for editors, edited) after this moment — use for incremental sync.

Responses

StatusDescription
200OK — a page of results with meta
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Plan without API access
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl 'https://app.jecheck.io/api/ext/v1/instructions?folder_id=42' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/instructions?folder_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/instructions",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    params={"folder_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', 'instructions', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'query' => [
        'folder_id' => 42,
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_list",
        "arguments": {
            "folder_id": 42
        }
    }
}
Response 200
{
  "data": [
    {
      "uuid": "5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a",
      "title": "Opening the coffee shop",
      "icon": "coffee",
      "summary": "Morning checklist for baristas",
      "folder_id": 14,
      "status": "published",
      "version": 3,
      "published_at": "2026-10-28T09:12:00+05:00",
      "updated_at": "2026-10-28T09:12:00+05:00",
      "require_ack": true,
      "tags": [
        "Barista",
        "Opening"
      ],
      "words": 412,
      "viewed": true,
      "acknowledged": false,
      "needs_ack": true,
      "has_unpublished_changes": null,
      "can_edit": false,
      "url": "https://app.jecheck.io/ui/instructions/5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 25,
    "total": 1,
    "has_more": false
  }
}

GETGet my reading counters

GET /instructions/badge

Counters for the acting user over the published instructions they can read: total, never opened, and waiting for acknowledgement.

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

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Plan without API access
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl 'https://app.jecheck.io/api/ext/v1/instructions/badge' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/instructions/badge', {
  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/instructions/badge",
    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', 'instructions/badge', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_badge",
        "arguments": {}
    }
}
Response 200
{
  "data": {
    "total": 42,
    "unread": 5,
    "needs_ack": 2
  }
}

GETGet the library tree

GET /instructions/tree

The whole library in one call: the folder tree (with document counts and edit rights) and the list of documents visible to the acting user (see instructions.list for the item shape).

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

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Plan without API access
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl 'https://app.jecheck.io/api/ext/v1/instructions/tree' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/instructions/tree', {
  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/instructions/tree",
    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', 'instructions/tree', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_tree",
        "arguments": {}
    }
}
Response 200
{
  "data": {
    "folders": [
      {
        "id": 14,
        "parent_id": 3,
        "name": "Barista",
        "icon": "coffee",
        "color": null,
        "count": 6,
        "total": 6,
        "can_edit": false,
        "restricted": false,
        "children": []
      }
    ],
    "documents": [
      {
        "uuid": "5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a",
        "title": "Opening the coffee shop",
        "icon": "coffee",
        "summary": "Morning checklist for baristas",
        "folder_id": 14,
        "status": "published",
        "version": 3,
        "published_at": "2026-10-28T09:12:00+05:00",
        "updated_at": "2026-10-28T09:12:00+05:00",
        "require_ack": true,
        "tags": [
          "Barista",
          "Opening"
        ],
        "words": 412,
        "viewed": true,
        "acknowledged": false,
        "needs_ack": true,
        "has_unpublished_changes": null,
        "can_edit": false,
        "url": "https://app.jecheck.io/ui/instructions/5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a"
      }
    ],
    "can_create_in_root": false
  }
}

GETList instruction changes

GET /instructions/changes

Change feed for mirrors and caches, oldest first: every document of the company changed after updated_since, with state = active (published and readable by the acting user) or removed (deleted, archived, unpublished or no longer visible). Store the last updated_at and pass it as updated_since next time.

Token scoperead
Permission Any employee; results follow the token's visibility
MCP toolinstructions_changes · 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.
updated_since date-time
Only changes after this moment; omit for a full snapshot.

Responses

StatusDescription
200OK — a page of results with meta
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Plan without API access
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl 'https://app.jecheck.io/api/ext/v1/instructions/changes?updated_since=2026-11-03T09:00:00+05:00' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/instructions/changes?updated_since=2026-11-03T09:00:00+05:00', {
  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/instructions/changes",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    params={"updated_since":"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', 'instructions/changes', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'query' => [
        'updated_since' => '2026-11-03T09:00:00+05:00',
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_changes",
        "arguments": {
            "updated_since": "2026-11-03T09:00:00+05:00"
        }
    }
}
Response 200
{
  "data": [
    {
      "uuid": "5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a",
      "state": "active",
      "version": 3,
      "updated_at": "2026-10-28T09:12:00+05:00"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 25,
    "total": 1,
    "has_more": false
  }
}

GETFind an instruction by external reference

GET /instructions/by-ref/{ref}

Resolves an external reference (for example confluence:12345 for pages imported from Confluence) to the instruction UUID — use it to redirect old links.

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

Path parameters

ref string Required
External reference, e.g. confluence:12345.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Plan without API access
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl 'https://app.jecheck.io/api/ext/v1/instructions/by-ref/string' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/instructions/by-ref/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/instructions/by-ref/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', 'instructions/by-ref/string', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_by_ref",
        "arguments": {
            "ref": "string"
        }
    }
}
Response 200
{
  "data": {
    "uuid": "5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a",
    "title": "Opening the coffee shop",
    "url": "https://app.jecheck.io/ui/instructions/5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a"
  }
}

GETRetrieve an instruction

GET /instructions/{uuid}

The current published version of a document (or an older one with version) with its content in Markdown (default), HTML or plain text, the table of contents, attachments with download links and the acting user's acknowledgement status. Editors can request the unpublished draft with draft=true; a never-published document returns its draft. Pass track=true to count the call as a view by the acting user (as when the employee opens it in the app).

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

Path parameters

uuid uuid Required
Instruction UUID.

Query parameters

format string
Format of content. Default markdown.
markdownhtmltext
version integer
Version number (default — current published version). Minimum 1.
draft boolean
Return the working draft (editors only).
track boolean
Record a view of the current version by the acting user.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Plan without API access
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl 'https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b?format=markdown' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b?format=markdown', {
  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/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    params={"format":"markdown"},
)
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', 'instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'query' => [
        'format' => 'markdown',
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_get",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
            "format": "markdown"
        }
    }
}
Response 200
{
  "data": {
    "uuid": "5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a",
    "title": "Opening the coffee shop",
    "icon": "coffee",
    "summary": "Morning checklist for baristas",
    "status": "published",
    "folder": {
      "id": 14,
      "name": "Barista"
    },
    "folder_path": [
      {
        "id": 3,
        "name": "Operations"
      },
      {
        "id": 14,
        "name": "Barista"
      }
    ],
    "tags": [
      "Barista",
      "Opening"
    ],
    "version": 3,
    "is_latest": true,
    "is_draft": false,
    "published_at": "2026-10-28T09:12:00+05:00",
    "published_by": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "change_note": "New grinder settings",
    "is_major": true,
    "versions_count": 3,
    "format": "markdown",
    "content": "## Before opening\n\n1. Turn on the espresso machine\n2. Calibrate the grinder\n\n> **Important:** check fridge temperatures.",
    "toc": [
      {
        "id": "before-opening",
        "text": "Before opening",
        "level": 2
      }
    ],
    "words": 412,
    "read_minutes": 3,
    "require_ack": true,
    "acknowledged": false,
    "needs_ack": true,
    "attachments": [
      {
        "uuid": "0c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
        "kind": "file",
        "name": "Cleaning schedule.pdf",
        "mime": "application/pdf",
        "size": 182044,
        "width": null,
        "height": null,
        "url": "https://files.jecheck.io/instructions/761/2026/11/0c1d2e3f.pdf"
      }
    ],
    "can_edit": true,
    "has_unpublished_changes": false,
    "review_every_days": 180,
    "review_due_at": "2027-04-26",
    "owner": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "updated_at": "2026-10-28T09:12:00+05:00",
    "url": "https://app.jecheck.io/ui/instructions/5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a"
  }
}

GETList versions of an instruction

GET /instructions/{uuid}/versions

Published versions, newest first. Read an older version with GET /instructions/{uuid}?version=N.

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

Path parameters

uuid uuid Required
Instruction UUID.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Plan without API access
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl 'https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/versions' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/versions', {
  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/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/versions",
    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', 'instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/versions', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_versions",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
        }
    }
}
Response 200
{
  "data": [
    {
      "number": 3,
      "title": "Opening the coffee shop",
      "change_note": "New grinder settings",
      "is_major": true,
      "words": 412,
      "published_by": {
        "id": 120,
        "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
        "name": "Daniyar Omarov"
      },
      "published_at": "2026-10-28T09:12:00+05:00",
      "is_latest": true
    }
  ]
}

GETCompare versions

GET /instructions/{uuid}/diff

Block-level comparison of two versions: from (0 — empty document) and to (default — current version; editors may pass draft). Each block is HTML with op = added, removed or same.

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

Path parameters

uuid uuid Required
Instruction UUID.

Query parameters

from integer Required
Version number to compare from (0 — empty). Minimum 0.
to string
Version number to compare to, or draft (editors only). Default — current version. Maximum length 10.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Plan without API access
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl 'https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/diff?from=42' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/diff?from=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/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/diff",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    params={"from":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', 'instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/diff', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'query' => [
        'from' => 42,
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_diff",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
            "from": 42
        }
    }
}
Response 200
{
  "data": {
    "from": 2,
    "to": "3",
    "blocks": [
      {
        "op": "removed",
        "html": "<p>Grind size 12</p>"
      },
      {
        "op": "added",
        "html": "<p>Grind size 10</p>"
      }
    ],
    "added": 1,
    "removed": 1
  }
}

GETList instruction files

GET /instructions/{uuid}/files

Images and attachments used in the current published version (editors: in the draft with draft=true) with download links.

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

Path parameters

uuid uuid Required
Instruction UUID.

Query parameters

draft boolean
Files of the working draft (editors only).

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Plan without API access
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl 'https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/files?draft=true' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/files?draft=true', {
  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/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/files",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    params={"draft":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', 'instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/files', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'query' => [
        'draft' => true,
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_files_list",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
            "draft": true
        }
    }
}
Response 200
{
  "data": [
    {
      "uuid": "0c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
      "kind": "file",
      "name": "Cleaning schedule.pdf",
      "mime": "application/pdf",
      "size": 182044,
      "width": null,
      "height": null,
      "url": "https://files.jecheck.io/instructions/761/2026/11/0c1d2e3f.pdf"
    }
  ]
}

POSTAcknowledge an instruction

POST /instructions/{uuid}/acknowledge

Records that the acting user has read the current version ("I have read it"). Required again after each major version when the document has require_ack.

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

Path parameters

uuid uuid Required
Instruction UUID.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X POST 'https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/acknowledge' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/acknowledge', {
  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/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/acknowledge",
    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', 'instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/acknowledge', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_acknowledge",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
        }
    }
}
Response 200
{
  "data": {
    "acknowledged": true,
    "version": 3
  }
}

GETGet the acknowledgement report

GET /instructions/{uuid}/acknowledgements

Who in the audience of the document has opened and acknowledged the current major version. Editors of the document only.

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

Path parameters

uuid uuid Required
Instruction UUID.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Plan without API access
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl 'https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/acknowledgements' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/acknowledgements', {
  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/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/acknowledgements",
    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', 'instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/acknowledgements', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_acknowledgements",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
        }
    }
}
Response 200
{
  "data": {
    "total": 18,
    "viewed": 15,
    "acknowledged": 12,
    "ack_rate": 67,
    "ack_since_version": 3,
    "users": [
      {
        "user": {
          "id": 120,
          "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
          "name": "Daniyar Omarov"
        },
        "position": "Barista",
        "last_viewed_at": "2026-10-29T08:01:00+05:00",
        "viewed_version": 3,
        "acknowledged_at": "2026-10-29T08:03:00+05:00",
        "source": "app"
      }
    ]
  }
}

POSTRemind employees to read an instruction

POST /instructions/{uuid}/remind

Sends a push / in-app notification to everyone in the audience who has not acknowledged the current version yet.

Token scopewrite
Permission Any employee; results follow the token's visibility
Plan featureinstructions_pro
MCP toolinstructions_remind

Path parameters

uuid uuid Required
Instruction UUID.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X POST 'https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/remind' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/remind', {
  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/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/remind",
    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', 'instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/remind', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_remind",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
        }
    }
}
Response 200
{
  "data": {
    "reminded": 6
  }
}

POSTCreate an instruction

POST /instructions

Creates a draft in a folder where the acting user can edit (the library root — knowledge-base managers only). Content is converted to the editor format; pass publish=true to publish the first version right away (employees are notified).

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

Request body

title string Required
Title. Length 1–250.
content string
Body text. Maximum length 500000.
content_format string
Format of content, default markdown. HTML is sanitised to text formatting, headings, lists, tables, quotes, code and links; add images and files with the upload operation.
markdownhtmltext
template string
Start from a built-in template (ignored when content is passed).
sopopeningsanitationequipment
folder_id integer | null
Folder id (null — library root, managers only). Moving requires edit rights on the target folder.
icon string | null
Material Symbols icon name. Maximum length 40.
summary string | null
Short description shown in the list. Maximum length 500.
require_ack boolean
Employees must confirm they have read each major version.
review_every_days integer | null
Review period in days (null — no review reminders). Value 1–1095.
owner_id integer | null
Responsible user id.
tags array<string>
Tags (replace the current ones). Maximum items 20.
ai_visibility string
Visibility for the external AI knowledge base (only when the AI knowledge base is enabled for the company; managers only).
inheritnonestaffclient
ai_note string | null
Hint for the external AI (same conditions as ai_visibility). Maximum length 2000.
publish boolean
Publish the first version immediately.
change_note string
Version note when publishing. Maximum length 490.

Responses

StatusDescription
201Created
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X POST 'https://app.jecheck.io/api/ext/v1/instructions' \
  -H 'Authorization: Bearer $JECHECK_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "Replace the broken fridge seal",
    "content": "string",
    "content_format": "markdown",
    "template": "sop"
}'
const res = await fetch('https://app.jecheck.io/api/ext/v1/instructions', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "title": "Replace the broken fridge seal",
      "content": "string",
      "content_format": "markdown",
      "template": "sop"
  }),
});
const { data } = await res.json();
import os, requests

res = requests.post(
    "https://app.jecheck.io/api/ext/v1/instructions",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    json={"title":"Replace the broken fridge seal","content":"string","content_format":"markdown","template":"sop"},
)
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', 'instructions', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'json' => [
        'title' => 'Replace the broken fridge seal',
        'content' => 'string',
        'content_format' => 'markdown',
        'template' => 'sop',
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_create",
        "arguments": {
            "title": "Replace the broken fridge seal",
            "content": "string",
            "content_format": "markdown",
            "template": "sop"
        }
    }
}
Response 201
{
  "data": {
    "uuid": "5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a",
    "title": "Opening the coffee shop",
    "icon": "coffee",
    "summary": "Morning checklist for baristas",
    "status": "published",
    "folder": {
      "id": 14,
      "name": "Barista"
    },
    "folder_path": [
      {
        "id": 3,
        "name": "Operations"
      },
      {
        "id": 14,
        "name": "Barista"
      }
    ],
    "tags": [
      "Barista",
      "Opening"
    ],
    "version": 3,
    "is_latest": true,
    "is_draft": false,
    "published_at": "2026-10-28T09:12:00+05:00",
    "published_by": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "change_note": "New grinder settings",
    "is_major": true,
    "versions_count": 3,
    "format": "markdown",
    "content": "## Before opening\n\n1. Turn on the espresso machine\n2. Calibrate the grinder\n\n> **Important:** check fridge temperatures.",
    "toc": [
      {
        "id": "before-opening",
        "text": "Before opening",
        "level": 2
      }
    ],
    "words": 412,
    "read_minutes": 3,
    "require_ack": true,
    "acknowledged": false,
    "needs_ack": true,
    "attachments": [
      {
        "uuid": "0c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
        "kind": "file",
        "name": "Cleaning schedule.pdf",
        "mime": "application/pdf",
        "size": 182044,
        "width": null,
        "height": null,
        "url": "https://files.jecheck.io/instructions/761/2026/11/0c1d2e3f.pdf"
      }
    ],
    "can_edit": true,
    "has_unpublished_changes": false,
    "review_every_days": 180,
    "review_due_at": "2027-04-26",
    "owner": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "updated_at": "2026-10-28T09:12:00+05:00",
    "url": "https://app.jecheck.io/ui/instructions/5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a"
  }
}

PATCHUpdate an instruction

PATCH /instructions/{uuid}

Edits the working draft (title, content) and document settings. Changes to title or content are saved to the draft and become visible to readers only after publish; settings (folder, tags, review period, acknowledgement) apply immediately. Moving to another folder requires edit rights on it.

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

Path parameters

uuid uuid Required
Instruction UUID.

Request body

title string
Title (draft). Length 1–250.
content string
New body text, replaces the draft content. Maximum length 500000.
content_format string
Format of content, default markdown. HTML is sanitised to text formatting, headings, lists, tables, quotes, code and links; add images and files with the upload operation.
markdownhtmltext
folder_id integer | null
Folder id (null — library root, managers only). Moving requires edit rights on the target folder.
icon string | null
Material Symbols icon name. Maximum length 40.
summary string | null
Short description shown in the list. Maximum length 500.
require_ack boolean
Employees must confirm they have read each major version.
review_every_days integer | null
Review period in days (null — no review reminders). Value 1–1095.
owner_id integer | null
Responsible user id.
tags array<string>
Tags (replace the current ones). Maximum items 20.
ai_visibility string
Visibility for the external AI knowledge base (only when the AI knowledge base is enabled for the company; managers only).
inheritnonestaffclient
ai_note string | null
Hint for the external AI (same conditions as ai_visibility). Maximum length 2000.

Responses

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

res = requests.patch(
    "https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    json={"title":"Replace the broken fridge seal","content":"string","content_format":"markdown","folder_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('PATCH', 'instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'json' => [
        'title' => 'Replace the broken fridge seal',
        'content' => 'string',
        'content_format' => 'markdown',
        'folder_id' => 42,
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_update",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
            "title": "Replace the broken fridge seal",
            "content": "string",
            "content_format": "markdown",
            "folder_id": 42
        }
    }
}
Response 200
{
  "data": {
    "uuid": "5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a",
    "title": "Opening the coffee shop",
    "icon": "coffee",
    "summary": "Morning checklist for baristas",
    "status": "published",
    "folder": {
      "id": 14,
      "name": "Barista"
    },
    "folder_path": [
      {
        "id": 3,
        "name": "Operations"
      },
      {
        "id": 14,
        "name": "Barista"
      }
    ],
    "tags": [
      "Barista",
      "Opening"
    ],
    "version": 3,
    "is_latest": true,
    "is_draft": false,
    "published_at": "2026-10-28T09:12:00+05:00",
    "published_by": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "change_note": "New grinder settings",
    "is_major": true,
    "versions_count": 3,
    "format": "markdown",
    "content": "## Before opening\n\n1. Turn on the espresso machine\n2. Calibrate the grinder\n\n> **Important:** check fridge temperatures.",
    "toc": [
      {
        "id": "before-opening",
        "text": "Before opening",
        "level": 2
      }
    ],
    "words": 412,
    "read_minutes": 3,
    "require_ack": true,
    "acknowledged": false,
    "needs_ack": true,
    "attachments": [
      {
        "uuid": "0c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
        "kind": "file",
        "name": "Cleaning schedule.pdf",
        "mime": "application/pdf",
        "size": 182044,
        "width": null,
        "height": null,
        "url": "https://files.jecheck.io/instructions/761/2026/11/0c1d2e3f.pdf"
      }
    ],
    "can_edit": true,
    "has_unpublished_changes": false,
    "review_every_days": 180,
    "review_due_at": "2027-04-26",
    "owner": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "updated_at": "2026-10-28T09:12:00+05:00",
    "url": "https://app.jecheck.io/ui/instructions/5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a"
  }
}

POSTPublish an instruction

POST /instructions/{uuid}/publish

Publishes the draft as a new version. A major version (default) requires a new acknowledgement and notifies employees; a minor one notifies only when notify=true.

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

Path parameters

uuid uuid Required
Instruction UUID.

Request body

change_note string
What changed. Maximum length 490.
is_major boolean
Major version, default true.
notify boolean
Notify employees (default — only for a major version).

Responses

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

res = requests.post(
    "https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/publish",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    json={"change_note":"string","is_major":True,"notify":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', 'instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/publish', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'json' => [
        'change_note' => 'string',
        'is_major' => true,
        'notify' => true,
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_publish",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
            "change_note": "string",
            "is_major": true,
            "notify": true
        }
    }
}
Response 200
{
  "data": {
    "uuid": "5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a",
    "title": "Opening the coffee shop",
    "icon": "coffee",
    "summary": "Morning checklist for baristas",
    "status": "published",
    "folder": {
      "id": 14,
      "name": "Barista"
    },
    "folder_path": [
      {
        "id": 3,
        "name": "Operations"
      },
      {
        "id": 14,
        "name": "Barista"
      }
    ],
    "tags": [
      "Barista",
      "Opening"
    ],
    "version": 3,
    "is_latest": true,
    "is_draft": false,
    "published_at": "2026-10-28T09:12:00+05:00",
    "published_by": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "change_note": "New grinder settings",
    "is_major": true,
    "versions_count": 3,
    "format": "markdown",
    "content": "## Before opening\n\n1. Turn on the espresso machine\n2. Calibrate the grinder\n\n> **Important:** check fridge temperatures.",
    "toc": [
      {
        "id": "before-opening",
        "text": "Before opening",
        "level": 2
      }
    ],
    "words": 412,
    "read_minutes": 3,
    "require_ack": true,
    "acknowledged": false,
    "needs_ack": true,
    "attachments": [
      {
        "uuid": "0c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
        "kind": "file",
        "name": "Cleaning schedule.pdf",
        "mime": "application/pdf",
        "size": 182044,
        "width": null,
        "height": null,
        "url": "https://files.jecheck.io/instructions/761/2026/11/0c1d2e3f.pdf"
      }
    ],
    "can_edit": true,
    "has_unpublished_changes": false,
    "review_every_days": 180,
    "review_due_at": "2027-04-26",
    "owner": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "updated_at": "2026-10-28T09:12:00+05:00",
    "url": "https://app.jecheck.io/ui/instructions/5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a"
  }
}

POSTDiscard draft changes

POST /instructions/{uuid}/discard

Resets the draft to the current published version.

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

Path parameters

uuid uuid Required
Instruction UUID.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X POST 'https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/discard' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/discard', {
  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/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/discard",
    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', 'instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/discard', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_discard",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
        }
    }
}
Response 200
{
  "data": {
    "uuid": "5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a",
    "title": "Opening the coffee shop",
    "icon": "coffee",
    "summary": "Morning checklist for baristas",
    "status": "published",
    "folder": {
      "id": 14,
      "name": "Barista"
    },
    "folder_path": [
      {
        "id": 3,
        "name": "Operations"
      },
      {
        "id": 14,
        "name": "Barista"
      }
    ],
    "tags": [
      "Barista",
      "Opening"
    ],
    "version": 3,
    "is_latest": true,
    "is_draft": false,
    "published_at": "2026-10-28T09:12:00+05:00",
    "published_by": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "change_note": "New grinder settings",
    "is_major": true,
    "versions_count": 3,
    "format": "markdown",
    "content": "## Before opening\n\n1. Turn on the espresso machine\n2. Calibrate the grinder\n\n> **Important:** check fridge temperatures.",
    "toc": [
      {
        "id": "before-opening",
        "text": "Before opening",
        "level": 2
      }
    ],
    "words": 412,
    "read_minutes": 3,
    "require_ack": true,
    "acknowledged": false,
    "needs_ack": true,
    "attachments": [
      {
        "uuid": "0c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
        "kind": "file",
        "name": "Cleaning schedule.pdf",
        "mime": "application/pdf",
        "size": 182044,
        "width": null,
        "height": null,
        "url": "https://files.jecheck.io/instructions/761/2026/11/0c1d2e3f.pdf"
      }
    ],
    "can_edit": true,
    "has_unpublished_changes": false,
    "review_every_days": 180,
    "review_due_at": "2027-04-26",
    "owner": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "updated_at": "2026-10-28T09:12:00+05:00",
    "url": "https://app.jecheck.io/ui/instructions/5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a"
  }
}

POSTRestore an old version to the draft

POST /instructions/{uuid}/restore

Copies an older version into the draft; publish it to make it current again.

Token scopewrite
Permission Any employee; results follow the token's visibility
Plan featureinstructions_pro
MCP toolinstructions_restore

Path parameters

uuid uuid Required
Instruction UUID.

Request body

version integer Required
Version number to restore. Minimum 1.

Responses

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

res = requests.post(
    "https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/restore",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    json={"version":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', 'instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/restore', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'json' => [
        'version' => 42,
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_restore",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
            "version": 42
        }
    }
}
Response 200
{
  "data": {
    "uuid": "5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a",
    "title": "Opening the coffee shop",
    "icon": "coffee",
    "summary": "Morning checklist for baristas",
    "status": "published",
    "folder": {
      "id": 14,
      "name": "Barista"
    },
    "folder_path": [
      {
        "id": 3,
        "name": "Operations"
      },
      {
        "id": 14,
        "name": "Barista"
      }
    ],
    "tags": [
      "Barista",
      "Opening"
    ],
    "version": 3,
    "is_latest": true,
    "is_draft": false,
    "published_at": "2026-10-28T09:12:00+05:00",
    "published_by": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "change_note": "New grinder settings",
    "is_major": true,
    "versions_count": 3,
    "format": "markdown",
    "content": "## Before opening\n\n1. Turn on the espresso machine\n2. Calibrate the grinder\n\n> **Important:** check fridge temperatures.",
    "toc": [
      {
        "id": "before-opening",
        "text": "Before opening",
        "level": 2
      }
    ],
    "words": 412,
    "read_minutes": 3,
    "require_ack": true,
    "acknowledged": false,
    "needs_ack": true,
    "attachments": [
      {
        "uuid": "0c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
        "kind": "file",
        "name": "Cleaning schedule.pdf",
        "mime": "application/pdf",
        "size": 182044,
        "width": null,
        "height": null,
        "url": "https://files.jecheck.io/instructions/761/2026/11/0c1d2e3f.pdf"
      }
    ],
    "can_edit": true,
    "has_unpublished_changes": false,
    "review_every_days": 180,
    "review_due_at": "2027-04-26",
    "owner": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "updated_at": "2026-10-28T09:12:00+05:00",
    "url": "https://app.jecheck.io/ui/instructions/5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a"
  }
}

POSTArchive or unarchive an instruction

POST /instructions/{uuid}/archive

Archived documents are hidden from readers. Pass archived=false to return a document from the archive.

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

Path parameters

uuid uuid Required
Instruction UUID.

Request body

archived boolean
Default true.

Responses

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

res = requests.post(
    "https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/archive",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    json={"archived":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', 'instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/archive', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'json' => [
        'archived' => true,
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_archive",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
            "archived": true
        }
    }
}
Response 200
{
  "data": {
    "uuid": "5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a",
    "title": "Opening the coffee shop",
    "icon": "coffee",
    "summary": "Morning checklist for baristas",
    "status": "published",
    "folder": {
      "id": 14,
      "name": "Barista"
    },
    "folder_path": [
      {
        "id": 3,
        "name": "Operations"
      },
      {
        "id": 14,
        "name": "Barista"
      }
    ],
    "tags": [
      "Barista",
      "Opening"
    ],
    "version": 3,
    "is_latest": true,
    "is_draft": false,
    "published_at": "2026-10-28T09:12:00+05:00",
    "published_by": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "change_note": "New grinder settings",
    "is_major": true,
    "versions_count": 3,
    "format": "markdown",
    "content": "## Before opening\n\n1. Turn on the espresso machine\n2. Calibrate the grinder\n\n> **Important:** check fridge temperatures.",
    "toc": [
      {
        "id": "before-opening",
        "text": "Before opening",
        "level": 2
      }
    ],
    "words": 412,
    "read_minutes": 3,
    "require_ack": true,
    "acknowledged": false,
    "needs_ack": true,
    "attachments": [
      {
        "uuid": "0c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
        "kind": "file",
        "name": "Cleaning schedule.pdf",
        "mime": "application/pdf",
        "size": 182044,
        "width": null,
        "height": null,
        "url": "https://files.jecheck.io/instructions/761/2026/11/0c1d2e3f.pdf"
      }
    ],
    "can_edit": true,
    "has_unpublished_changes": false,
    "review_every_days": 180,
    "review_due_at": "2027-04-26",
    "owner": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "updated_at": "2026-10-28T09:12:00+05:00",
    "url": "https://app.jecheck.io/ui/instructions/5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a"
  }
}

POSTDuplicate an instruction

POST /instructions/{uuid}/duplicate

Creates a draft copy in the same folder with the same settings and permissions.

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

Path parameters

uuid uuid Required
Instruction UUID.

Responses

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

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

$res = $client->request('POST', 'instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/duplicate', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_duplicate",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
        }
    }
}
Response 201
{
  "data": {
    "uuid": "5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a",
    "title": "Opening the coffee shop",
    "icon": "coffee",
    "summary": "Morning checklist for baristas",
    "status": "published",
    "folder": {
      "id": 14,
      "name": "Barista"
    },
    "folder_path": [
      {
        "id": 3,
        "name": "Operations"
      },
      {
        "id": 14,
        "name": "Barista"
      }
    ],
    "tags": [
      "Barista",
      "Opening"
    ],
    "version": 3,
    "is_latest": true,
    "is_draft": false,
    "published_at": "2026-10-28T09:12:00+05:00",
    "published_by": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "change_note": "New grinder settings",
    "is_major": true,
    "versions_count": 3,
    "format": "markdown",
    "content": "## Before opening\n\n1. Turn on the espresso machine\n2. Calibrate the grinder\n\n> **Important:** check fridge temperatures.",
    "toc": [
      {
        "id": "before-opening",
        "text": "Before opening",
        "level": 2
      }
    ],
    "words": 412,
    "read_minutes": 3,
    "require_ack": true,
    "acknowledged": false,
    "needs_ack": true,
    "attachments": [
      {
        "uuid": "0c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
        "kind": "file",
        "name": "Cleaning schedule.pdf",
        "mime": "application/pdf",
        "size": 182044,
        "width": null,
        "height": null,
        "url": "https://files.jecheck.io/instructions/761/2026/11/0c1d2e3f.pdf"
      }
    ],
    "can_edit": true,
    "has_unpublished_changes": false,
    "review_every_days": 180,
    "review_due_at": "2027-04-26",
    "owner": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "updated_at": "2026-10-28T09:12:00+05:00",
    "url": "https://app.jecheck.io/ui/instructions/5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a"
  }
}

POSTMark an instruction as reviewed

POST /instructions/{uuid}/reviewed

Confirms the document is still up to date without changes: the next review date moves one period ahead. Only for published documents with a review period.

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

Path parameters

uuid uuid Required
Instruction UUID.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X POST 'https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/reviewed' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/reviewed', {
  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/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/reviewed",
    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', 'instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/reviewed', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_reviewed",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
        }
    }
}
Response 200
{
  "data": {
    "uuid": "5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a",
    "title": "Opening the coffee shop",
    "icon": "coffee",
    "summary": "Morning checklist for baristas",
    "status": "published",
    "folder": {
      "id": 14,
      "name": "Barista"
    },
    "folder_path": [
      {
        "id": 3,
        "name": "Operations"
      },
      {
        "id": 14,
        "name": "Barista"
      }
    ],
    "tags": [
      "Barista",
      "Opening"
    ],
    "version": 3,
    "is_latest": true,
    "is_draft": false,
    "published_at": "2026-10-28T09:12:00+05:00",
    "published_by": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "change_note": "New grinder settings",
    "is_major": true,
    "versions_count": 3,
    "format": "markdown",
    "content": "## Before opening\n\n1. Turn on the espresso machine\n2. Calibrate the grinder\n\n> **Important:** check fridge temperatures.",
    "toc": [
      {
        "id": "before-opening",
        "text": "Before opening",
        "level": 2
      }
    ],
    "words": 412,
    "read_minutes": 3,
    "require_ack": true,
    "acknowledged": false,
    "needs_ack": true,
    "attachments": [
      {
        "uuid": "0c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
        "kind": "file",
        "name": "Cleaning schedule.pdf",
        "mime": "application/pdf",
        "size": 182044,
        "width": null,
        "height": null,
        "url": "https://files.jecheck.io/instructions/761/2026/11/0c1d2e3f.pdf"
      }
    ],
    "can_edit": true,
    "has_unpublished_changes": false,
    "review_every_days": 180,
    "review_due_at": "2027-04-26",
    "owner": {
      "id": 120,
      "uuid": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
      "name": "Daniyar Omarov"
    },
    "updated_at": "2026-10-28T09:12:00+05:00",
    "url": "https://app.jecheck.io/ui/instructions/5d3c2b1a-9f8e-4d7c-8b6a-5f4e3d2c1b0a"
  }
}

DELDelete an instruction

DELETE /instructions/{uuid}
Token scopewrite
Permission Any employee; results follow the token's visibility
MCP toolinstructions_delete · destructive

Path parameters

uuid uuid Required
Instruction UUID.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/instructions/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/instructions/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', 'instructions/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": "instructions_delete",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
        }
    }
}
Response 200
{
  "data": {
    "deleted": true
  }
}

POSTUpload a file to an instruction

POST /instructions/{uuid}/files

Uploads an image (JPEG, PNG, WebP, GIF up to 15 MB) or a file (PDF, Office, TXT, CSV, ZIP, MP4, MOV up to 50 MB) and, by default, appends it to the end of the draft as an image or attachment block. Publish to show it to readers.

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

Path parameters

uuid uuid Required
Instruction UUID.

Request body

file file Required
append boolean
Append to the end of the draft, default true.

Responses

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

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

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

$res = $client->request('POST', 'instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/files', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'multipart' => [
        ['name' => 'append', 'contents' => '1'],
        ['name' => 'file', 'contents' => fopen('photo.jpg', 'r')],
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_files_upload",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
            "append": true
        }
    }
}
Response 201
{
  "data": {
    "uuid": "0c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
    "kind": "file",
    "name": "Cleaning schedule.pdf",
    "mime": "application/pdf",
    "size": 182044,
    "width": null,
    "height": null,
    "url": "https://files.jecheck.io/instructions/761/2026/11/0c1d2e3f.pdf"
  }
}

GETGet instruction permissions

GET /instructions/{uuid}/access

Who can view and who can edit the document, plus folders above that restrict viewing and the inherited editors. Editors of the document only.

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

Path parameters

uuid uuid Required
Instruction UUID.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Plan without API access
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl 'https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/access' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/access', {
  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/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/access",
    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', 'instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/access', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_access_get",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
        }
    }
}
Response 200
{
  "data": {
    "view": [
      {
        "type": "position",
        "id": 7,
        "name": "Barista"
      },
      {
        "type": "department",
        "id": 12,
        "name": "Abay Ave"
      }
    ],
    "edit": [
      {
        "type": "user",
        "id": 120,
        "name": "Daniyar Omarov"
      }
    ],
    "restricted_by": [],
    "inherited_edit": {
      "folder": null,
      "subjects": []
    }
  }
}

PUTSet instruction permissions

PUT /instructions/{uuid}/access

Replaces the view and/or edit lists of the document. Subjects: user, position, department (location), team. If the change would remove the acting user's own edit rights, they are kept as an editor.

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

Path parameters

uuid uuid Required
Instruction UUID.

Request body

view array<object> | null
Who can view. Empty array — everyone who sees the parent folder; omit to keep unchanged. Maximum items 500.
type string Required
Subject type.
userpositiondepartmentteam
id integer Required
User, position, location or team id.
edit array<object> | null
Who can edit. Empty array — inherit editors from the folder; omit to keep unchanged. Maximum items 500.
type string Required
Subject type.
userpositiondepartmentteam
id integer Required
User, position, location or team id.

Responses

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

res = requests.put(
    "https://app.jecheck.io/api/ext/v1/instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/access",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    json={"view":[{"type":"user","id":42}],"edit":[{"type":"user","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('PUT', 'instructions/3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b/access', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'json' => [
        'view' => [
            [
                'type' => 'user',
                'id' => 42,
            ],
        ],
        'edit' => [
            [
                'type' => 'user',
                'id' => 42,
            ],
        ],
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_access_update",
        "arguments": {
            "uuid": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
            "view": [
                {
                    "type": "user",
                    "id": 42
                }
            ],
            "edit": [
                {
                    "type": "user",
                    "id": 42
                }
            ]
        }
    }
}
Response 200
{
  "data": {
    "view": [
      {
        "type": "position",
        "id": 7,
        "name": "Barista"
      },
      {
        "type": "department",
        "id": 12,
        "name": "Abay Ave"
      }
    ],
    "edit": [
      {
        "type": "user",
        "id": 120,
        "name": "Daniyar Omarov"
      }
    ],
    "restricted_by": [],
    "inherited_edit": {
      "folder": null,
      "subjects": []
    }
  }
}

GETList folders

GET /instructions/folders

Folder tree visible to the acting user with document counts (count — directly in the folder, total — with subfolders). Readers see only branches that contain readable documents.

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

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Plan without API access
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl 'https://app.jecheck.io/api/ext/v1/instructions/folders' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/instructions/folders', {
  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/instructions/folders",
    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', 'instructions/folders', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_folders_list",
        "arguments": {}
    }
}
Response 200
{
  "data": [
    {
      "id": 14,
      "parent_id": 3,
      "name": "Barista",
      "icon": "coffee",
      "color": null,
      "count": 6,
      "total": 6,
      "can_edit": false,
      "restricted": false,
      "children": []
    }
  ]
}

POSTCreate a folder

POST /instructions/folders

Creates a folder inside parent_id (requires edit rights on it) or in the root (knowledge-base managers only).

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

Request body

name string Required
Length 1–150.
parent_id integer | null
Parent folder id.
icon string | null
Material Symbols icon name. Maximum length 40.

Responses

StatusDescription
201Created
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X POST 'https://app.jecheck.io/api/ext/v1/instructions/folders' \
  -H 'Authorization: Bearer $JECHECK_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Replace the broken fridge seal",
    "parent_id": 42,
    "icon": "string"
}'
const res = await fetch('https://app.jecheck.io/api/ext/v1/instructions/folders', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "name": "Replace the broken fridge seal",
      "parent_id": 42,
      "icon": "string"
  }),
});
const { data } = await res.json();
import os, requests

res = requests.post(
    "https://app.jecheck.io/api/ext/v1/instructions/folders",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    json={"name":"Replace the broken fridge seal","parent_id":42,"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', 'instructions/folders', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'json' => [
        'name' => 'Replace the broken fridge seal',
        'parent_id' => 42,
        'icon' => 'string',
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_folders_create",
        "arguments": {
            "name": "Replace the broken fridge seal",
            "parent_id": 42,
            "icon": "string"
        }
    }
}
Response 201
{
  "data": {
    "id": 14,
    "parent_id": 3,
    "name": "Barista",
    "icon": "coffee",
    "color": null,
    "count": 6,
    "total": 6,
    "can_edit": false,
    "restricted": false,
    "children": []
  }
}

PATCHUpdate a folder

PATCH /instructions/folders/{id}

Rename, change the icon/colour or move the folder (parent_id; moving requires edit rights on both the old and the new parent).

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

Path parameters

id integer Required
Folder id.

Request body

name string
Length 1–150.
parent_id integer | null
New parent folder id (null — root).
icon string | null
Maximum length 40.
color string | null
Maximum length 20.
ai_visibility string
Visibility for the external AI knowledge base (managers of companies with the AI knowledge base only).
inheritnonestaffclient

Responses

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

res = requests.patch(
    "https://app.jecheck.io/api/ext/v1/instructions/folders/42",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    json={"name":"Replace the broken fridge seal","parent_id":42,"icon":"string","color":"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', 'instructions/folders/42', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'json' => [
        'name' => 'Replace the broken fridge seal',
        'parent_id' => 42,
        'icon' => 'string',
        'color' => 'string',
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_folders_update",
        "arguments": {
            "id": 42,
            "name": "Replace the broken fridge seal",
            "parent_id": 42,
            "icon": "string",
            "color": "string"
        }
    }
}
Response 200
{
  "data": {
    "id": 14,
    "parent_id": 3,
    "name": "Barista",
    "icon": "coffee",
    "color": null,
    "count": 6,
    "total": 6,
    "can_edit": false,
    "restricted": false,
    "children": []
  }
}

DELDelete a folder

DELETE /instructions/folders/{id}

Deletes the folder; its subfolders and documents move one level up and keep the folder's permissions.

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

Path parameters

id integer Required
Folder id.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X DELETE 'https://app.jecheck.io/api/ext/v1/instructions/folders/42' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/instructions/folders/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/instructions/folders/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', 'instructions/folders/42', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_folders_delete",
        "arguments": {
            "id": 42
        }
    }
}
Response 200
{
  "data": {
    "deleted": true
  }
}

GETGet folder permissions

GET /instructions/folders/{id}/access

Who can view and edit the folder (inherited by its documents and subfolders). Requires edit rights on the folder.

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

Path parameters

id integer Required
Folder id.

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Plan without API access
404not_found — The record does not exist or is not visible to the token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl 'https://app.jecheck.io/api/ext/v1/instructions/folders/42/access' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/instructions/folders/42/access', {
  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/instructions/folders/42/access",
    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', 'instructions/folders/42/access', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_folders_access_get",
        "arguments": {
            "id": 42
        }
    }
}
Response 200
{
  "data": {
    "view": [
      {
        "type": "position",
        "id": 7,
        "name": "Barista"
      },
      {
        "type": "department",
        "id": 12,
        "name": "Abay Ave"
      }
    ],
    "edit": [
      {
        "type": "user",
        "id": 120,
        "name": "Daniyar Omarov"
      }
    ],
    "restricted_by": [],
    "inherited_edit": {
      "folder": null,
      "subjects": []
    }
  }
}

PUTSet folder permissions

PUT /instructions/folders/{id}/access

Replaces the view and/or edit lists of the folder. Same subjects and self-protection rules as for documents.

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

Path parameters

id integer Required
Folder id.

Request body

view array<object> | null
Who can view. Empty array — everyone who sees the parent folder; omit to keep unchanged. Maximum items 500.
type string Required
Subject type.
userpositiondepartmentteam
id integer Required
User, position, location or team id.
edit array<object> | null
Who can edit. Empty array — inherit editors from the folder; omit to keep unchanged. Maximum items 500.
type string Required
Subject type.
userpositiondepartmentteam
id integer Required
User, position, location or team id.

Responses

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

res = requests.put(
    "https://app.jecheck.io/api/ext/v1/instructions/folders/42/access",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    json={"view":[{"type":"user","id":42}],"edit":[{"type":"user","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('PUT', 'instructions/folders/42/access', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'json' => [
        'view' => [
            [
                'type' => 'user',
                'id' => 42,
            ],
        ],
        'edit' => [
            [
                'type' => 'user',
                'id' => 42,
            ],
        ],
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "instructions_folders_access_update",
        "arguments": {
            "id": 42,
            "view": [
                {
                    "type": "user",
                    "id": 42
                }
            ],
            "edit": [
                {
                    "type": "user",
                    "id": 42
                }
            ]
        }
    }
}
Response 200
{
  "data": {
    "view": [
      {
        "type": "position",
        "id": 7,
        "name": "Barista"
      },
      {
        "type": "department",
        "id": 12,
        "name": "Abay Ave"
      }
    ],
    "edit": [
      {
        "type": "user",
        "id": 120,
        "name": "Daniyar Omarov"
      }
    ],
    "restricted_by": [],
    "inherited_edit": {
      "folder": null,
      "subjects": []
    }
  }
}