Skip to content
Rigel docs
Open Rigel

Add a recurring maintenance task

maintenance.task.add

POST/api/v1/households/{household_id}/commands/maintenance.task.add

  • Command
  • Rigel runs it
  • Applies offline

Adds a maintenance rule for an item, a place, or the whole home (give asset_id or location_id, not both). The first due date is next_due_on if given, else counted from last_done_on (which also records that it was done), else spread 7 to 27 days out for tasks that repeat from completion and set by the rule for the others. Proposed tasks go straight in. Fails with one_subject, invalid_timing or invalid_range.

Parameters#

Add a recurring maintenance task: 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.

Add a recurring maintenance task: request body fields
FieldDescription
property_idstringoptional

Which property. Leave out when the household has one, or when asset_id or location_id is given.

asset_idstringoptional

The item the task is for.

location_idstringoptional

The place the task is for.

titlestringrequired

What to do, in a few words: "Replace the furnace filter".

at most 200 characters
summarystringoptional

What it is, in a sentence or two of plain words.

at most 20,000 characters
whystringoptional

What goes wrong if it's skipped, with a rough cost of the failure where known.

at most 20,000 characters
timingone of 5 shapesrequired

How the task repeats. Exactly one kind.

Shape 1
timing.kindone of: intervalrequired

Counted from when it was last done.

timing.everyintegerrequired

How many units between one time and the next.

1 to 1,200
timing.unitone of: day, week, month, yearrequired

The unit of the interval: day, week, month or year.

Shape 2, with month_day
timing.kindone of: anchoredrequired

On a fixed day of the year, kept even when done late or early.

timing.month_daystringrequired

The anchor day, MM-DD, such as 09-15.

pattern ^(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
timing.everyintegeroptional

How many units between anchor dates. Defaults to 1.

1 to 100
timing.unitone of: month, yearoptional

month or year. Defaults to year.

Shape 3, with start, end
timing.kindone of: seasonalrequired

Once a year, in a window that may wrap the new year.

timing.startstringrequired

When the window opens, MM-DD.

pattern ^(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
timing.endstringrequired

When the window closes, MM-DD. May be earlier in the year than start (11-15 to 02-15).

pattern ^(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
timing.reasoningstringoptional

Why the window is where it is, shown on the task page so the household can move it.

at most 2,000 characters
Shape 4, with rule
timing.kindone of: usagerequired

When a reading or a check says so; shows as Check until given a date.

timing.rulestringrequired

When it's due, in words: "every 100 hours", "when the salt is low".

at most 200 characters
Shape 5
timing.kindone of: oncerequired

Done for good once checked off.

importanceone of: essential, recommended, optionaloptional

Defaults to recommended.

next_due_onstring (date)optional

The first due date, overriding the rule. For a seasonal task, the day its window opens.

last_done_onstring (date)optional

When it was last done, if known. Records a completion and counts the next due date from it. Leave out when unknown.

diy_stepsstringoptional

Markdown: steps, tools, supplies, time needed, and the signs that mean you should call a pro. Leave out when DIY isn't reasonable.

at most 20,000 characters
hire_guidancestringoptional

Markdown: the kind of contractor and what to ask for.

at most 20,000 characters
costobjectoptional

Cost estimates as ranges. Sending cost replaces all of the task's estimates.

cost.currencystringrequired

An ISO 4217 currency code, such as USD.

pattern ^[A-Z]{3}$
cost.diy_minintegeroptional

Lowest cost to do it yourself, in minor units (cents).

0 to 1,000,000,000
cost.diy_maxintegeroptional

Highest cost to do it yourself, in minor units.

0 to 1,000,000,000
cost.hire_minintegeroptional

Lowest cost to hire it out, in minor units.

0 to 1,000,000,000
cost.hire_maxintegeroptional

Highest cost to hire it out, in minor units.

0 to 1,000,000,000
cost.basisstringoptional

Where the estimate comes from: place, date and source.

at most 500 characters
handled_byone of: diy, hire, serviceoptional

How the household handles it: diy (does it themselves), hire (calls someone), service (covered by a service plan).

handling_notestringoptional

The household's plan, such as "Call Lakes Region HVAC to schedule."

at most 2,000 characters
contractor_idstringoptional

The contractor who handles it.

assignee_person_idstringoptional

Who in the household usually does it.

house_notesstringoptional

Anything specific to this home: "shutoff is behind the water heater".

at most 20,000 characters
originone of: manufacturer, general, homeownerrequired

Where the task came from: manufacturer (the manual or maker), general (general guidance for this kind of thing), homeowner (someone in the household asked for it).

evidenceobjectoptional

Where the task came from, such as the manual page or what someone said.

evidence.file_idstringoptional

A photo, manual or invoice already uploaded to the household's files.

evidence.urlstring (uri)optional

A web address.

at most 2,000 characters
evidence.said_by_person_idstringoptional

Who said it, when the source is something a person said.

evidence.locatorstringoptional

Where in the source: "p. 14", "rating plate".

at most 200 characters
evidence.excerptstringoptional

The exact text the value was read from.

at most 2,000 characters
part_idsarray of stringsoptional

Parts and supplies the task uses.

at most 50 items

Response#

200 The command was applied.

Add a recurring maintenance task: response fields
FieldDescription
resultobjectrequired

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

result.task_idstringrequired

The new task.

result.completion_idstring or nullrequired

The completion recorded for last_done_on, or null.

result.next_due_onstring or nullrequired

When it's next due, or null for a usage task without a date.

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.

Add a recurring maintenance task: errors
StatusCodeWhen
400validation_failedA field is missing, misspelled or out of range. details.fields lists each problem.
401unauthenticatedThe request has no valid session.
404asset_not_foundRejects an unknown item.
404location_not_foundRejects an unknown place.
404property_not_foundRejects an unknown property.
404contractor_not_foundRejects an unknown contractor.
404person_not_foundRejects an unknown assignee.
404part_not_foundRejects an unknown part.
404not_foundThe household doesn't exist, or you aren't a member of it.
409one_subjectRejects an asset and a place together.
409invalid_range
  • Rejects a cost range whose lowest is above its highest.
  • Rejects a do-it-yourself range that's reversed.
409invalid_timingRejects a window that opens and closes on the same day.
409different_propertyRejects an item at a different property than the one named.
409property_requiredRejects no property named when there are several.
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.

A known last date records a completion and counts the next due date from it

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA01' \
  -d '{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "last_done_on": "2025-10-01"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAA01",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    title: "Replace the furnace filter",
    timing: {
      kind: "interval",
      every: 3,
      unit: "month",
    },
    origin: "general",
    last_done_on: "2025-10-01",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA01

{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "last_done_on": "2025-10-01"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0S20W4M7W3GES2AXW

{
  "result": {
    "task_id": "mtk_01JC4N0000X7XC2MTDD2363JZD",
    "completion_id": "mtc_01JC4N0000EPJFDHTDT9TKJD4S",
    "next_due_on": "2026-01-01"
  },
  "version": 1
}

An unknown last date spreads the first due date 7 to 27 days out, chosen from the task's ID

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA02' \
  -d '{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAA02",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    title: "Replace the furnace filter",
    timing: {
      kind: "interval",
      every: 3,
      unit: "month",
    },
    origin: "general",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA02

{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0SR4ZXXVRWEBS10EM

{
  "result": {
    "task_id": "mtk_01JC4N000043K2D1Z3D5HKPY5A",
    "completion_id": null,
    "next_due_on": "2025-11-24"
  },
  "version": 1
}

The first command in a household makes its property

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA03' \
  -d '{
  "title": "Service the furnace",
  "timing": {
    "kind": "anchored",
    "month_day": "09-15"
  },
  "origin": "manufacturer",
  "importance": "essential",
  "handled_by": "hire"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAA03",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    title: "Service the furnace",
    timing: {
      kind: "anchored",
      month_day: "09-15",
    },
    origin: "manufacturer",
    importance: "essential",
    handled_by: "hire",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA03

{
  "title": "Service the furnace",
  "timing": {
    "kind": "anchored",
    "month_day": "09-15"
  },
  "origin": "manufacturer",
  "importance": "essential",
  "handled_by": "hire"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0MPM7AZPJ9BPZ5262

{
  "result": {
    "task_id": "mtk_01JC4N0000D6KXZRA9QPV9FTYR",
    "completion_id": null,
    "next_due_on": "2026-09-15"
  },
  "version": 1
}

An item's task with a source, cost, parts, a contractor and an assignee; a seasonal window that's open starts at its opening day

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA04' \
  -d '{
  "asset_id": "ast_01JC0000000000000000000001",
  "title": "Winterize the irrigation",
  "timing": {
    "kind": "seasonal",
    "start": "10-01",
    "end": "11-15",
    "reasoning": "First frost is usually mid-October."
  },
  "origin": "manufacturer",
  "evidence": {
    "url": "https://example.com/manual.pdf",
    "locator": "p. 14"
  },
  "cost": {
    "currency": "USD",
    "diy_min": 2000,
    "diy_max": 4000,
    "hire_min": 15000,
    "hire_max": 20000,
    "basis": "New Hampshire, 2025"
  },
  "handled_by": "hire",
  "handling_note": "Call them in September",
  "contractor_id": "ctr_01JC0000000000000000000001",
  "assignee_person_id": "per_01JC0000000000000000000001",
  "part_ids": [
    "prt_01JC0000000000000000000001",
    "prt_01JC0000000000000000000002",
    "prt_01JC0000000000000000000001"
  ]
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAA04",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    asset_id: "ast_01JC0000000000000000000001",
    title: "Winterize the irrigation",
    timing: {
      kind: "seasonal",
      start: "10-01",
      end: "11-15",
      reasoning: "First frost is usually mid-October.",
    },
    origin: "manufacturer",
    evidence: {
      url: "https://example.com/manual.pdf",
      locator: "p. 14",
    },
    cost: {
      currency: "USD",
      diy_min: 2000,
      diy_max: 4000,
      hire_min: 15000,
      hire_max: 20000,
      basis: "New Hampshire, 2025",
    },
    handled_by: "hire",
    handling_note: "Call them in September",
    contractor_id: "ctr_01JC0000000000000000000001",
    assignee_person_id: "per_01JC0000000000000000000001",
    part_ids: [
      "prt_01JC0000000000000000000001",
      "prt_01JC0000000000000000000002",
      "prt_01JC0000000000000000000001",
    ],
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA04

{
  "asset_id": "ast_01JC0000000000000000000001",
  "title": "Winterize the irrigation",
  "timing": {
    "kind": "seasonal",
    "start": "10-01",
    "end": "11-15",
    "reasoning": "First frost is usually mid-October."
  },
  "origin": "manufacturer",
  "evidence": {
    "url": "https://example.com/manual.pdf",
    "locator": "p. 14"
  },
  "cost": {
    "currency": "USD",
    "diy_min": 2000,
    "diy_max": 4000,
    "hire_min": 15000,
    "hire_max": 20000,
    "basis": "New Hampshire, 2025"
  },
  "handled_by": "hire",
  "handling_note": "Call them in September",
  "contractor_id": "ctr_01JC0000000000000000000001",
  "assignee_person_id": "per_01JC0000000000000000000001",
  "part_ids": [
    "prt_01JC0000000000000000000001",
    "prt_01JC0000000000000000000002",
    "prt_01JC0000000000000000000001"
  ]
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0MNG1P8Y0YXVQB5S3

{
  "result": {
    "task_id": "mtk_01JC4N0000DBZ0A30789BQBA1F",
    "completion_id": null,
    "next_due_on": "2025-10-01"
  },
  "version": 1
}

A place's task, and a wrapping window that is open after the new year

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA05' \
  -d '{
  "location_id": "mlc_01JC0000000000000000000001",
  "title": "Clear the roof",
  "timing": {
    "kind": "seasonal",
    "start": "11-15",
    "end": "02-15"
  },
  "origin": "homeowner"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAA05",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    location_id: "mlc_01JC0000000000000000000001",
    title: "Clear the roof",
    timing: {
      kind: "seasonal",
      start: "11-15",
      end: "02-15",
    },
    origin: "homeowner",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA05

{
  "location_id": "mlc_01JC0000000000000000000001",
  "title": "Clear the roof",
  "timing": {
    "kind": "seasonal",
    "start": "11-15",
    "end": "02-15"
  },
  "origin": "homeowner"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0TCXS7A3JAT3XKRF2

{
  "result": {
    "task_id": "mtk_01JC4N0000H2AEHPF910NY3WC4",
    "completion_id": null,
    "next_due_on": "2025-11-15"
  },
  "version": 1
}

A usage task has no date until it is given one

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA06' \
  -d '{
  "title": "Add salt",
  "timing": {
    "kind": "usage",
    "rule": "when the salt is low"
  },
  "origin": "homeowner"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAA06",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    title: "Add salt",
    timing: {
      kind: "usage",
      rule: "when the salt is low",
    },
    origin: "homeowner",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA06

{
  "title": "Add salt",
  "timing": {
    "kind": "usage",
    "rule": "when the salt is low"
  },
  "origin": "homeowner"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0QAJ2W2QR1X00B6A9

{
  "result": {
    "task_id": "mtk_01JC4N0000RBJ11BRAXVJVM8TS",
    "completion_id": null,
    "next_due_on": null
  },
  "version": 1
}

An explicit next_due_on wins, and last_done_on is still recorded

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA07' \
  -d '{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "last_done_on": "2025-10-01",
  "next_due_on": "2025-12-24",
  "importance": "optional"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAA07",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    title: "Replace the furnace filter",
    timing: {
      kind: "interval",
      every: 3,
      unit: "month",
    },
    origin: "general",
    last_done_on: "2025-10-01",
    next_due_on: "2025-12-24",
    importance: "optional",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA07

{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "last_done_on": "2025-10-01",
  "next_due_on": "2025-12-24",
  "importance": "optional"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0NAMNSKNREX1JF7SP

{
  "result": {
    "task_id": "mtk_01JC4N0000BZEH8WN4S4XM9FPQ",
    "completion_id": "mtc_01JC4N00004Y71CTN4PK76SEKM",
    "next_due_on": "2025-12-24"
  },
  "version": 1
}

A once task done already has no next date

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA08' \
  -d '{
  "title": "Register the warranty",
  "timing": {
    "kind": "once"
  },
  "origin": "general",
  "last_done_on": "2025-10-20"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAA08",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    title: "Register the warranty",
    timing: {
      kind: "once",
    },
    origin: "general",
    last_done_on: "2025-10-20",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA08

{
  "title": "Register the warranty",
  "timing": {
    "kind": "once"
  },
  "origin": "general",
  "last_done_on": "2025-10-20"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0GBH112BAM16A9XX1

{
  "result": {
    "task_id": "mtk_01JC4N0000J90CJ93K9W3ZQZXZ",
    "completion_id": "mtc_01JC4N0000HA1J4C3KWDZG8W00",
    "next_due_on": null
  },
  "version": 1
}

Rejects an asset and a place together

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA09' \
  -d '{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "asset_id": "ast_01JC0000000000000000000001",
  "location_id": "mlc_01JC0000000000000000000001"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAA09",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    title: "Replace the furnace filter",
    timing: {
      kind: "interval",
      every: 3,
      unit: "month",
    },
    origin: "general",
    asset_id: "ast_01JC0000000000000000000001",
    location_id: "mlc_01JC0000000000000000000001",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA09

{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "asset_id": "ast_01JC0000000000000000000001",
  "location_id": "mlc_01JC0000000000000000000001"
}
Response, 409
HTTP/1.1 409 Conflict
Content-Type: application/json
X-Request-Id: req_01K9D9S2R01PTDG527FRWW9G3Q

{
  "error": {
    "code": "one_subject",
    "message": "Give an asset or a place, not both. No changes were applied.",
    "details": {},
    "recovery": "Read the current state, then send a command that fits it.",
    "request_id": "req_01K9D9S2R01PTDG527FRWW9G3Q"
  }
}

Rejects a cost range whose lowest is above its highest

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA0A' \
  -d '{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "cost": {
    "currency": "USD",
    "hire_min": 500,
    "hire_max": 100
  }
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAA0A",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    title: "Replace the furnace filter",
    timing: {
      kind: "interval",
      every: 3,
      unit: "month",
    },
    origin: "general",
    cost: {
      currency: "USD",
      hire_min: 500,
      hire_max: 100,
    },
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA0A

{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "cost": {
    "currency": "USD",
    "hire_min": 500,
    "hire_max": 100
  }
}
Response, 409
HTTP/1.1 409 Conflict
Content-Type: application/json
X-Request-Id: req_01K9D9S2R03KTPAT0MAW0GQ0DP

{
  "error": {
    "code": "invalid_range",
    "message": "The lowest hired cost is higher than the highest. No changes were applied.",
    "details": {},
    "recovery": "Read the current state, then send a command that fits it.",
    "request_id": "req_01K9D9S2R03KTPAT0MAW0GQ0DP"
  }
}

Rejects a do-it-yourself range that's reversed

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA0B' \
  -d '{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "cost": {
    "currency": "USD",
    "diy_min": 500,
    "diy_max": 100
  }
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAA0B",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    title: "Replace the furnace filter",
    timing: {
      kind: "interval",
      every: 3,
      unit: "month",
    },
    origin: "general",
    cost: {
      currency: "USD",
      diy_min: 500,
      diy_max: 100,
    },
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA0B

{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "cost": {
    "currency": "USD",
    "diy_min": 500,
    "diy_max": 100
  }
}
Response, 409
HTTP/1.1 409 Conflict
Content-Type: application/json
X-Request-Id: req_01K9D9S2R06J3KDB41WS6QKWB3

{
  "error": {
    "code": "invalid_range",
    "message": "The lowest do-it-yourself cost is higher than the highest. No changes were applied.",
    "details": {},
    "recovery": "Read the current state, then send a command that fits it.",
    "request_id": "req_01K9D9S2R06J3KDB41WS6QKWB3"
  }
}

Rejects a window that opens and closes on the same day

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA0C' \
  -d '{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "seasonal",
    "start": "10-01",
    "end": "10-01"
  },
  "origin": "general"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAA0C",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    title: "Replace the furnace filter",
    timing: {
      kind: "seasonal",
      start: "10-01",
      end: "10-01",
    },
    origin: "general",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA0C

{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "seasonal",
    "start": "10-01",
    "end": "10-01"
  },
  "origin": "general"
}
Response, 409
HTTP/1.1 409 Conflict
Content-Type: application/json
X-Request-Id: req_01K9D9S2R08Y6WJC8MGB8J4BGP

{
  "error": {
    "code": "invalid_timing",
    "message": "A season window needs different start and end days. No changes were applied.",
    "details": {},
    "recovery": "Read the current state, then send a command that fits it.",
    "request_id": "req_01K9D9S2R08Y6WJC8MGB8J4BGP"
  }
}

Rejects an unknown item

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA0D' \
  -d '{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "asset_id": "ast_01JC0000000000000000000002"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAA0D",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    title: "Replace the furnace filter",
    timing: {
      kind: "interval",
      every: 3,
      unit: "month",
    },
    origin: "general",
    asset_id: "ast_01JC0000000000000000000002",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA0D

{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "asset_id": "ast_01JC0000000000000000000002"
}
Response, 404
HTTP/1.1 404 Not Found
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0Y0KHSGD0BW1GR6F0

{
  "error": {
    "code": "asset_not_found",
    "message": "That item isn't in the house records any more. No changes were applied.",
    "details": {
      "asset_id": "ast_01JC0000000000000000000002"
    },
    "recovery": "Read the current state, then send a command that fits it.",
    "request_id": "req_01K9D9S2R0Y0KHSGD0BW1GR6F0"
  }
}

Rejects an unknown place

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA0E' \
  -d '{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "location_id": "mlc_01JC0000000000000000000002"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAA0E",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    title: "Replace the furnace filter",
    timing: {
      kind: "interval",
      every: 3,
      unit: "month",
    },
    origin: "general",
    location_id: "mlc_01JC0000000000000000000002",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA0E

{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "location_id": "mlc_01JC0000000000000000000002"
}
Response, 404
HTTP/1.1 404 Not Found
Content-Type: application/json
X-Request-Id: req_01K9D9S2R05YV9QPXAPAJVQHJ5

{
  "error": {
    "code": "location_not_found",
    "message": "That place isn't there any more. No changes were applied.",
    "details": {
      "location_id": "mlc_01JC0000000000000000000002"
    },
    "recovery": "Read the current state, then send a command that fits it.",
    "request_id": "req_01K9D9S2R05YV9QPXAPAJVQHJ5"
  }
}

Rejects an unknown property

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA0F' \
  -d '{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "property_id": "prp_01JC0000000000000000000002"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAA0F",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    title: "Replace the furnace filter",
    timing: {
      kind: "interval",
      every: 3,
      unit: "month",
    },
    origin: "general",
    property_id: "prp_01JC0000000000000000000002",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA0F

{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "property_id": "prp_01JC0000000000000000000002"
}
Response, 404
HTTP/1.1 404 Not Found
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0KSMSMG3ZT0T601DV

{
  "error": {
    "code": "property_not_found",
    "message": "That property isn't there any more. No changes were applied.",
    "details": {
      "property_id": "prp_01JC0000000000000000000002"
    },
    "recovery": "Read the current state, then send a command that fits it.",
    "request_id": "req_01K9D9S2R0KSMSMG3ZT0T601DV"
  }
}

Rejects an item at a different property than the one named

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA0G' \
  -d '{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "asset_id": "ast_01JC0000000000000000000001",
  "property_id": "prp_01JC0000000000000000000002"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAA0G",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    title: "Replace the furnace filter",
    timing: {
      kind: "interval",
      every: 3,
      unit: "month",
    },
    origin: "general",
    asset_id: "ast_01JC0000000000000000000001",
    property_id: "prp_01JC0000000000000000000002",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA0G

{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "asset_id": "ast_01JC0000000000000000000001",
  "property_id": "prp_01JC0000000000000000000002"
}
Response, 409
HTTP/1.1 409 Conflict
Content-Type: application/json
X-Request-Id: req_01K9D9S2R09SECKPA8N6PCYXFX

{
  "error": {
    "code": "different_property",
    "message": "That item is at a different property. No changes were applied.",
    "details": {
      "property_id": "prp_01JC0000000000000000000001"
    },
    "recovery": "Read the current state, then send a command that fits it.",
    "request_id": "req_01K9D9S2R09SECKPA8N6PCYXFX"
  }
}

Rejects no property named when there are several

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA0H' \
  -d '{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAA0H",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    title: "Replace the furnace filter",
    timing: {
      kind: "interval",
      every: 3,
      unit: "month",
    },
    origin: "general",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA0H

{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general"
}
Response, 409
HTTP/1.1 409 Conflict
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0X1MTDSSDTJPNSBF3

{
  "error": {
    "code": "property_required",
    "message": "This household has more than one property. Say which one. No changes were applied.",
    "details": {},
    "recovery": "Read the current state, then send a command that fits it.",
    "request_id": "req_01K9D9S2R0X1MTDSSDTJPNSBF3"
  }
}

Rejects an unknown contractor

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA0J' \
  -d '{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "contractor_id": "ctr_01JC0000000000000000000001"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAA0J",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    title: "Replace the furnace filter",
    timing: {
      kind: "interval",
      every: 3,
      unit: "month",
    },
    origin: "general",
    contractor_id: "ctr_01JC0000000000000000000001",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA0J

{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "contractor_id": "ctr_01JC0000000000000000000001"
}
Response, 404
HTTP/1.1 404 Not Found
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0KSKKAA47NGJAGP1H

{
  "error": {
    "code": "contractor_not_found",
    "message": "That contractor isn't there any more. No changes were applied.",
    "details": {
      "contractor_id": "ctr_01JC0000000000000000000001"
    },
    "recovery": "Read the current state, then send a command that fits it.",
    "request_id": "req_01K9D9S2R0KSKKAA47NGJAGP1H"
  }
}

Rejects an unknown assignee

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA0K' \
  -d '{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "assignee_person_id": "per_01JC0000000000000000000001"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAA0K",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    title: "Replace the furnace filter",
    timing: {
      kind: "interval",
      every: 3,
      unit: "month",
    },
    origin: "general",
    assignee_person_id: "per_01JC0000000000000000000001",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA0K

{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "assignee_person_id": "per_01JC0000000000000000000001"
}
Response, 404
HTTP/1.1 404 Not Found
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0GW90WNRVEHGJEWVW

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

Rejects an unknown part

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA0M' \
  -d '{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "part_ids": [
    "prt_01JC0000000000000000000001"
  ]
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAA0M",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    title: "Replace the furnace filter",
    timing: {
      kind: "interval",
      every: 3,
      unit: "month",
    },
    origin: "general",
    part_ids: [
      "prt_01JC0000000000000000000001",
    ],
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAA0M

{
  "title": "Replace the furnace filter",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "origin": "general",
  "part_ids": [
    "prt_01JC0000000000000000000001"
  ]
}
Response, 404
HTTP/1.1 404 Not Found
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0RTHDGJRMBCE7KBY6

{
  "error": {
    "code": "part_not_found",
    "message": "That part isn't recorded any more. No changes were applied.",
    "details": {
      "part_id": "prt_01JC0000000000000000000001"
    },
    "recovery": "Read the current state, then send a command that fits it.",
    "request_id": "req_01K9D9S2R0RTHDGJRMBCE7KBY6"
  }
}

Add a task that repeats from when it was last done

last_done_on records that it was done and counts the next due date from it.

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01M6V9CSWMSNF57R0B23S0F1NP' \
  -d '{
  "asset_id": "ast_01M6V9CSVCMZFAP6ZN5WANZ6M8",
  "title": "Replace the furnace filter",
  "summary": "Swap the 16x25x1 filter. The arrow points toward the furnace.",
  "why": "A clogged filter strains the blower and cuts airflow.",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "importance": "essential",
  "last_done_on": "2026-08-19",
  "handled_by": "diy",
  "assignee_person_id": "per_01M6V9CS744BQQH188FS6CXY9W",
  "diy_steps": "Switch the furnace off. Slide out the old filter, slide in the new one, and write the date on the frame.",
  "cost": {
    "currency": "USD",
    "diy_min": 1500,
    "diy_max": 3000,
    "basis": "A 4-pack lasts a year"
  },
  "origin": "manufacturer",
  "part_ids": [
    "prt_01M6V9CSWCCK3TQDA78RGRZ2E2"
  ]
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01M6V9CSWMSNF57R0B23S0F1NP",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    asset_id: "ast_01M6V9CSVCMZFAP6ZN5WANZ6M8",
    title: "Replace the furnace filter",
    summary: "Swap the 16x25x1 filter. The arrow points toward the furnace.",
    why: "A clogged filter strains the blower and cuts airflow.",
    timing: {
      kind: "interval",
      every: 3,
      unit: "month",
    },
    importance: "essential",
    last_done_on: "2026-08-19",
    handled_by: "diy",
    assignee_person_id: "per_01M6V9CS744BQQH188FS6CXY9W",
    diy_steps: "Switch the furnace off. Slide out the old filter, slide in the new one, and write the date on the frame.",
    cost: {
      currency: "USD",
      diy_min: 1500,
      diy_max: 3000,
      basis: "A 4-pack lasts a year",
    },
    origin: "manufacturer",
    part_ids: [
      "prt_01M6V9CSWCCK3TQDA78RGRZ2E2",
    ],
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01M6V9CSWMSNF57R0B23S0F1NP

{
  "asset_id": "ast_01M6V9CSVCMZFAP6ZN5WANZ6M8",
  "title": "Replace the furnace filter",
  "summary": "Swap the 16x25x1 filter. The arrow points toward the furnace.",
  "why": "A clogged filter strains the blower and cuts airflow.",
  "timing": {
    "kind": "interval",
    "every": 3,
    "unit": "month"
  },
  "importance": "essential",
  "last_done_on": "2026-08-19",
  "handled_by": "diy",
  "assignee_person_id": "per_01M6V9CS744BQQH188FS6CXY9W",
  "diy_steps": "Switch the furnace off. Slide out the old filter, slide in the new one, and write the date on the frame.",
  "cost": {
    "currency": "USD",
    "diy_min": 1500,
    "diy_max": 3000,
    "basis": "A 4-pack lasts a year"
  },
  "origin": "manufacturer",
  "part_ids": [
    "prt_01M6V9CSWCCK3TQDA78RGRZ2E2"
  ]
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01M6V9CSWMTNY990N4Z2GQ47WH

{
  "result": {
    "task_id": "mtk_01M6V9CSWM1GKX8MAYQFYBAM3S",
    "completion_id": "mtc_01M6V9CSWM2KQTDJAY4PFXSQJB",
    "next_due_on": "2026-11-19"
  },
  "version": 195
}

Add a task a contractor handles

With no date given, the first one is spread 7 to 27 days out so tasks don't pile up.

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01M6V9CSWSEHT79BRRPJ565S3A' \
  -d '{
  "asset_id": "ast_01M6V9CSVCMZFAP6ZN5WANZ6M8",
  "title": "Annual furnace inspection",
  "summary": "A technician checks the burners, heat exchanger, flue and safety controls before heating season.",
  "timing": {
    "kind": "interval",
    "every": 1,
    "unit": "year"
  },
  "importance": "essential",
  "handled_by": "hire",
  "contractor_id": "ctr_01M6V9CSWEFJH8CRZCXNAH8109",
  "origin": "manufacturer"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01M6V9CSWSEHT79BRRPJ565S3A",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    asset_id: "ast_01M6V9CSVCMZFAP6ZN5WANZ6M8",
    title: "Annual furnace inspection",
    summary: "A technician checks the burners, heat exchanger, flue and safety controls before heating season.",
    timing: {
      kind: "interval",
      every: 1,
      unit: "year",
    },
    importance: "essential",
    handled_by: "hire",
    contractor_id: "ctr_01M6V9CSWEFJH8CRZCXNAH8109",
    origin: "manufacturer",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01M6V9CSWSEHT79BRRPJ565S3A

{
  "asset_id": "ast_01M6V9CSVCMZFAP6ZN5WANZ6M8",
  "title": "Annual furnace inspection",
  "summary": "A technician checks the burners, heat exchanger, flue and safety controls before heating season.",
  "timing": {
    "kind": "interval",
    "every": 1,
    "unit": "year"
  },
  "importance": "essential",
  "handled_by": "hire",
  "contractor_id": "ctr_01M6V9CSWEFJH8CRZCXNAH8109",
  "origin": "manufacturer"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01M6V9CSWSW4DBY31KNE2TVMXP

{
  "result": {
    "task_id": "mtk_01M6V9CSWSHKH0MYE1RMRRDC58",
    "completion_id": null,
    "next_due_on": "2026-11-17"
  },
  "version": 196
}

Add a task for a season

A task for the whole house leaves out the item and the place.

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01M6V9CSWXY271AQYJ5GYJ38KF' \
  -d '{
  "title": "Clean the gutters",
  "summary": "Scoop out the leaves once the maples drop them, then flush the downspouts.",
  "timing": {
    "kind": "seasonal",
    "start": "10-25",
    "end": "12-05",
    "reasoning": "After the maples drop their leaves and before the first hard freeze."
  },
  "importance": "recommended",
  "handled_by": "diy",
  "assignee_person_id": "per_01M6V9CS744BQQH188FS6CXY9W",
  "origin": "homeowner"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01M6V9CSWXY271AQYJ5GYJ38KF",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    title: "Clean the gutters",
    summary: "Scoop out the leaves once the maples drop them, then flush the downspouts.",
    timing: {
      kind: "seasonal",
      start: "10-25",
      end: "12-05",
      reasoning: "After the maples drop their leaves and before the first hard freeze.",
    },
    importance: "recommended",
    handled_by: "diy",
    assignee_person_id: "per_01M6V9CS744BQQH188FS6CXY9W",
    origin: "homeowner",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01M6V9CSWXY271AQYJ5GYJ38KF

{
  "title": "Clean the gutters",
  "summary": "Scoop out the leaves once the maples drop them, then flush the downspouts.",
  "timing": {
    "kind": "seasonal",
    "start": "10-25",
    "end": "12-05",
    "reasoning": "After the maples drop their leaves and before the first hard freeze."
  },
  "importance": "recommended",
  "handled_by": "diy",
  "assignee_person_id": "per_01M6V9CS744BQQH188FS6CXY9W",
  "origin": "homeowner"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01M6V9CSWX9M1E62K29K9Q0120

{
  "result": {
    "task_id": "mtk_01M6V9CSWXXCGQMAC702FF72JQ",
    "completion_id": null,
    "next_due_on": "2026-10-25"
  },
  "version": 197
}

Add a monthly task

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01M6V9CSX1HDG9YDF86QMEVCD3' \
  -d '{
  "asset_id": "ast_01M6V9CSVNY4PN710B9NWNSNVT",
  "title": "Test the smoke alarms",
  "summary": "Press the test button on every alarm and listen for the full-volume sound.",
  "timing": {
    "kind": "interval",
    "every": 1,
    "unit": "month"
  },
  "importance": "essential",
  "last_done_on": "2026-10-12",
  "handled_by": "diy",
  "assignee_person_id": "per_01M6V9CS6RX26JK5KVYGRN22D2",
  "origin": "general"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01M6V9CSX1HDG9YDF86QMEVCD3",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    asset_id: "ast_01M6V9CSVNY4PN710B9NWNSNVT",
    title: "Test the smoke alarms",
    summary: "Press the test button on every alarm and listen for the full-volume sound.",
    timing: {
      kind: "interval",
      every: 1,
      unit: "month",
    },
    importance: "essential",
    last_done_on: "2026-10-12",
    handled_by: "diy",
    assignee_person_id: "per_01M6V9CS6RX26JK5KVYGRN22D2",
    origin: "general",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01M6V9CSX1HDG9YDF86QMEVCD3

{
  "asset_id": "ast_01M6V9CSVNY4PN710B9NWNSNVT",
  "title": "Test the smoke alarms",
  "summary": "Press the test button on every alarm and listen for the full-volume sound.",
  "timing": {
    "kind": "interval",
    "every": 1,
    "unit": "month"
  },
  "importance": "essential",
  "last_done_on": "2026-10-12",
  "handled_by": "diy",
  "assignee_person_id": "per_01M6V9CS6RX26JK5KVYGRN22D2",
  "origin": "general"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01M6V9CSX12C8P9R1NG5NNHCJ8

{
  "result": {
    "task_id": "mtk_01M6V9CSX1RN5MWBHS4SJAK8F3",
    "completion_id": "mtc_01M6V9CSX1Z254GEHS7TMW39R2",
    "next_due_on": "2026-11-12"
  },
  "version": 198
}

Add a task that is already overdue

last_done_on counts the next due date from a day in the past, so it comes out overdue.

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01M6V9CSX59C20M4S2KQJ81EC2' \
  -d '{
  "asset_id": "ast_01M6V9CSVKPYARY331YY06WH85",
  "title": "Clean the dryer vent",
  "summary": "Pull the dryer out, brush the duct clear from both ends and vacuum the outside hood.",
  "why": "Lint in the vent is a fire risk and makes every load take longer.",
  "timing": {
    "kind": "interval",
    "every": 1,
    "unit": "year"
  },
  "importance": "essential",
  "last_done_on": "2025-10-23",
  "handled_by": "diy",
  "assignee_person_id": "per_01M6V9CS6RX26JK5KVYGRN22D2",
  "origin": "general"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01M6V9CSX59C20M4S2KQJ81EC2",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    asset_id: "ast_01M6V9CSVKPYARY331YY06WH85",
    title: "Clean the dryer vent",
    summary: "Pull the dryer out, brush the duct clear from both ends and vacuum the outside hood.",
    why: "Lint in the vent is a fire risk and makes every load take longer.",
    timing: {
      kind: "interval",
      every: 1,
      unit: "year",
    },
    importance: "essential",
    last_done_on: "2025-10-23",
    handled_by: "diy",
    assignee_person_id: "per_01M6V9CS6RX26JK5KVYGRN22D2",
    origin: "general",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01M6V9CSX59C20M4S2KQJ81EC2

{
  "asset_id": "ast_01M6V9CSVKPYARY331YY06WH85",
  "title": "Clean the dryer vent",
  "summary": "Pull the dryer out, brush the duct clear from both ends and vacuum the outside hood.",
  "why": "Lint in the vent is a fire risk and makes every load take longer.",
  "timing": {
    "kind": "interval",
    "every": 1,
    "unit": "year"
  },
  "importance": "essential",
  "last_done_on": "2025-10-23",
  "handled_by": "diy",
  "assignee_person_id": "per_01M6V9CS6RX26JK5KVYGRN22D2",
  "origin": "general"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01M6V9CSX5AYV6JAMNH0TFNSPE

{
  "result": {
    "task_id": "mtk_01M6V9CSX5S6WYB5HV2YGMA0FD",
    "completion_id": "mtc_01M6V9CSX5TBPSS2HVFEN2T3ZT",
    "next_due_on": "2026-10-23"
  },
  "version": 199
}

Add an optional task

Optional tasks never come due. They show on the item's page.

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/maintenance.task.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01M6V9CSX9DPB6WYKNZ4NBFJPP' \
  -d '{
  "asset_id": "ast_01M6V9CSVH77630WV0WA1X2DAK",
  "title": "Run a descaling cycle",
  "timing": {
    "kind": "interval",
    "every": 6,
    "unit": "month"
  },
  "importance": "optional",
  "handled_by": "diy",
  "origin": "general"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/maintenance.task.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01M6V9CSX9DPB6WYKNZ4NBFJPP",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    asset_id: "ast_01M6V9CSVH77630WV0WA1X2DAK",
    title: "Run a descaling cycle",
    timing: {
      kind: "interval",
      every: 6,
      unit: "month",
    },
    importance: "optional",
    handled_by: "diy",
    origin: "general",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/maintenance.task.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01M6V9CSX9DPB6WYKNZ4NBFJPP

{
  "asset_id": "ast_01M6V9CSVH77630WV0WA1X2DAK",
  "title": "Run a descaling cycle",
  "timing": {
    "kind": "interval",
    "every": 6,
    "unit": "month"
  },
  "importance": "optional",
  "handled_by": "diy",
  "origin": "general"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01M6V9CSX9THY5FJ3Y7AFHNQ9F

{
  "result": {
    "task_id": "mtk_01M6V9CSX9NQR7S63YXVAJ5EQV",
    "completion_id": null,
    "next_due_on": "2026-11-21"
  },
  "version": 200
}

For Rigel#

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