Skip to content
Rigel docs
Open Rigel

Change an event, or every occurrence of a repeating one

calendar.event.update

POST/api/v1/households/{household_id}/commands/calendar.event.update

  • Command
  • Rigel runs it
  • Applies offline

Sets only the fields given; null clears description, location and recurrence (recurrence null makes it a single event). Giving only starts_at (or start_date) moves the event and keeps its length; giving only ends_at (or end_date) changes its length. To switch between timed and all-day, give both ends of the new kind. A new time_zone with no times keeps the same wall-clock times. person_ids and reminders replace the current ones. On a repeating event, moving the start moves its changed and extra occurrences with it, so a cancelled Saturday stays cancelled; ones the new rule no longer reaches are dropped. For one occurrence use calendar.event.update_occurrence. Events another app owns are refused (event_owned_by_app). Errors: event_not_found, event_owned_by_app, person_not_found, invalid_time_range, invalid_recurrence.

Parameters#

Change an event, or every occurrence of a repeating one: 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.

Change an event, or every occurrence of a repeating one: request body fields
FieldDescription
event_idstringrequired

A calendar event ID, such as evt_01JC0000000000000000000000.

titlestringoptional

The event's title, as written, 1–200 characters.

1 to 200 characters
descriptionstring or nulloptional

Notes about the event, as written, up to 8,000 characters.

at most 8,000 characters
locationstring or nulloptional

Where it is, as written, up to 500 characters.

at most 500 characters
kindone of: event, appointment, activity, chore, meal, trip, birthday, holiday, reminder, busyoptional

What sort of thing it is: event (the default), appointment (a doctor, a contractor), activity (swim, practice), chore, meal, trip, birthday, holiday, reminder, or busy (time blocked with no details).

statusone of: confirmed, tentativeoptional

confirmed (the default), or tentative for a plan that isn't settled.

starts_atstringoptional

When a timed event starts. ISO 8601: with an offset it's that instant, without one it's wall-clock time in time_zone, so 2026-11-11T15:30 means 3:30pm there.

ends_atstringoptional

When a timed event ends, in the same form as starts_at.

start_datestringoptional

The first day of an all-day event, YYYY-MM-DD.

end_datestringoptional

The last day of an all-day event, YYYY-MM-DD, inclusive. The same as start_date for a one-day event.

time_zonestringoptional

The IANA zone the event happens in, such as America/New_York. Defaults to the household's zone.

recurrencestring or nulloptional

An RFC 5545 repeat rule without the "RRULE:" prefix, such as FREQ=WEEKLY;BYDAY=SA;UNTIL=20270328. Supports FREQ DAILY, WEEKLY, MONTHLY and YEARLY with INTERVAL, COUNT, UNTIL, BYDAY (with positions), BYMONTHDAY, BYMONTH, BYSETPOS and WKST.

1 to 500 characters
person_idsarray of stringsoptional

The family members the event involves. Duplicates are ignored.

at most 50 items
remindersarray of objectsoptional

Reminders before the event or each occurrence, at most 5. Replaces the event's current reminders.

at most 5 items
reminders[].minutes_beforeintegerrequired

How long before the event starts, 0 to 40,320 (4 weeks).

0 to 40,320
reminders[].person_idstring or nulloptional

Who to remind. Leave out or null for the people on the event (or the calendar's owner, or everyone).

Response#

200 The command was applied.

Change an event, or every occurrence of a repeating one: response fields
FieldDescription
resultobjectrequired

What the command returned, such as the IDs it created.

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.

Change an event, or every occurrence of a repeating one: errors
StatusCodeWhen
400validation_failedA field is missing, misspelled or out of range. details.fields lists each problem.
401unauthenticatedThe request has no valid session.
404event_not_found
  • The event doesn't exist in this household.
  • The event must exist.
404person_not_found
  • The person doesn't exist in this household.
  • The people must exist.
404not_foundThe household doesn't exist, or you aren't a member of it.
409event_owned_by_appAn event another app owns is refused, naming the app.
409invalid_time_range
  • Switching kinds of timing needs both ends.
  • Ending before the start is refused.
409invalid_recurrenceA rule Rigel can't read 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.

Sets only what's given

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "event_id": "evt_01JC000000000000000000000B",
  "title": "Dentist (Nia and Leo)",
  "description": null,
  "kind": "activity",
  "status": "tentative"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    event_id: "evt_01JC000000000000000000000B",
    title: "Dentist (Nia and Leo)",
    description: null,
    kind: "activity",
    status: "tentative",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "event_id": "evt_01JC000000000000000000000B",
  "title": "Dentist (Nia and Leo)",
  "description": null,
  "kind": "activity",
  "status": "tentative"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R03NFJ4E9VVY43Y0AF

{
  "result": {},
  "version": 1
}

Giving only starts_at moves the event and keeps its length

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "event_id": "evt_01JC000000000000000000000B",
  "starts_at": "2025-11-12T10:00"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    event_id: "evt_01JC000000000000000000000B",
    starts_at: "2025-11-12T10:00",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "event_id": "evt_01JC000000000000000000000B",
  "starts_at": "2025-11-12T10:00"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0ZG4D9CCJ14SYC3AW

{
  "result": {},
  "version": 1
}

Giving only ends_at changes the length

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "event_id": "evt_01JC000000000000000000000B",
  "ends_at": "2025-11-11T17:30"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    event_id: "evt_01JC000000000000000000000B",
    ends_at: "2025-11-11T17:30",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "event_id": "evt_01JC000000000000000000000B",
  "ends_at": "2025-11-11T17:30"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R00C8A677V22CYSXNN

{
  "result": {},
  "version": 1
}

A timed event becomes all-day when both dates are given

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "event_id": "evt_01JC000000000000000000000B",
  "start_date": "2025-11-11",
  "end_date": "2025-11-12"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    event_id: "evt_01JC000000000000000000000B",
    start_date: "2025-11-11",
    end_date: "2025-11-12",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "event_id": "evt_01JC000000000000000000000B",
  "start_date": "2025-11-11",
  "end_date": "2025-11-12"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R02M95R0J17Z0XPHTS

{
  "result": {},
  "version": 1
}

An all-day event becomes timed when both times are given

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "event_id": "evt_01JC000000000000000000000C",
  "starts_at": "2025-11-14T14:00",
  "ends_at": "2025-11-14T18:00"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    event_id: "evt_01JC000000000000000000000C",
    starts_at: "2025-11-14T14:00",
    ends_at: "2025-11-14T18:00",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "event_id": "evt_01JC000000000000000000000C",
  "starts_at": "2025-11-14T14:00",
  "ends_at": "2025-11-14T18:00"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0HTPN3CT2SPDD5GGJ

{
  "result": {},
  "version": 1
}

An all-day event keeps its length when only the first day moves

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "event_id": "evt_01JC000000000000000000000C",
  "start_date": "2025-11-20"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    event_id: "evt_01JC000000000000000000000C",
    start_date: "2025-11-20",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "event_id": "evt_01JC000000000000000000000C",
  "start_date": "2025-11-20"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0QBW7N1A1Y86V41YK

{
  "result": {},
  "version": 1
}

Moving a repeating event's start moves its changes with it, so a cancelled Saturday stays cancelled

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "event_id": "evt_01JC000000000000000000000A",
  "starts_at": "2025-11-08T10:00"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    event_id: "evt_01JC000000000000000000000A",
    starts_at: "2025-11-08T10:00",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "event_id": "evt_01JC000000000000000000000A",
  "starts_at": "2025-11-08T10:00"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0E5HJRHPJ7YQCZ8DV

{
  "result": {},
  "version": 1
}

A new rule drops changes that no longer fall on an occurrence

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "event_id": "evt_01JC000000000000000000000A",
  "recurrence": "FREQ=WEEKLY;BYDAY=SU"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    event_id: "evt_01JC000000000000000000000A",
    recurrence: "FREQ=WEEKLY;BYDAY=SU",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "event_id": "evt_01JC000000000000000000000A",
  "recurrence": "FREQ=WEEKLY;BYDAY=SU"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R02TWDX371PBXGVSVP

{
  "result": {},
  "version": 1
}

Making a repeating event single drops its changes

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "event_id": "evt_01JC000000000000000000000A",
  "recurrence": null
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    event_id: "evt_01JC000000000000000000000A",
    recurrence: null,
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "event_id": "evt_01JC000000000000000000000A",
  "recurrence": null
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R01KDBFXWVXHNK3EYX

{
  "result": {},
  "version": 1
}

A single event can start to repeat

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "event_id": "evt_01JC000000000000000000000B",
  "recurrence": "FREQ=MONTHLY;BYDAY=2TU"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    event_id: "evt_01JC000000000000000000000B",
    recurrence: "FREQ=MONTHLY;BYDAY=2TU",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "event_id": "evt_01JC000000000000000000000B",
  "recurrence": "FREQ=MONTHLY;BYDAY=2TU"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0AH6HN2646S31EXFD

{
  "result": {},
  "version": 1
}

A new time zone keeps the wall-clock times

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "event_id": "evt_01JC000000000000000000000B",
  "time_zone": "America/Chicago"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    event_id: "evt_01JC000000000000000000000B",
    time_zone: "America/Chicago",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "event_id": "evt_01JC000000000000000000000B",
  "time_zone": "America/Chicago"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R09RV8PV1W1HQHCAFN

{
  "result": {},
  "version": 1
}

People are replaced: the ones who stay keep their rows

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "event_id": "evt_01JC000000000000000000000B",
  "person_ids": [
    "per_01JC000000000000000000000A",
    "per_01JC000000000000000000000B"
  ]
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    event_id: "evt_01JC000000000000000000000B",
    person_ids: [
      "per_01JC000000000000000000000A",
      "per_01JC000000000000000000000B",
    ],
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "event_id": "evt_01JC000000000000000000000B",
  "person_ids": [
    "per_01JC000000000000000000000A",
    "per_01JC000000000000000000000B"
  ]
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R08K5R7X0YE6K3NVAA

{
  "result": {},
  "version": 1
}

Reminders are replaced: matching ones stay, and pending notifications are scheduled again

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "event_id": "evt_01JC000000000000000000000B",
  "reminders": [
    {
      "minutes_before": 30
    },
    {
      "minutes_before": 0
    }
  ]
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    event_id: "evt_01JC000000000000000000000B",
    reminders: [
      {
        minutes_before: 30,
      },
      {
        minutes_before: 0,
      },
    ],
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "event_id": "evt_01JC000000000000000000000B",
  "reminders": [
    {
      "minutes_before": 30
    },
    {
      "minutes_before": 0
    }
  ]
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0ETAY3JCRXN6EMFDP

{
  "result": {},
  "version": 1
}

An event on a busy-only calendar is stored as Busy with no details, whatever it was or is given

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "event_id": "evt_01JC000000000000000000000B",
  "title": "Secret meeting",
  "description": "x",
  "person_ids": [
    "per_01JC000000000000000000000C"
  ]
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    event_id: "evt_01JC000000000000000000000B",
    title: "Secret meeting",
    description: "x",
    person_ids: [
      "per_01JC000000000000000000000C",
    ],
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "event_id": "evt_01JC000000000000000000000B",
  "title": "Secret meeting",
  "description": "x",
  "person_ids": [
    "per_01JC000000000000000000000C"
  ]
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R08TDEEQD6NA6HHB83

{
  "result": {},
  "version": 1
}

Switching kinds of timing needs both ends

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "event_id": "evt_01JC000000000000000000000B",
  "start_date": "2025-11-11"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    event_id: "evt_01JC000000000000000000000B",
    start_date: "2025-11-11",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "event_id": "evt_01JC000000000000000000000B",
  "start_date": "2025-11-11"
}
Response, 409
HTTP/1.1 409 Conflict
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0H69Q0EC1Z0KZDV9J

{
  "error": {
    "code": "invalid_time_range",
    "message": "To make a timed event all-day, give both start_date and end_date. No changes were applied.",
    "details": {},
    "recovery": "Read the current state, then send a command that fits it.",
    "request_id": "req_01K9D9S2R0H69Q0EC1Z0KZDV9J"
  }
}

Ending before the start is refused

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "event_id": "evt_01JC000000000000000000000B",
  "ends_at": "2025-11-11T15:00"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    event_id: "evt_01JC000000000000000000000B",
    ends_at: "2025-11-11T15:00",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "event_id": "evt_01JC000000000000000000000B",
  "ends_at": "2025-11-11T15:00"
}
Response, 409
HTTP/1.1 409 Conflict
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0CA91ST1TW0A2M2E0

{
  "error": {
    "code": "invalid_time_range",
    "message": "An event can't end before it starts. No changes were applied.",
    "details": {},
    "recovery": "Read the current state, then send a command that fits it.",
    "request_id": "req_01K9D9S2R0CA91ST1TW0A2M2E0"
  }
}

An event another app owns is refused, naming the app

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "event_id": "evt_01JC000000000000000000000D",
  "title": "x"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    event_id: "evt_01JC000000000000000000000D",
    title: "x",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "event_id": "evt_01JC000000000000000000000D",
  "title": "x"
}
Response, 409
HTTP/1.1 409 Conflict
Content-Type: application/json
X-Request-Id: req_01K9D9S2R07TVY36NWJ6AKS9M5

{
  "error": {
    "code": "event_owned_by_app",
    "message": "Maintenance manages this event. Change it there. No changes were applied.",
    "details": {
      "app": "maintenance"
    },
    "recovery": "Read the current state, then send a command that fits it.",
    "request_id": "req_01K9D9S2R07TVY36NWJ6AKS9M5"
  }
}

A rule Rigel can't read is refused

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "event_id": "evt_01JC000000000000000000000B",
  "recurrence": "FREQ=SECONDLY"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    event_id: "evt_01JC000000000000000000000B",
    recurrence: "FREQ=SECONDLY",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "event_id": "evt_01JC000000000000000000000B",
  "recurrence": "FREQ=SECONDLY"
}
Response, 409
HTTP/1.1 409 Conflict
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0GM6SES5S6X5H4HFM

{
  "error": {
    "code": "invalid_recurrence",
    "message": "That repeat rule doesn't work: Rigel can't repeat events by the second. No changes were applied.",
    "details": {
      "problem": "Rigel can't repeat events by the second."
    },
    "recovery": "Read the current state, then send a command that fits it.",
    "request_id": "req_01K9D9S2R0GM6SES5S6X5H4HFM"
  }
}

The people must exist

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "event_id": "evt_01JC000000000000000000000B",
  "person_ids": [
    "per_01JC000000000000000000000Z"
  ]
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    event_id: "evt_01JC000000000000000000000B",
    person_ids: [
      "per_01JC000000000000000000000Z",
    ],
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "event_id": "evt_01JC000000000000000000000B",
  "person_ids": [
    "per_01JC000000000000000000000Z"
  ]
}
Response, 404
HTTP/1.1 404 Not Found
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0D2R9P8C2619SBDWQ

{
  "error": {
    "code": "person_not_found",
    "message": "That person isn't in the household any more. No changes were applied.",
    "details": {
      "person_id": "per_01JC000000000000000000000Z"
    },
    "recovery": "Read the current state, then send a command that fits it.",
    "request_id": "req_01K9D9S2R0D2R9P8C2619SBDWQ"
  }
}

The event must exist

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "event_id": "evt_01JC000000000000000000000Z",
  "title": "x"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    event_id: "evt_01JC000000000000000000000Z",
    title: "x",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/calendar.event.update HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "event_id": "evt_01JC000000000000000000000Z",
  "title": "x"
}
Response, 404
HTTP/1.1 404 Not Found
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0T2290Q0H82FDE9Q6

{
  "error": {
    "code": "event_not_found",
    "message": "That event isn't on the calendar any more. No changes were applied.",
    "details": {
      "event_id": "evt_01JC000000000000000000000Z"
    },
    "recovery": "Read the current state, then send a command that fits it.",
    "request_id": "req_01K9D9S2R0T2290Q0H82FDE9Q6"
  }
}

Change an event

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/calendar.event.update' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01M6V9CSKVWNH83NSEY2CQJCCF' \
  -d '{
  "event_id": "evt_01M6V9CSHPG77MMGGKHAEJQ484",
  "location": "Riverside Park, field 2"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/calendar.event.update", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01M6V9CSKVWNH83NSEY2CQJCCF",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    event_id: "evt_01M6V9CSHPG77MMGGKHAEJQ484",
    location: "Riverside Park, field 2",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/calendar.event.update HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01M6V9CSKVWNH83NSEY2CQJCCF

{
  "event_id": "evt_01M6V9CSHPG77MMGGKHAEJQ484",
  "location": "Riverside Park, field 2"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01M6V9CSKVN63VTXSR33B0R6X2

{
  "result": {},
  "version": 99
}

Change an event another app owns

Only the owning app changes it. Anyone can still move it, attach files, or change its people and reminders.

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/calendar.event.update' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01M6V9CSMC1S13322VH007AJ9R' \
  -d '{
  "event_id": "evt_01M6V9CSM9VAVPZBE6BH6107WD",
  "title": "Orzo, maybe"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/calendar.event.update", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01M6V9CSMC1S13322VH007AJ9R",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    event_id: "evt_01M6V9CSM9VAVPZBE6BH6107WD",
    title: "Orzo, maybe",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/calendar.event.update HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01M6V9CSMC1S13322VH007AJ9R

{
  "event_id": "evt_01M6V9CSM9VAVPZBE6BH6107WD",
  "title": "Orzo, maybe"
}
Response, 409
HTTP/1.1 409 Conflict
Content-Type: application/json
X-Request-Id: req_01M6V9CSMCHTTA52B9CRDRFEW6

{
  "error": {
    "code": "event_owned_by_app",
    "message": "Meals manages this event. Change it there. No changes were applied.",
    "details": {
      "app": "meals"
    },
    "recovery": "Read the current state, then send a command that fits it.",
    "request_id": "req_01M6V9CSMCHTTA52B9CRDRFEW6"
  }
}

For Rigel#

Rigel's tool for this command is calendar_event_update. 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