Notsku
APISign in
Notsku API
Send 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).
Authentication
Create 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 notification
Look 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 person
GET /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 team
GET /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 board
POST /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 board
1. 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.
MCP
One 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 URL
MCP URL
https://api.notsku.com/functions/v1/mcp
Send 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.
Cursor config
{ "mcpServers": { "joinboard": { "url": "https://api.notsku.com/functions/v1/mcp", "headers": { "Authorization": "Bearer jb_user_YOUR_KEY" } } } }
Member tools (jb_user_…)
list_inbox
List your messages. recipient_id is the message id. open_only true shows only items that still need a reply.
Example
{ "open_only": true }
get_message
Read 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_message
Reply 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_boards
List boards you have joined, with your role and per-board notification settings.
Example
{}
update_notification_settings
Set 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_board
Leave a board. Owners cannot leave until they transfer ownership.
Example
{ "board_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee" }
Organization tools (jb_live_…)
list_boards
List the board this organization API key can access.
Example
{}
get_board
Get one board’s metadata. Does not include people or teams.
Example
{ "board_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee" }
list_teams
List 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_people
List 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_notification
Send 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_session
Start 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_code
Exchange the one-time code from the connect redirect for a membership id.
Example
{ "code": "…" }
Endpoints
GET
/v1/boards
Scope: read
List 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.
cURL
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}
Scope: read
Get 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.
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}/teams
Scope: read
List teams on the board.
Use a team’s id as audience.team_id when sending to that team.
cURL
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}/people
Scope: read
List 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.
cURL
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}/notifications
Scope: send
Send 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.
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"] } }'
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-sessions
Scope: join
Start 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.
cURL
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/exchange
Scope: join
Exchange 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.
cURL
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" }
Errors look like { "error": { "code": "unauthorized", "message": "…" } } with HTTP 401, 403, 404, 422, or 429.
Notsku
Important messages. Clear answers.
API docs