Notify people
notifications.notification.send
POST/api/v1/households/{household_id}/commands/notifications.notification.send
- Command
- Rigel runs it
- Applies offline
Records one notification for each listed person who has an account, so they see it in Rigel and get a push on their devices. Leaves out the person making the request (unless include_self) and anyone who muted the app, and says who was left out and why. The title is the only text sent to a lock screen, so write it as who and where ("Ada in Summer trip"), never the private detail; the body (up to 500 characters) is shown only inside the app. Give deliver_at in the future for a reminder. Fails with person_not_found if a listed person doesn't exist, and invalid_time_range if expires_at is before deliver_at.
Parameters#
| Field | Description |
|---|---|
household_idpathstringrequired | The household's ID. |
Idempotency-Keyheaderstringoptional | The command's ID. Reuse it when retrying the same command. |
Request body#
JSON, as application/json.
| Field | Description |
|---|---|
person_idsarray of stringsrequired | The people to notify, 1–50. |
titlestringrequired | What the notification says on a lock screen, 1–120 characters. Never the private detail. |
bodystring or nulloptional | More detail, shown only inside the app, up to 500 characters. |
appone of: meals, recipes, shopping, inventory, calendar, email, tasks, documents, chat, maintenance, null or nulloptional | The app it comes from, so people can mute it; null or left out for none. |
kindstringoptional | What kind of notification it is, snake_case, 1–40 characters, such as mention, assigned or reminder. Defaults to message. |
record_idstring or nulloptional | The record it is about; opening the notification opens it. |
topic_idstring or nulloptional | The larger thing it belongs to, such as the conversation; notifications with the same topic replace each other. |
deliver_atstring (date-time)optional | When to deliver it, for a reminder. Left out or in the past means now. |
expires_atstring (date-time)optional | After this a push is no longer sent. Defaults to a day after deliver_at. |
include_selfbooleanoptional | Also notify the person making the request. Defaults to false. |
Response#
200 The command was applied.
| Field | Description |
|---|---|
resultobjectrequired | What the command returned, such as the IDs it created. |
result.notifiedarray of objectsrequired | Who was notified, in the order given. |
result.notified[].person_idstringrequired | A person ID, such as per_01JC0000000000000000000000. |
result.notified[].notification_idstringrequired | The notification recorded for them. |
result.skippedarray of objectsrequired | Who was left out and why. |
result.skipped[].person_idstringrequired | A person ID, such as per_01JC0000000000000000000000. |
result.skipped[].reasonone of: not_found, no_account, self, mutedrequired | Why nothing was recorded: they don't exist, they have no account, they made the change themselves, or they muted the app. |
versionintegerrequired | The household version after the command. |
Errors#
Every error has the same envelope: error.code, error.message, error.details, error.recovery and error.request_id.
| Status | Code | When |
|---|---|---|
400 | validation_failed | A field is missing, misspelled or out of range. details.fields lists each problem. |
401 | unauthenticated | The request has no valid session. |
404 | person_not_found | A person who isn't in the household is refused, and nobody is notified. |
404 | not_found | The household doesn't exist, or you aren't a member of it. |
409 | invalid_time_range |
|
409 | idempotency_key_reused | The Idempotency-Key was already used for a different command. |
Examples#
These are real. Each scenario is one of the command's test cases, run on a household when this site was built, and the response is what the API returned.
Notifies each person with an account once, in order, leaving out me and people without accounts
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send' \
-H "Cookie: rigel_session=$RIGEL_SESSION" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
-d '{
"person_ids": [
"per_01JC000000000000000000000B",
"per_01JC000000000000000000000A",
"per_01JC000000000000000000000C",
"per_01JC000000000000000000000B"
],
"title": "Ada in Summer trip"
}'const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
},
body: JSON.stringify({
person_ids: [
"per_01JC000000000000000000000B",
"per_01JC000000000000000000000A",
"per_01JC000000000000000000000C",
"per_01JC000000000000000000000B",
],
title: "Ada in Summer trip",
}),
});
const data = await response.json();POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA
{
"person_ids": [
"per_01JC000000000000000000000B",
"per_01JC000000000000000000000A",
"per_01JC000000000000000000000C",
"per_01JC000000000000000000000B"
],
"title": "Ada in Summer trip"
}HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0P7W62VBMKF5Q1W6X
{
"result": {
"notified": [
{
"person_id": "per_01JC000000000000000000000B",
"notification_id": "ntf_01JC4N0000MBGE5RJ6Q7V6V6T8"
}
],
"skipped": [
{
"person_id": "per_01JC000000000000000000000A",
"reason": "self"
},
{
"person_id": "per_01JC000000000000000000000C",
"reason": "no_account"
}
]
},
"version": 1
}Include_self notifies me too, with IDs in recipient order
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send' \
-H "Cookie: rigel_session=$RIGEL_SESSION" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
-d '{
"person_ids": [
"per_01JC000000000000000000000A",
"per_01JC000000000000000000000B"
],
"title": "Ada in Summer trip",
"include_self": true,
"kind": "mention",
"app": "tasks",
"body": "Take a look",
"record_id": "per_01JC000000000000000000000A",
"topic_id": "fnt_01JC000000000000000000000A"
}'const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
},
body: JSON.stringify({
person_ids: [
"per_01JC000000000000000000000A",
"per_01JC000000000000000000000B",
],
title: "Ada in Summer trip",
include_self: true,
kind: "mention",
app: "tasks",
body: "Take a look",
record_id: "per_01JC000000000000000000000A",
topic_id: "fnt_01JC000000000000000000000A",
}),
});
const data = await response.json();POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA
{
"person_ids": [
"per_01JC000000000000000000000A",
"per_01JC000000000000000000000B"
],
"title": "Ada in Summer trip",
"include_self": true,
"kind": "mention",
"app": "tasks",
"body": "Take a look",
"record_id": "per_01JC000000000000000000000A",
"topic_id": "fnt_01JC000000000000000000000A"
}HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R046SDJPTZCS5R5X01
{
"result": {
"notified": [
{
"person_id": "per_01JC000000000000000000000A",
"notification_id": "ntf_01JC4N0000MBGE5RJ6Q7V6V6T8"
},
{
"person_id": "per_01JC000000000000000000000B",
"notification_id": "ntf_01JC4N0000VGW1STJ6TGXRB7FY"
}
],
"skipped": []
},
"version": 1
}A person who muted the app is skipped, and a skipped person uses no ID
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send' \
-H "Cookie: rigel_session=$RIGEL_SESSION" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
-d '{
"person_ids": [
"per_01JC000000000000000000000B",
"per_01JC000000000000000000000C",
"per_01JC000000000000000000000A"
],
"title": "Ada in Summer trip",
"app": "tasks",
"include_self": true
}'const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
},
body: JSON.stringify({
person_ids: [
"per_01JC000000000000000000000B",
"per_01JC000000000000000000000C",
"per_01JC000000000000000000000A",
],
title: "Ada in Summer trip",
app: "tasks",
include_self: true,
}),
});
const data = await response.json();POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA
{
"person_ids": [
"per_01JC000000000000000000000B",
"per_01JC000000000000000000000C",
"per_01JC000000000000000000000A"
],
"title": "Ada in Summer trip",
"app": "tasks",
"include_self": true
}HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0WJ5TMP70DB4DE9YK
{
"result": {
"notified": [
{
"person_id": "per_01JC000000000000000000000A",
"notification_id": "ntf_01JC4N0000MBGE5RJ6Q7V6V6T8"
}
],
"skipped": [
{
"person_id": "per_01JC000000000000000000000B",
"reason": "muted"
},
{
"person_id": "per_01JC000000000000000000000C",
"reason": "no_account"
}
]
},
"version": 1
}Muting another app doesn't matter, and a notification from no app can't be muted
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send' \
-H "Cookie: rigel_session=$RIGEL_SESSION" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
-d '{
"person_ids": [
"per_01JC000000000000000000000B"
],
"title": "Ada in Summer trip",
"app": "calendar"
}'const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
},
body: JSON.stringify({
person_ids: [
"per_01JC000000000000000000000B",
],
title: "Ada in Summer trip",
app: "calendar",
}),
});
const data = await response.json();POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA
{
"person_ids": [
"per_01JC000000000000000000000B"
],
"title": "Ada in Summer trip",
"app": "calendar"
}HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0WKP81WDYB9HWX77R
{
"result": {
"notified": [
{
"person_id": "per_01JC000000000000000000000B",
"notification_id": "ntf_01JC4N0000MBGE5RJ6Q7V6V6T8"
}
],
"skipped": []
},
"version": 1
}A mute that ends after the notification is due still applies
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send' \
-H "Cookie: rigel_session=$RIGEL_SESSION" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
-d '{
"person_ids": [
"per_01JC000000000000000000000B"
],
"title": "Ada in Summer trip",
"app": "chat",
"deliver_at": "2025-11-06T19:20:02Z"
}'const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
},
body: JSON.stringify({
person_ids: [
"per_01JC000000000000000000000B",
],
title: "Ada in Summer trip",
app: "chat",
deliver_at: "2025-11-06T19:20:02Z",
}),
});
const data = await response.json();POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA
{
"person_ids": [
"per_01JC000000000000000000000B"
],
"title": "Ada in Summer trip",
"app": "chat",
"deliver_at": "2025-11-06T19:20:02Z"
}HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0P357H5KCRM8HJYDY
{
"result": {
"notified": [],
"skipped": [
{
"person_id": "per_01JC000000000000000000000B",
"reason": "muted"
}
]
},
"version": 1
}A mute that ends exactly when the notification is due is over
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send' \
-H "Cookie: rigel_session=$RIGEL_SESSION" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
-d '{
"person_ids": [
"per_01JC000000000000000000000B"
],
"title": "Ada in Summer trip",
"app": "chat",
"deliver_at": "2025-11-06T19:20:02Z"
}'const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
},
body: JSON.stringify({
person_ids: [
"per_01JC000000000000000000000B",
],
title: "Ada in Summer trip",
app: "chat",
deliver_at: "2025-11-06T19:20:02Z",
}),
});
const data = await response.json();POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA
{
"person_ids": [
"per_01JC000000000000000000000B"
],
"title": "Ada in Summer trip",
"app": "chat",
"deliver_at": "2025-11-06T19:20:02Z"
}HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0H7GTCHNJX26A5RCE
{
"result": {
"notified": [
{
"person_id": "per_01JC000000000000000000000B",
"notification_id": "ntf_01JC4N0000MBGE5RJ6Q7V6V6T8"
}
],
"skipped": []
},
"version": 1
}A mute that has already ended doesn't stop a notification
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send' \
-H "Cookie: rigel_session=$RIGEL_SESSION" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
-d '{
"person_ids": [
"per_01JC000000000000000000000B"
],
"title": "Ada in Summer trip",
"app": "chat"
}'const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
},
body: JSON.stringify({
person_ids: [
"per_01JC000000000000000000000B",
],
title: "Ada in Summer trip",
app: "chat",
}),
});
const data = await response.json();POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA
{
"person_ids": [
"per_01JC000000000000000000000B"
],
"title": "Ada in Summer trip",
"app": "chat"
}HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0J1FWXB243VXNF8CG
{
"result": {
"notified": [
{
"person_id": "per_01JC000000000000000000000B",
"notification_id": "ntf_01JC4N0000MBGE5RJ6Q7V6V6T8"
}
],
"skipped": []
},
"version": 1
}A deliver_at in the past means now
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send' \
-H "Cookie: rigel_session=$RIGEL_SESSION" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
-d '{
"person_ids": [
"per_01JC000000000000000000000B"
],
"title": "Ada in Summer trip",
"deliver_at": "2025-11-06T18:20:00Z"
}'const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
},
body: JSON.stringify({
person_ids: [
"per_01JC000000000000000000000B",
],
title: "Ada in Summer trip",
deliver_at: "2025-11-06T18:20:00Z",
}),
});
const data = await response.json();POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA
{
"person_ids": [
"per_01JC000000000000000000000B"
],
"title": "Ada in Summer trip",
"deliver_at": "2025-11-06T18:20:00Z"
}HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0GTG4D3R19AM3FDFS
{
"result": {
"notified": [
{
"person_id": "per_01JC000000000000000000000B",
"notification_id": "ntf_01JC4N0000MBGE5RJ6Q7V6V6T8"
}
],
"skipped": []
},
"version": 1
}A reminder keeps its later deliver_at and its own expiry
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send' \
-H "Cookie: rigel_session=$RIGEL_SESSION" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
-d '{
"person_ids": [
"per_01JC000000000000000000000B"
],
"title": "Ada in Summer trip",
"kind": "reminder",
"deliver_at": "2025-11-06T19:50:00Z",
"expires_at": "2025-11-06T20:20:00Z"
}'const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
},
body: JSON.stringify({
person_ids: [
"per_01JC000000000000000000000B",
],
title: "Ada in Summer trip",
kind: "reminder",
deliver_at: "2025-11-06T19:50:00Z",
expires_at: "2025-11-06T20:20:00Z",
}),
});
const data = await response.json();POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA
{
"person_ids": [
"per_01JC000000000000000000000B"
],
"title": "Ada in Summer trip",
"kind": "reminder",
"deliver_at": "2025-11-06T19:50:00Z",
"expires_at": "2025-11-06T20:20:00Z"
}HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R054V1QX4T1AVH01BV
{
"result": {
"notified": [
{
"person_id": "per_01JC000000000000000000000B",
"notification_id": "ntf_01JC4N0000MBGE5RJ6Q7V6V6T8"
}
],
"skipped": []
},
"version": 1
}Expiring exactly when it's due is allowed
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send' \
-H "Cookie: rigel_session=$RIGEL_SESSION" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
-d '{
"person_ids": [
"per_01JC000000000000000000000B"
],
"title": "Ada in Summer trip",
"deliver_at": "2025-11-06T19:20:01Z",
"expires_at": "2025-11-06T19:20:01Z"
}'const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
},
body: JSON.stringify({
person_ids: [
"per_01JC000000000000000000000B",
],
title: "Ada in Summer trip",
deliver_at: "2025-11-06T19:20:01Z",
expires_at: "2025-11-06T19:20:01Z",
}),
});
const data = await response.json();POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA
{
"person_ids": [
"per_01JC000000000000000000000B"
],
"title": "Ada in Summer trip",
"deliver_at": "2025-11-06T19:20:01Z",
"expires_at": "2025-11-06T19:20:01Z"
}HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R06NAS0RQQA154VAR1
{
"result": {
"notified": [
{
"person_id": "per_01JC000000000000000000000B",
"notification_id": "ntf_01JC4N0000MBGE5RJ6Q7V6V6T8"
}
],
"skipped": []
},
"version": 1
}A title of 120 characters and a body of 500 are the longest allowed
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send' \
-H "Cookie: rigel_session=$RIGEL_SESSION" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
-d '{
"person_ids": [
"per_01JC000000000000000000000B"
],
"title": "tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt",
"body": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
}'const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
},
body: JSON.stringify({
person_ids: [
"per_01JC000000000000000000000B",
],
title: "tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt",
body: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
}),
});
const data = await response.json();POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA
{
"person_ids": [
"per_01JC000000000000000000000B"
],
"title": "tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt",
"body": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
}HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0ATXJC7F0FA23QK41
{
"result": {
"notified": [
{
"person_id": "per_01JC000000000000000000000B",
"notification_id": "ntf_01JC4N0000MBGE5RJ6Q7V6V6T8"
}
],
"skipped": []
},
"version": 1
}Expiring before it's due is refused
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send' \
-H "Cookie: rigel_session=$RIGEL_SESSION" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
-d '{
"person_ids": [
"per_01JC000000000000000000000B"
],
"title": "Ada in Summer trip",
"deliver_at": "2025-11-06T19:20:02Z",
"expires_at": "2025-11-06T19:20:01.999Z"
}'const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
},
body: JSON.stringify({
person_ids: [
"per_01JC000000000000000000000B",
],
title: "Ada in Summer trip",
deliver_at: "2025-11-06T19:20:02Z",
expires_at: "2025-11-06T19:20:01.999Z",
}),
});
const data = await response.json();POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA
{
"person_ids": [
"per_01JC000000000000000000000B"
],
"title": "Ada in Summer trip",
"deliver_at": "2025-11-06T19:20:02Z",
"expires_at": "2025-11-06T19:20:01.999Z"
}HTTP/1.1 409 Conflict
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0D2NHGHXN6TPWGPY9
{
"error": {
"code": "invalid_time_range",
"message": "A notification can't expire before it is due. No changes were applied.",
"details": {
"deliver_at": 1762456802000,
"expires_at": 1762456801999
},
"recovery": "Read the current state, then send a command that fits it.",
"request_id": "req_01K9D9S2R0D2NHGHXN6TPWGPY9"
}
}An expiry in the past, with no deliver_at, is refused
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send' \
-H "Cookie: rigel_session=$RIGEL_SESSION" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
-d '{
"person_ids": [
"per_01JC000000000000000000000B"
],
"title": "Ada in Summer trip",
"expires_at": "2025-11-06T19:19:59Z"
}'const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
},
body: JSON.stringify({
person_ids: [
"per_01JC000000000000000000000B",
],
title: "Ada in Summer trip",
expires_at: "2025-11-06T19:19:59Z",
}),
});
const data = await response.json();POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA
{
"person_ids": [
"per_01JC000000000000000000000B"
],
"title": "Ada in Summer trip",
"expires_at": "2025-11-06T19:19:59Z"
}HTTP/1.1 409 Conflict
Content-Type: application/json
X-Request-Id: req_01K9D9S2R09A4WZHDC8CJ5S62E
{
"error": {
"code": "invalid_time_range",
"message": "A notification can't expire before it is due. No changes were applied.",
"details": {
"deliver_at": 1762456800000,
"expires_at": 1762456799000
},
"recovery": "Read the current state, then send a command that fits it.",
"request_id": "req_01K9D9S2R09A4WZHDC8CJ5S62E"
}
}A person who isn't in the household is refused, and nobody is notified
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send' \
-H "Cookie: rigel_session=$RIGEL_SESSION" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
-d '{
"person_ids": [
"per_01JC000000000000000000000B",
"per_01JC000000000000000000000D"
],
"title": "Ada in Summer trip"
}'const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
},
body: JSON.stringify({
person_ids: [
"per_01JC000000000000000000000B",
"per_01JC000000000000000000000D",
],
title: "Ada in Summer trip",
}),
});
const data = await response.json();POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/notifications.notification.send HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA
{
"person_ids": [
"per_01JC000000000000000000000B",
"per_01JC000000000000000000000D"
],
"title": "Ada in Summer trip"
}HTTP/1.1 404 Not Found
Content-Type: application/json
X-Request-Id: req_01K9D9S2R07Z7V3KA6SA5JHV91
{
"error": {
"code": "person_not_found",
"message": "One of those people isn't in the household. No changes were applied.",
"details": {
"person_id": "per_01JC000000000000000000000D"
},
"recovery": "Read the current state, then send a command that fits it.",
"request_id": "req_01K9D9S2R07Z7V3KA6SA5JHV91"
}
}Notify someone
The title is all a lock screen shows, so keep the private detail in body. include_self lets you notify yourself; otherwise the person making the request is left out.
curl -X POST 'https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/notifications.notification.send' \
-H "Cookie: rigel_session=$RIGEL_SESSION" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: cmd_01M6V9CSSJAEX21YR7KGMBMWCT' \
-d '{
"person_ids": [
"per_01M6V9CS6RX26JK5KVYGRN22D2"
],
"title": "Pick up Theo from soccer",
"body": "Tuesday at 5:00 pm, Riverside Park. Ben is going.",
"app": "calendar",
"kind": "reminder",
"record_id": "evt_01M6V9CSHPG77MMGGKHAEJQ484",
"include_self": true
}'const response = await fetch("https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/notifications.notification.send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Idempotency-Key": "cmd_01M6V9CSSJAEX21YR7KGMBMWCT",
Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
},
body: JSON.stringify({
person_ids: [
"per_01M6V9CS6RX26JK5KVYGRN22D2",
],
title: "Pick up Theo from soccer",
body: "Tuesday at 5:00 pm, Riverside Park. Ben is going.",
app: "calendar",
kind: "reminder",
record_id: "evt_01M6V9CSHPG77MMGGKHAEJQ484",
include_self: true,
}),
});
const data = await response.json();POST /api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/notifications.notification.send HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01M6V9CSSJAEX21YR7KGMBMWCT
{
"person_ids": [
"per_01M6V9CS6RX26JK5KVYGRN22D2"
],
"title": "Pick up Theo from soccer",
"body": "Tuesday at 5:00 pm, Riverside Park. Ben is going.",
"app": "calendar",
"kind": "reminder",
"record_id": "evt_01M6V9CSHPG77MMGGKHAEJQ484",
"include_self": true
}HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01M6V9CSSJD0F61Q1GR1B56AQ8
{
"result": {
"notified": [
{
"person_id": "per_01M6V9CS6RX26JK5KVYGRN22D2",
"notification_id": "ntf_01M6V9CSSJ74CDDFEP3N4T0X8P"
}
],
"skipped": []
},
"version": 153
}Notify people who can't all be notified
Ben and Nia have no account to notify, so skipped says why.
curl -X POST 'https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/notifications.notification.send' \
-H "Cookie: rigel_session=$RIGEL_SESSION" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: cmd_01M6V9CSSMY39SHM2Q0YFHS1Z2' \
-d '{
"person_ids": [
"per_01M6V9CS6RX26JK5KVYGRN22D2",
"per_01M6V9CS744BQQH188FS6CXY9W",
"per_01M6V9CS79TMYHDAM7FTA9ZK3Z"
],
"title": "Dinner is at 6:00 pm",
"app": "meals",
"topic_id": "mel_01M6V9CSFSFH4859KG4NM47HF2",
"include_self": true
}'const response = await fetch("https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/notifications.notification.send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Idempotency-Key": "cmd_01M6V9CSSMY39SHM2Q0YFHS1Z2",
Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
},
body: JSON.stringify({
person_ids: [
"per_01M6V9CS6RX26JK5KVYGRN22D2",
"per_01M6V9CS744BQQH188FS6CXY9W",
"per_01M6V9CS79TMYHDAM7FTA9ZK3Z",
],
title: "Dinner is at 6:00 pm",
app: "meals",
topic_id: "mel_01M6V9CSFSFH4859KG4NM47HF2",
include_self: true,
}),
});
const data = await response.json();POST /api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/notifications.notification.send HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01M6V9CSSMY39SHM2Q0YFHS1Z2
{
"person_ids": [
"per_01M6V9CS6RX26JK5KVYGRN22D2",
"per_01M6V9CS744BQQH188FS6CXY9W",
"per_01M6V9CS79TMYHDAM7FTA9ZK3Z"
],
"title": "Dinner is at 6:00 pm",
"app": "meals",
"topic_id": "mel_01M6V9CSFSFH4859KG4NM47HF2",
"include_self": true
}HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01M6V9CSSMYAMP390QBFJCA1T5
{
"result": {
"notified": [
{
"person_id": "per_01M6V9CS6RX26JK5KVYGRN22D2",
"notification_id": "ntf_01M6V9CSSMTA415FM404N9HKYH"
}
],
"skipped": [
{
"person_id": "per_01M6V9CS744BQQH188FS6CXY9W",
"reason": "no_account"
},
{
"person_id": "per_01M6V9CS79TMYHDAM7FTA9ZK3Z",
"reason": "no_account"
}
]
},
"version": 154
}Notify yourself without include_self
The person making the request is left out unless include_self is true, and the reason is self.
curl -X POST 'https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/notifications.notification.send' \
-H "Cookie: rigel_session=$RIGEL_SESSION" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: cmd_01M6V9CSSRC59RWK6YZPYRR53H' \
-d '{
"person_ids": [
"per_01M6V9CS6RX26JK5KVYGRN22D2"
],
"title": "Dinner is at 6:00 pm",
"app": "meals"
}'const response = await fetch("https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/notifications.notification.send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Idempotency-Key": "cmd_01M6V9CSSRC59RWK6YZPYRR53H",
Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
},
body: JSON.stringify({
person_ids: [
"per_01M6V9CS6RX26JK5KVYGRN22D2",
],
title: "Dinner is at 6:00 pm",
app: "meals",
}),
});
const data = await response.json();POST /api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/notifications.notification.send HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01M6V9CSSRC59RWK6YZPYRR53H
{
"person_ids": [
"per_01M6V9CS6RX26JK5KVYGRN22D2"
],
"title": "Dinner is at 6:00 pm",
"app": "meals"
}HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01M6V9CSSRR41STZFD5WMRFGEP
{
"result": {
"notified": [],
"skipped": [
{
"person_id": "per_01M6V9CS6RX26JK5KVYGRN22D2",
"reason": "self"
}
]
},
"version": 155
}Notify someone who muted the app
The person is left out, with the reason muted.
curl -X POST 'https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/notifications.notification.send' \
-H "Cookie: rigel_session=$RIGEL_SESSION" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: cmd_01M6V9CST6TS6TDDB5ZNY8QKBE' \
-d '{
"person_ids": [
"per_01M6V9CS6RX26JK5KVYGRN22D2"
],
"title": "Saturday pancakes was cooked",
"app": "recipes",
"include_self": true
}'const response = await fetch("https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/notifications.notification.send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Idempotency-Key": "cmd_01M6V9CST6TS6TDDB5ZNY8QKBE",
Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
},
body: JSON.stringify({
person_ids: [
"per_01M6V9CS6RX26JK5KVYGRN22D2",
],
title: "Saturday pancakes was cooked",
app: "recipes",
include_self: true,
}),
});
const data = await response.json();POST /api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/notifications.notification.send HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01M6V9CST6TS6TDDB5ZNY8QKBE
{
"person_ids": [
"per_01M6V9CS6RX26JK5KVYGRN22D2"
],
"title": "Saturday pancakes was cooked",
"app": "recipes",
"include_self": true
}HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01M6V9CST6Y1DP33XXNK9XPYE4
{
"result": {
"notified": [],
"skipped": [
{
"person_id": "per_01M6V9CS6RX26JK5KVYGRN22D2",
"reason": "muted"
}
]
},
"version": 159
}For Rigel#
Rigel's tool for this command is notifications_notification_send. Rigel runs this on its own, then says what it did. The agent guide has the rest.