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#
| Field | Description |
|---|---|
household_idpathstringrequired | The household's ID. |
Idempotency-Keyheaderstringoptional | The command's ID. Reuse it when retrying the same command. |
Request body#
JSON, as application/json.
| Field | Description |
|---|---|
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 |
quantitynumber or nulloptional | How many, when said. Leave out when no amount was given. |
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. |
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.
| Field | Description |
|---|---|
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.
| Status | Code | When |
|---|---|---|
400 | validation_failed | A field is missing, misspelled or out of range. details.fields lists each problem. |
401 | unauthenticated | The request has no valid session. |
404 | product_not_found | An unknown product is refused. |
404 | person_not_found | An unknown person is refused. |
404 | not_found | The household doesn't exist, or you aren't a member of it. |
409 | idempotency_key_reused | The Idempotency-Key was already used for a different command. |
Examples#
These are real. Each scenario is one of the command's test cases, run on a household when this site was built, and the response is what the API returned.
A product by ID goes on the list with its amount, note and who it's for, added by the actor's person
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"
}'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();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"
}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
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"
}'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();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"
}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
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"
}'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();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"
}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
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"
}'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();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"
}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
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"
}'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();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"
}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
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"
}'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();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"
}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
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"
}'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();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"
}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
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"
}'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();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"
}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
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"
}'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();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"
}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
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"
}'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();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"
}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
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"
}'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();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"
}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
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"
}'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();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"
}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
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"
}'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();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"
}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
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"
}'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();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"
}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
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"
}'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();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"
}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
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"
}'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();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"
}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
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"
}'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();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"
}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
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"
}'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();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"
}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
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"
}'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();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"
}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.
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"
}'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();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"
}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.
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."
}'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();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."
}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.
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"
}'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();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"
}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.
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"
}'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();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"
}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.