Notsku APISend notifications to everyone, a team, or one person. GET /v1/boards/{boardId} returns the board only. People are GET /v1/boards/{boardId}/people. Notifications arrive in Notsku (inbox and push).
AuthenticationCreate an org-scoped key in Manage → API. Send it as Authorization: Bearer jb_live_YOUR_KEY. Keys never go in a user’s browser.
Base URL
https://api.notsku.com/functions/v1/public-api
How to send a notificationLook up ids first, then POST /notifications. For one person, audience.type is "people" and people_ids is an array with that membership id.
Send a notification to one personGET /v1/boards — copy board id.GET /v1/boards/{boardId}/people — copy that person’s id. This is a membership id, not their email and not their auth user id.POST /v1/boards/{boardId}/notifications with audience.type "people" and people_ids: ["that-membership-id"]. One person is an array of one id.
cURL
curl -X POST https://api.notsku.com/functions/v1/public-api/v1/boards/{boardId}/notifications \
-H "Authorization: Bearer jb_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Your shift starts at 16:00",
"body": "Please open Notsku and confirm.",
"urgency": "important",
"audience": {
"type": "people",
"people_ids": ["11111111-2222-3333-4444-555555555555"]
}
}'Send a notification to one teamGET /v1/boards/{boardId}/teams — copy the team’s id.POST /v1/boards/{boardId}/notifications with audience.type "team" and team_id.
cURL
curl -X POST https://api.notsku.com/functions/v1/public-api/v1/boards/{boardId}/notifications \
-H "Authorization: Bearer jb_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Kitchen prep list",
"body": "Check the cooler before open.",
"urgency": "normal",
"audience": {
"type": "team",
"team_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
}
}'Send a notification to everyone on the boardPOST /v1/boards/{boardId}/notifications with audience.type "all". No people_ids or team_id.
cURL
curl -X POST https://api.notsku.com/functions/v1/public-api/v1/boards/{boardId}/notifications \
-H "Authorization: Bearer jb_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Office closed Friday",
"body": "The office is closed on Friday.",
"urgency": "normal",
"audience": { "type": "all" }
}'Connect a user to a board1. Your server creates a connect session with the API key.2. Redirect the user to connect_url. They sign in on Notsku and confirm.3. Notsku redirects back with a one-time code. Your server exchanges it for membership_id. Use that id later in people_ids.
MCPOne MCP server, two kinds of keys. Personal keys (Profile) read and reply to your inbox, manage where you are joined, and change notification settings. Organization keys (Manage → API) expose the same operations as this REST API.
MCP URLSend the key as Authorization: Bearer jb_user_… or jb_live_…. On hosted Supabase, if the gateway requires the publishable key in Authorization, put the Notsku key in X-Joinboard-Key instead.
Member tools (jb_user_…)MCP URL
https://api.notsku.com/functions/v1/mcp
Cursor config
{
"mcpServers": {
"joinboard": {
"url": "https://api.notsku.com/functions/v1/mcp",
"headers": {
"Authorization": "Bearer jb_user_YOUR_KEY"
}
}
}
}list_inboxList your messages. recipient_id is the message id. open_only true shows only items that still need a reply.
Example
{
"open_only": true
}get_messageRead one message (title, body, questions) and mark it viewed. Use recipient_id from list_inbox.
Example
{
"recipient_id": "11111111-2222-3333-4444-555555555555"
}reply_to_messageReply to a message. For one question, pass answer (yes/no, an option, or text). For several, pass answers. Acknowledgements use yes.
Example
{
"recipient_id": "11111111-2222-3333-4444-555555555555",
"answer": "yes"
}list_my_boardsList boards you have joined, with your role and per-board notification settings.
Example
{}update_notification_settingsSet which urgencies you receive on one board. board_id is the organization id from list_my_boards.
Example
{
"board_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
"notify_normal": true,
"notify_important": true,
"notify_urgent": true
}leave_boardLeave a board. Owners cannot leave until they transfer ownership.
Organization tools (jb_live_…)Example
{
"board_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee"
}list_boardsList the board this organization API key can access.
Example
{}get_boardGet one board’s metadata. Does not include people or teams.
Example
{
"board_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee"
}list_teamsList teams on a board. Use a team id as team_id when sending to that team.
Example
{
"board_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee"
}list_peopleList people on a board. Each id is a membership id for send_notification people_ids. Optional state defaults to active; use all for invited or pending.
Example
{
"board_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
"state": "active"
}send_notificationSend a notification to everyone, one team, or specific people. Recipients get it in the Notsku inbox and as a push notification. people_ids are membership ids from list_people.
Example
{
"board_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
"title": "Your shift starts at 16:00",
"body": "Please open Notsku and confirm.",
"urgency": "important",
"audience_type": "people",
"people_ids": ["11111111-2222-3333-4444-555555555555"]
}create_connect_sessionStart a member connect flow. return_url must be allowlisted on the API key.
Example
{
"board_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
"return_url": "https://partner.example/joinboard/callback",
"state": "csrf-token"
}exchange_connect_codeExchange the one-time code from the connect redirect for a membership id.
Example
{
"code": "…"
}EndpointsScope: readList the board this API key can access.Returns metadata only (id, name, slug, description). It does not include people. Use GET /v1/boards/{boardId}/people next.Scope: readGet one board’s metadata. Returns 404 if the id is not this key’s board.Does not include people or teams. Those are separate URLs under this board id.Scope: readList teams on the board.Use a team’s id as audience.team_id when sending to that team.Scope: readList people on the board.Each row’s id is the membership id. Use that id in POST /notifications audience.people_ids. Do not send email or user_id. Default filter is ?state=active. Use ?state=all to include invited or pending people.Scope: sendSend a notification. Recipients get it in the Notsku inbox and as a push notification.audience.type must be all, team, or people. For one person, type is still "people" with a one-element people_ids array. people_ids values come from GET /people (membership id). Optional Idempotency-Key header retries the same send safely.Scope: joinStart a member connect flow. Redirect the user to connect_url. return_url must be allowlisted on the key.Call this from your server. Never put the API key in the user’s browser.Scope: joinExchange the one-time code from the redirect for the membership id.membership_id in the response is the same id you later pass in people_ids when sending a notification to that person.Errors look like { "error": { "code": "unauthorized", "message": "…" } } with HTTP 401, 403, 404, 422, or 429.
GET
/v1/boardscURL
curl https://api.notsku.com/functions/v1/public-api/v1/boards \ -H "Authorization: Bearer jb_live_YOUR_KEY"
Response
{
"data": [{ "id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee", "name": "Helsinki Store", "slug": "helsinki-store", "description": "Staff board" }]
}GET
/v1/boards/{boardId}cURL
curl https://api.notsku.com/functions/v1/public-api/v1/boards/{boardId} \
-H "Authorization: Bearer jb_live_YOUR_KEY"Response
{
"id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
"name": "Helsinki Store",
"slug": "helsinki-store",
"description": "Staff board"
}GET
/v1/boards/{boardId}/teamscURL
curl https://api.notsku.com/functions/v1/public-api/v1/boards/{boardId}/teams \
-H "Authorization: Bearer jb_live_YOUR_KEY"Response
{
"data": [{ "id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", "name": "Kitchen", "member_count": 4 }]
}GET
/v1/boards/{boardId}/peoplecURL
curl https://api.notsku.com/functions/v1/public-api/v1/boards/{boardId}/people \
-H "Authorization: Bearer jb_live_YOUR_KEY"Response
{
"data": [{
"id": "11111111-2222-3333-4444-555555555555",
"display_name": "Alex",
"email": "alex@example.com",
"role": "member",
"state": "active",
"team_ids": []
}]
}POST
/v1/boards/{boardId}/notificationscURL
curl -X POST https://api.notsku.com/functions/v1/public-api/v1/boards/{boardId}/notifications \
-H "Authorization: Bearer jb_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Your shift starts at 16:00",
"body": "Please open Notsku and confirm.",
"urgency": "important",
"audience": {
"type": "people",
"people_ids": ["11111111-2222-3333-4444-555555555555"]
}
}'One person
{
"title": "Your shift starts at 16:00",
"body": "Please open Notsku and confirm.",
"urgency": "important",
"audience": {
"type": "people",
"people_ids": ["11111111-2222-3333-4444-555555555555"]
}
}Several people
{
"title": "Cover needed tonight",
"body": "Can you take 16:00–22:00?",
"audience": {
"type": "people",
"people_ids": [
"11111111-2222-3333-4444-555555555555",
"bbbbbbbb-cccc-dddd-eeee-ffffffffffff"
]
}
}One team
{
"title": "Kitchen prep list",
"body": "Check the cooler before open.",
"audience": {
"type": "team",
"team_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
}
}Everyone on the board
{
"title": "Office closed Friday",
"body": "The office is closed on Friday.",
"audience": { "type": "all" }
}Response
{
"id": "content-item-uuid",
"campaign_id": "campaign-uuid",
"recipient_count": 1,
"audience": {
"type": "people",
"people_ids": ["11111111-2222-3333-4444-555555555555"]
}
}POST
/v1/boards/{boardId}/connect-sessionscURL
curl -X POST https://api.notsku.com/functions/v1/public-api/v1/boards/{boardId}/connect-sessions \
-H "Authorization: Bearer jb_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"return_url": "https://partner.example/joinboard/callback",
"state": "csrf-token"
}'Body
{
"return_url": "https://partner.example/joinboard/callback",
"state": "csrf-token"
}Response
{
"connect_url": "https://app.example/connect/…",
"token": "…",
"expires_at": "2026-09-06T12:00:00Z",
"state": "csrf-token"
}POST
/v1/connect/exchangecURL
curl -X POST https://api.notsku.com/functions/v1/public-api/v1/connect/exchange \
-H "Authorization: Bearer jb_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "code": "…" }'Body
{ "code": "…" }Response
{
"board_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
"membership_id": "11111111-2222-3333-4444-555555555555",
"status": "joined"
}