jeCheckDevelopers
Get an API key

Notifications

In-app notifications of the acting user (the bell in the web app and the Notifications screen in the mobile app): list, unread count, mark as read, and personal notification settings. A company key sees the notifications of its service user.

GETList notifications

GET /notifications

Notifications of the acting user, newest first. meta.unread — the number of unread notifications.

Token scoperead
Permission Any employee; results follow the token's visibility
MCP toolnotifications_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.
unread boolean
Only unread notifications.
since date-time
Only notifications created after this moment.

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/notifications?unread=true' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/notifications?unread=true', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
  },
});
const { data, meta } = await res.json();
import os, requests

res = requests.get(
    "https://app.jecheck.io/api/ext/v1/notifications",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    params={"unread":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', 'notifications', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'query' => [
        'unread' => true,
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "notifications_list",
        "arguments": {
            "unread": true
        }
    }
}
Response 200
{
  "data": [
    {
      "id": 88123,
      "title": "New task: Replace the broken fridge seal",
      "body": "Abay Ave · due Nov 10",
      "url": "https://app.jecheck.io/ui/tasks?task=3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b",
      "data": {
        "type": "task",
        "task_id": "3f2b8c1e-7a4d-4e2f-9b1a-6c5d4e3f2a1b"
      },
      "is_read": false,
      "read_at": null,
      "created_at": "2026-11-03T10:24:00+05:00"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 25,
    "total": 1,
    "has_more": false
  }
}

GETCount unread notifications

GET /notifications/unread-count
Token scoperead
Permission Any employee; results follow the token's visibility
MCP toolnotifications_unread_count · 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/notifications/unread-count' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/notifications/unread-count', {
  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/notifications/unread-count",
    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', 'notifications/unread-count', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "notifications_unread_count",
        "arguments": {}
    }
}
Response 200
{
  "data": {
    "unread": 3
  }
}

POSTMark notifications as read

POST /notifications/read

Pass ids to mark specific notifications, or all: true to mark everything as read. Returns the remaining unread count.

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

Request body

ids array<integer>
Notification ids. Maximum items 200.
all boolean
Mark all notifications as read.

Responses

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

res = requests.post(
    "https://app.jecheck.io/api/ext/v1/notifications/read",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    json={"ids":[12,14],"all":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', 'notifications/read', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'json' => [
        'ids' => [
            12,
            14,
        ],
        'all' => true,
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "notifications_read",
        "arguments": {
            "ids": [
                12,
                14
            ],
            "all": true
        }
    }
}
Response 200
{
  "data": {
    "marked": 2,
    "unread": 1
  }
}

GETGet notification settings

GET /notifications/preferences

Personal settings by channel (push, email) and event group: assigned — a task is assigned, comments, updates — status and due-date changes, reminders — due and overdue reminders, digest — daily email digest, brief — morning AI-control brief, urgent — urgent signals during the day. The in-app history is always kept.

Token scoperead
Permission Any employee; results follow the token's visibility
MCP toolnotifications_preferences_get · 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/notifications/preferences' \
  -H 'Authorization: Bearer $JECHECK_TOKEN'
const res = await fetch('https://app.jecheck.io/api/ext/v1/notifications/preferences', {
  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/notifications/preferences",
    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', 'notifications/preferences', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "notifications_preferences_get",
        "arguments": {}
    }
}
Response 200
{
  "data": {
    "push": {
      "assigned": true,
      "comments": true,
      "updates": true,
      "reminders": true,
      "brief": true,
      "urgent": true
    },
    "email": {
      "assigned": true,
      "digest": false,
      "brief": true
    }
  }
}

PATCHUpdate notification settings

PATCH /notifications/preferences

Partial update: pass only the switches to change, e.g. {"email": {"digest": false}}. Unknown keys are ignored.

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

Request body

push object
Push notifications to the mobile app.
assigned boolean
comments boolean
updates boolean
reminders boolean
brief boolean
urgent boolean
email object
Emails (only for users with web-cabinet access).
assigned boolean
digest boolean
brief boolean

Responses

StatusDescription
200OK
401unauthorized — Missing, invalid, revoked or expired token
403forbidden · insufficient_scope · plan_required — Read-only token
422validation_failed — Invalid parameters — see error.fields
429rate_limited — Too many requests — retry after Retry-After seconds
Request
curl -X PATCH 'https://app.jecheck.io/api/ext/v1/notifications/preferences' \
  -H 'Authorization: Bearer $JECHECK_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "push": {
        "assigned": true,
        "comments": true,
        "updates": true
    },
    "email": {
        "assigned": true,
        "digest": true,
        "brief": true
    }
}'
const res = await fetch('https://app.jecheck.io/api/ext/v1/notifications/preferences', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.JECHECK_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
      "push": {
          "assigned": true,
          "comments": true,
          "updates": true
      },
      "email": {
          "assigned": true,
          "digest": true,
          "brief": true
      }
  }),
});
const { data } = await res.json();
import os, requests

res = requests.patch(
    "https://app.jecheck.io/api/ext/v1/notifications/preferences",
    headers={"Authorization": f"Bearer {os.environ['JECHECK_TOKEN']}"},
    json={"push":{"assigned":True,"comments":True,"updates":True},"email":{"assigned":True,"digest":True,"brief":True}},
)
res.raise_for_status()
data = res.json()["data"]
$client = new GuzzleHttp\Client(['base_uri' => 'https://app.jecheck.io/api/ext/v1/']);

$res = $client->request('PATCH', 'notifications/preferences', [
    'headers' => ['Authorization' => 'Bearer ' . getenv('JECHECK_TOKEN')],
    'json' => [
        'push' => [
            'assigned' => true,
            'comments' => true,
            'updates' => true,
        ],
        'email' => [
            'assigned' => true,
            'digest' => true,
            'brief' => true,
        ],
    ],
]);
$data = json_decode($res->getBody(), true)['data'];
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "notifications_preferences_update",
        "arguments": {
            "push": {
                "assigned": true,
                "comments": true,
                "updates": true
            },
            "email": {
                "assigned": true,
                "digest": true,
                "brief": true
            }
        }
    }
}
Response 200
{
  "data": {
    "push": {
      "assigned": true,
      "comments": true,
      "updates": true,
      "reminders": true,
      "brief": true,
      "urgent": true
    },
    "email": {
      "assigned": true,
      "digest": false,
      "brief": true
    }
  }
}