Skip to content
Rigel docs
Open Rigel

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#

Notify people: parameters
FieldDescription
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.

Notify people: request body fields
FieldDescription
person_idsarray of stringsrequired

The people to notify, 1–50.

1 to 50 items
titlestringrequired

What the notification says on a lock screen, 1–120 characters. Never the private detail.

1 to 120 characters
bodystring or nulloptional

More detail, shown only inside the app, up to 500 characters.

at most 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.

at most 40 characterspattern ^[a-z][a-z0-9]*(_[a-z0-9]+)*$Default "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.

Notify people: response fields
FieldDescription
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.

Notify people: errors
StatusCodeWhen
400validation_failedA field is missing, misspelled or out of range. details.fields lists each problem.
401unauthenticatedThe request has no valid session.
404person_not_foundA person who isn't in the household is refused, and nobody is notified.
404not_foundThe household doesn't exist, or you aren't a member of it.
409invalid_time_range
  • Expiring before it's due is refused.
  • An expiry in the past, with no deliver_at, is refused.
409idempotency_key_reusedThe 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

Request, curl
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"
}'
Request, TypeScript
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();
Request, HTTP
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"
}
Response, 200
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

Request, curl
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"
}'
Request, TypeScript
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();
Request, HTTP
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"
}
Response, 200
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

Request, curl
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
}'
Request, TypeScript
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();
Request, HTTP
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
}
Response, 200
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

Request, curl
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"
}'
Request, TypeScript
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();
Request, HTTP
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"
}
Response, 200
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

Request, curl
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"
}'
Request, TypeScript
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();
Request, HTTP
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"
}
Response, 200
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

Request, curl
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"
}'
Request, TypeScript
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();
Request, HTTP
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"
}
Response, 200
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

Request, curl
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"
}'
Request, TypeScript
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();
Request, HTTP
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"
}
Response, 200
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

Request, curl
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"
}'
Request, TypeScript
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();
Request, HTTP
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"
}
Response, 200
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

Request, curl
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"
}'
Request, TypeScript
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();
Request, HTTP
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"
}
Response, 200
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

Request, curl
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"
}'
Request, TypeScript
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();
Request, HTTP
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"
}
Response, 200
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

Request, curl
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"
}'
Request, TypeScript
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();
Request, HTTP
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"
}
Response, 200
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

Request, curl
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"
}'
Request, TypeScript
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();
Request, HTTP
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"
}
Response, 409
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

Request, curl
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"
}'
Request, TypeScript
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();
Request, HTTP
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"
}
Response, 409
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

Request, curl
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"
}'
Request, TypeScript
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();
Request, HTTP
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"
}
Response, 404
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.

Request, curl
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
}'
Request, TypeScript
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();
Request, HTTP
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
}
Response, 200
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.

Request, curl
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
}'
Request, TypeScript
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();
Request, HTTP
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
}
Response, 200
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.

Request, curl
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"
}'
Request, TypeScript
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();
Request, HTTP
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"
}
Response, 200
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.

Request, curl
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
}'
Request, TypeScript
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();
Request, HTTP
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
}
Response, 200
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.

Rigel is in early access, and sign-up is by invitation. Open Rigel