Skip to content
Rigel docs
Open Rigel

Put something on the shopping list

shopping.item.add

POST/api/v1/households/{household_id}/commands/shopping.item.add

  • Command
  • Rigel runs it
  • Applies offline

Adds a product to the household's shared shopping list. Name the product by product_id, or by product_name to use the existing product with that name (ignoring case) or make a new one; search with inventory.product.search first so you reuse the right one. If the product is already on the list and not yet checked off, nothing is duplicated: the amounts add when the units match (otherwise the new amount goes in the note as 'also 2 lb'), a new note is appended, and a person it's for is filled in or added to the note. Give meal_id when it's for a meal on the plan, and recipe_id when it's for a recipe; the item then shows them, and an item can be for several. Records who added it. Returns the list item and whether it merged into an existing one.

Parameters#

Put something on the shopping list: 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.

Put something on the shopping list: request body fields
FieldDescription
product_idstringoptional

The product, when you know its ID. Give this or product_name.

product_namestringoptional

The product's name, when you don't have its ID: an existing product with this name (ignoring case) is used, or a new one is made. Search with inventory.product.search first so you reuse the right one.

1 to 120 characters
quantitynumber or nulloptional

How many, when said. Leave out when no amount was given.

greater than 0, at most 1,000,000
unitone of: mg, g, kg, oz, lb, ml, l, tsp, tbsp, fl_oz, cup, pint, quart, gallon, pinch, dash, clove, slice, stick, sprig, head, bunch, stalk, can, jar, bottle, box, bag, package, carton, roll, null or nulloptional

A unit. Mass: mg, g, kg, oz, lb. Volume (US sizes): ml, l, tsp, tbsp, fl_oz, cup, pint, quart, gallon. Items, for a count of something other than the thing itself (2 cloves of garlic, 1 can of beans): pinch, dash, clove, slice, stick, sprig, head, bunch, stalk, can, jar, bottle, box, bag, package, carton, roll. Leave it out or null for a plain count of the things themselves (3 eggs).

notestring or nulloptional

A note for whoever shops: "plain", "the big bag". Name a meal or recipe with meal_id or recipe_id, not here, as written, 1–500 characters.

at most 500 characters
for_person_idstring or nulloptional

Who it's for, when someone said it's for a person in the family.

meal_idstring or nulloptional

The planned meal it's for, from the meal plan, so the list shows the meal and follows it if it moves. For something several meals need, add it once per meal.

recipe_idstring or nulloptional

The recipe it's for, when it comes from a recipe's ingredients, so the list can say so. For something several recipes need, add it once per recipe.

Response#

200 The command was applied.

Put something on the shopping list: response fields
FieldDescription
resultobjectrequired

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

result.item_idstringrequired

The list item: the new one, or the one already on the list that this was added to.

result.product_idstringrequired

The product it's for.

result.mergedbooleanrequired

True when the product was already on the list and this was added to that item.

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.

Put something on the shopping list: errors
StatusCodeWhen
400validation_failedA field is missing, misspelled or out of range. details.fields lists each problem.
401unauthenticatedThe request has no valid session.
404product_not_foundAn unknown product is refused.
404person_not_foundAn unknown person is refused.
404not_foundThe household doesn't exist, or you aren't a member of it.
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 product by ID goes on the list with its amount, note and who it's for, added by the actor's person

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "product_id": "prd_01JC000000000000000000000A",
  "quantity": 2,
  "unit": "gallon",
  "note": "whole",
  "for_person_id": "per_01JC000000000000000000000B"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    product_id: "prd_01JC000000000000000000000A",
    quantity: 2,
    unit: "gallon",
    note: "whole",
    for_person_id: "per_01JC000000000000000000000B",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "product_id": "prd_01JC000000000000000000000A",
  "quantity": 2,
  "unit": "gallon",
  "note": "whole",
  "for_person_id": "per_01JC000000000000000000000B"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R07ZVZAYRWDYR13DF3

{
  "result": {
    "item_id": "shi_01JC4N0000MBGE5RJ6Q7V6V6T8",
    "product_id": "prd_01JC000000000000000000000A",
    "merged": false
  },
  "version": 1
}

A new product name makes the product and the item, with IDs derived from the command

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

{
  "product_name": "Greek yogurt",
  "note": "plain"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R044NFC1TBGB7VRRSG

{
  "result": {
    "item_id": "shi_01JC4N0000VGW1STJ6TGXRB7FY",
    "product_id": "prd_01JC4N0000MBGE5RJ6Q7V6V6T8",
    "merged": false
  },
  "version": 1
}

A product name matches an existing product ignoring case

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

{
  "product_name": "mILK"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0HZ28KZVC8ZK06TX3

{
  "result": {
    "item_id": "shi_01JC4N0000MBGE5RJ6Q7V6V6T8",
    "product_id": "prd_01JC000000000000000000000A",
    "merged": false
  },
  "version": 1
}

Adding a product already on the list adds the amounts when the units match

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "product_id": "prd_01JC000000000000000000000A",
  "quantity": 1,
  "unit": "gallon"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    product_id: "prd_01JC000000000000000000000A",
    quantity: 1,
    unit: "gallon",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "product_id": "prd_01JC000000000000000000000A",
  "quantity": 1,
  "unit": "gallon"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0F4R4M9ENQ2381SJM

{
  "result": {
    "item_id": "shi_01JC0000000000000000000001",
    "product_id": "prd_01JC000000000000000000000A",
    "merged": true
  },
  "version": 1
}

Units that convert add in the item's unit

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "product_id": "prd_01JC000000000000000000000A",
  "quantity": 8,
  "unit": "oz"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    product_id: "prd_01JC000000000000000000000A",
    quantity: 8,
    unit: "oz",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "product_id": "prd_01JC000000000000000000000A",
  "quantity": 8,
  "unit": "oz"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R06QFR66J3BK5N4WK6

{
  "result": {
    "item_id": "shi_01JC0000000000000000000001",
    "product_id": "prd_01JC000000000000000000000A",
    "merged": true
  },
  "version": 1
}

An amount fills an item that had none

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "product_id": "prd_01JC000000000000000000000A",
  "quantity": 2,
  "unit": "l"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    product_id: "prd_01JC000000000000000000000A",
    quantity: 2,
    unit: "l",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "product_id": "prd_01JC000000000000000000000A",
  "quantity": 2,
  "unit": "l"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0HYBQ3T29EHA8JQJA

{
  "result": {
    "item_id": "shi_01JC0000000000000000000001",
    "product_id": "prd_01JC000000000000000000000A",
    "merged": true
  },
  "version": 1
}

Units that don't convert keep the amount and say 'also' in the note

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "product_id": "prd_01JC000000000000000000000A",
  "quantity": 1,
  "unit": "lb"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    product_id: "prd_01JC000000000000000000000A",
    quantity: 1,
    unit: "lb",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "product_id": "prd_01JC000000000000000000000A",
  "quantity": 1,
  "unit": "lb"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R068N2W1RF55R8R6DH

{
  "result": {
    "item_id": "shi_01JC0000000000000000000001",
    "product_id": "prd_01JC000000000000000000000A",
    "merged": true
  },
  "version": 1
}

A count and a measured amount don't convert either

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "product_id": "prd_01JC000000000000000000000B",
  "quantity": 1,
  "unit": "box"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    product_id: "prd_01JC000000000000000000000B",
    quantity: 1,
    unit: "box",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "product_id": "prd_01JC000000000000000000000B",
  "quantity": 1,
  "unit": "box"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0G4T516YV55Q68JR0

{
  "result": {
    "item_id": "shi_01JC0000000000000000000001",
    "product_id": "prd_01JC000000000000000000000B",
    "merged": true
  },
  "version": 1
}

A new note is appended after a semicolon

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "product_id": "prd_01JC000000000000000000000A",
  "note": "the big one"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    product_id: "prd_01JC000000000000000000000A",
    note: "the big one",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "product_id": "prd_01JC000000000000000000000A",
  "note": "the big one"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R06ZQCKDZKGE2AA635

{
  "result": {
    "item_id": "shi_01JC0000000000000000000001",
    "product_id": "prd_01JC000000000000000000000A",
    "merged": true
  },
  "version": 1
}

A note on an item with none becomes its note, and an empty 'for' is filled

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA' \
  -d '{
  "product_id": "prd_01JC000000000000000000000A",
  "note": "organic",
  "for_person_id": "per_01JC000000000000000000000B"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01JC4N0000AAAAAAAAAAAAAAAA",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    product_id: "prd_01JC000000000000000000000A",
    note: "organic",
    for_person_id: "per_01JC000000000000000000000B",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01K9BKKP003AHRZ6DMV29GQY5C/commands/shopping.item.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01JC4N0000AAAAAAAAAAAAAAAA

{
  "product_id": "prd_01JC000000000000000000000A",
  "note": "organic",
  "for_person_id": "per_01JC000000000000000000000B"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R07YF5AFQP9VX6FJK5

{
  "result": {
    "item_id": "shi_01JC0000000000000000000001",
    "product_id": "prd_01JC000000000000000000000A",
    "merged": true
  },
  "version": 1
}

A different person is appended to the note and the item keeps its own

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

{
  "product_id": "prd_01JC000000000000000000000A",
  "for_person_id": "per_01JC000000000000000000000B"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0FB8P8PKGA1T7DTQQ

{
  "result": {
    "item_id": "shi_01JC0000000000000000000001",
    "product_id": "prd_01JC000000000000000000000A",
    "merged": true
  },
  "version": 1
}

The same person changes nothing about who it's for

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

{
  "product_id": "prd_01JC000000000000000000000A",
  "for_person_id": "per_01JC000000000000000000000B"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0ZNMZDDCTFVRJ1QQ3

{
  "result": {
    "item_id": "shi_01JC0000000000000000000001",
    "product_id": "prd_01JC000000000000000000000A",
    "merged": true
  },
  "version": 1
}

Adding with nothing new writes no change but still reports the merge

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

{
  "product_id": "prd_01JC000000000000000000000A"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0XRK35A3QFTJK6C49

{
  "result": {
    "item_id": "shi_01JC0000000000000000000001",
    "product_id": "prd_01JC000000000000000000000A",
    "merged": true
  },
  "version": 1
}

The merge keeps who added the item

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

{
  "product_id": "prd_01JC000000000000000000000A",
  "note": "again"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0WQG80HJPFJKJDQKM

{
  "result": {
    "item_id": "shi_01JC0000000000000000000001",
    "product_id": "prd_01JC000000000000000000000A",
    "merged": true
  },
  "version": 1
}

A checked item for the product doesn't count: a new item is added beside it

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

{
  "product_id": "prd_01JC000000000000000000000A"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0TJ7AWCQ9NE5PY0PW

{
  "result": {
    "item_id": "shi_01JC4N0000MBGE5RJ6Q7V6V6T8",
    "product_id": "prd_01JC000000000000000000000A",
    "merged": false
  },
  "version": 1
}

A unit with no quantity is dropped

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

{
  "product_id": "prd_01JC000000000000000000000A",
  "unit": "gallon"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0G2C9XCTZAF6ZGFSE

{
  "result": {
    "item_id": "shi_01JC4N0000MBGE5RJ6Q7V6V6T8",
    "product_id": "prd_01JC000000000000000000000A",
    "merged": false
  },
  "version": 1
}

An actor with no person in the household adds with no added_by

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

{
  "product_id": "prd_01JC000000000000000000000A"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0RFR0T2Y7M151ESWD

{
  "result": {
    "item_id": "shi_01JC4N0000MBGE5RJ6Q7V6V6T8",
    "product_id": "prd_01JC000000000000000000000A",
    "merged": false
  },
  "version": 1
}

An unknown product is refused

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

{
  "product_id": "prd_01JC000000000000000000000Z"
}
Response, 404
HTTP/1.1 404 Not Found
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0YVMV6G6464E5S0HA

{
  "error": {
    "code": "product_not_found",
    "message": "That product isn't there any more. No changes were applied.",
    "details": {
      "product_id": "prd_01JC000000000000000000000Z"
    },
    "recovery": "Read the current state, then send a command that fits it.",
    "request_id": "req_01K9D9S2R0YVMV6G6464E5S0HA"
  }
}

An unknown person is refused

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

{
  "product_id": "prd_01JC000000000000000000000A",
  "for_person_id": "per_01JC000000000000000000000Z"
}
Response, 404
HTTP/1.1 404 Not Found
Content-Type: application/json
X-Request-Id: req_01K9D9S2R0AWCNF5NBSN7TGG7Y

{
  "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_01K9D9S2R0AWCNF5NBSN7TGG7Y"
  }
}

Put something on the shopping list

product_name uses the household's product of that name, or makes one.

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/shopping.item.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01M6V9CT7DN769DKN67J0Y2SHN' \
  -d '{
  "product_name": "Milk",
  "quantity": 1,
  "unit": "gallon"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/shopping.item.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01M6V9CT7DN769DKN67J0Y2SHN",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    product_name: "Milk",
    quantity: 1,
    unit: "gallon",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/shopping.item.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01M6V9CT7DN769DKN67J0Y2SHN

{
  "product_name": "Milk",
  "quantity": 1,
  "unit": "gallon"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01M6V9CT7D6F8GYTSE74T70XF1

{
  "result": {
    "item_id": "shi_01M6V9CT7DFWJ9QA55E2RH41NS",
    "product_id": "prd_01M6V9CSAWSAMCWTBQ2M7F80H9",
    "merged": false
  },
  "version": 274
}

Add something that is already on the list

Nothing is duplicated: the amounts add, the note is kept, and merged is true.

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/shopping.item.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01M6V9CT7F9CERB13EPCG330ZH' \
  -d '{
  "product_name": "milk",
  "quantity": 1,
  "unit": "gallon",
  "note": "Whole, for Theo."
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/shopping.item.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01M6V9CT7F9CERB13EPCG330ZH",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    product_name: "milk",
    quantity: 1,
    unit: "gallon",
    note: "Whole, for Theo.",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/shopping.item.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01M6V9CT7F9CERB13EPCG330ZH

{
  "product_name": "milk",
  "quantity": 1,
  "unit": "gallon",
  "note": "Whole, for Theo."
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01M6V9CT7FDC85PY9G9ZS6NG8Q

{
  "result": {
    "item_id": "shi_01M6V9CT7DFWJ9QA55E2RH41NS",
    "product_id": "prd_01M6V9CSAWSAMCWTBQ2M7F80H9",
    "merged": true
  },
  "version": 275
}

Add something for one person

for_person_id shows who it's for on the list.

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/shopping.item.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01M6V9CT7G4W655KWC40VGDVQ8' \
  -d '{
  "product_name": "Yogurt",
  "note": "Plain, the big tub.",
  "for_person_id": "per_01M6V9CS79TMYHDAM7FTA9ZK3Z"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/shopping.item.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01M6V9CT7G4W655KWC40VGDVQ8",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    product_name: "Yogurt",
    note: "Plain, the big tub.",
    for_person_id: "per_01M6V9CS79TMYHDAM7FTA9ZK3Z",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/shopping.item.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01M6V9CT7G4W655KWC40VGDVQ8

{
  "product_name": "Yogurt",
  "note": "Plain, the big tub.",
  "for_person_id": "per_01M6V9CS79TMYHDAM7FTA9ZK3Z"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01M6V9CT7GF3EM32TD3R80ATJC

{
  "result": {
    "item_id": "shi_01M6V9CT7GG3ZTVWXX33PWZ46G",
    "product_id": "prd_01M6V9CSB0DQFW5YBZYYMJ0A77",
    "merged": false
  },
  "version": 276
}

Add something for a meal

The item shows the meal and the recipe it's for. An item can be for several.

Request, curl
curl -X POST 'https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/shopping.item.add' \
  -H "Cookie: rigel_session=$RIGEL_SESSION" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: cmd_01M6V9CT7J3REWR9C3SSEXBDDT' \
  -d '{
  "product_name": "Crushed tomatoes",
  "quantity": 1,
  "unit": "can",
  "recipe_id": "rcp_01M6V9CSD8VZYF11AC568Y7QPZ",
  "meal_id": "mel_01M6V9CSFSFH4859KG4NM47HF2"
}'
Request, TypeScript
const response = await fetch("https://rigel.house/api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/shopping.item.add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "cmd_01M6V9CT7J3REWR9C3SSEXBDDT",
    Cookie: `rigel_session=${process.env.RIGEL_SESSION}`,
  },
  body: JSON.stringify({
    product_name: "Crushed tomatoes",
    quantity: 1,
    unit: "can",
    recipe_id: "rcp_01M6V9CSD8VZYF11AC568Y7QPZ",
    meal_id: "mel_01M6V9CSFSFH4859KG4NM47HF2",
  }),
});
const data = await response.json();
Request, HTTP
POST /api/v1/households/hh_01M6V9CS6GGVFCY7NAS8ZTQV95/commands/shopping.item.add HTTP/1.1
Host: rigel.house
Cookie: rigel_session=<your session>
Content-Type: application/json
Idempotency-Key: cmd_01M6V9CT7J3REWR9C3SSEXBDDT

{
  "product_name": "Crushed tomatoes",
  "quantity": 1,
  "unit": "can",
  "recipe_id": "rcp_01M6V9CSD8VZYF11AC568Y7QPZ",
  "meal_id": "mel_01M6V9CSFSFH4859KG4NM47HF2"
}
Response, 200
HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01M6V9CT7JV9RKC4KPJF5DJDCB

{
  "result": {
    "item_id": "shi_01M6V9CT7J9XGMH0J24WZ258T7",
    "product_id": "prd_01M6V9CT7JAMWHZXH2HJ4HMB3Y",
    "merged": false
  },
  "version": 277
}

For Rigel#

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