{"openapi":"3.1.0","info":{"title":"Suplus API","version":"1.0.0","description":"Starter OpenAPI schema for Suplus assistant integrations."},"servers":[{"url":"https:\/\/suplus.cofficus.club\/api\/v1"}],"security":[{"bearerAuth":[]}],"paths":{"\/me":{"get":{"summary":"Get current API user","operationId":"getCurrentUser","responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"}}}},"\/search":{"get":{"summary":"Search accessible supplies, zones, and suppliers","operationId":"searchSuplus","description":"Search by object names or notes. For location questions such as \"what is in the freezer\", use zone results to find the matching zone id, then call listSupplies with zone_id.","parameters":[{"name":"q","in":"query","required":true,"description":"Search text.","schema":{"type":"string"}},{"name":"space_id","in":"query","required":false,"description":"Optional Space id filter.","schema":{"type":"integer"}},{"name":"limit","in":"query","required":false,"description":"Result limit from 1 to 50.","schema":{"type":"integer"}}],"responses":{"200":{"description":"Grouped search results.","content":{"application\/json":{"schema":{"type":"object","properties":{"query":{"type":"string"},"supplies":{"type":"array","items":{"$ref":"#\/components\/schemas\/Supply"}},"zones":{"type":"array","items":{"$ref":"#\/components\/schemas\/Zone"}},"suppliers":{"type":"array","items":{"$ref":"#\/components\/schemas\/Supplier"}}}}}}},"401":{"$ref":"#\/components\/responses\/Unauthorized"}}}},"\/spaces":{"get":{"summary":"List accessible spaces","operationId":"listSpaces","responses":{"200":{"description":"Accessible spaces. Use the returned id field for later space path parameters.","content":{"application\/json":{"schema":{"type":"array","items":{"$ref":"#\/components\/schemas\/SpaceSummary"}}}}},"401":{"$ref":"#\/components\/responses\/Unauthorized"}}},"post":{"summary":"Create a space","operationId":"createSpace","requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"kind":{"$ref":"#\/components\/schemas\/SpaceKind"}},"required":["name"]}}}},"responses":{"201":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"422":{"$ref":"#\/components\/responses\/ValidationError"}}}},"\/spaces\/{space}":{"get":{"summary":"Get one accessible space","operationId":"getSpace","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Do not use a space name or list position.","schema":{"type":"integer"}}],"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"}}},"patch":{"summary":"Rename or edit a space","operationId":"updateSpace","description":"Owner-only action.","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Requires owner access.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"kind":{"$ref":"#\/components\/schemas\/SpaceKind"}},"required":["name"]}}}},"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"},"422":{"$ref":"#\/components\/responses\/ValidationError"}}},"delete":{"summary":"Delete a space","operationId":"deleteSpace","description":"Owner-only destructive action. The assistant must ask for explicit confirmation before calling this operation.","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Requires owner access.","schema":{"type":"integer"}}],"responses":{"204":{"$ref":"#\/components\/responses\/NoContent"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"}}}},"\/spaces\/{space}\/rooms":{"get":{"summary":"List rooms in a space","operationId":"listRooms","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Do not use a space name or list position.","schema":{"type":"integer"}}],"responses":{"200":{"description":"Rooms in the selected space. Use the returned id field for later room path parameters.","content":{"application\/json":{"schema":{"type":"array","items":{"$ref":"#\/components\/schemas\/Room"}}}}},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"}}},"post":{"summary":"Create a room in a space","operationId":"createRoom","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Requires owner or full access.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"sort_order":{"type":["integer","null"]}},"required":["name"]}}}},"responses":{"201":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"422":{"$ref":"#\/components\/responses\/ValidationError"}}}},"\/spaces\/{space}\/rooms\/{room}":{"patch":{"summary":"Rename or reorder a room","operationId":"updateRoom","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Requires owner or full access.","schema":{"type":"integer"}},{"name":"room","in":"path","required":true,"description":"Numeric Room id from listRooms. Do not use a room name or list position.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"sort_order":{"type":["integer","null"]}}}}}},"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"},"422":{"$ref":"#\/components\/responses\/ValidationError"}}},"delete":{"summary":"Delete a room","operationId":"deleteRoom","description":"Destructive action. The assistant must ask for explicit confirmation before calling this operation. The system unsorted room cannot be deleted.","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Requires owner or full access.","schema":{"type":"integer"}},{"name":"room","in":"path","required":true,"description":"Numeric Room id from listRooms. Do not use a room name or list position.","schema":{"type":"integer"}}],"responses":{"204":{"$ref":"#\/components\/responses\/NoContent"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"},"422":{"$ref":"#\/components\/responses\/ValidationError"}}}},"\/spaces\/{space}\/rooms\/{room}\/zones":{"get":{"summary":"List zones in a room","operationId":"listZones","description":"Returns storage zones in a room. For questions about what is inside a named zone, use the returned zone id as listSupplies zone_id.","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Do not use a space name or list position.","schema":{"type":"integer"}},{"name":"room","in":"path","required":true,"description":"Numeric Room id from listRooms. Do not use a room name or list position.","schema":{"type":"integer"}}],"responses":{"200":{"description":"Zones in the selected room.","content":{"application\/json":{"schema":{"type":"array","items":{"$ref":"#\/components\/schemas\/Zone"}}}}},"401":{"$ref":"#\/components\/responses\/Unauthorized"}}},"post":{"summary":"Create a zone in a room","operationId":"createZone","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Requires owner or full access.","schema":{"type":"integer"}},{"name":"room","in":"path","required":true,"description":"Numeric Room id from listRooms. Do not use a room name or list position.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"name":{"type":"string"}},"required":["name"]}}}},"responses":{"201":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"},"422":{"$ref":"#\/components\/responses\/ValidationError"}}}},"\/rooms\/{room}\/zones\/{zone}":{"patch":{"summary":"Rename a zone","operationId":"updateZone","parameters":[{"name":"room","in":"path","required":true,"description":"Numeric Room id from listRooms. Requires owner or full access.","schema":{"type":"integer"}},{"name":"zone","in":"path","required":true,"description":"Numeric Zone id from listZones. Do not use a zone name or list position.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"name":{"type":"string"}},"required":["name"]}}}},"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"},"422":{"$ref":"#\/components\/responses\/ValidationError"}}},"delete":{"summary":"Delete a zone","operationId":"deleteZone","description":"Destructive action. The assistant must ask for explicit confirmation before calling this operation.","parameters":[{"name":"room","in":"path","required":true,"description":"Numeric Room id from listRooms. Requires owner or full access.","schema":{"type":"integer"}},{"name":"zone","in":"path","required":true,"description":"Numeric Zone id from listZones. Do not use a zone name or list position.","schema":{"type":"integer"}}],"responses":{"204":{"$ref":"#\/components\/responses\/NoContent"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"}}}},"\/spaces\/{space}\/supplies":{"get":{"summary":"List supplies in a space","operationId":"listSupplies","description":"Lists supplies and supports room_id and zone_id filters. Use this for \"what is in this room\/zone\" questions after resolving the room or zone id.","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Do not use a space name or list position.","schema":{"type":"integer"}},{"name":"q","in":"query","required":false,"description":"Optional supply name or note filter.","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"Optional comma-separated statuses: ok, low, out, ordered.","schema":{"type":"string"}},{"name":"room_id","in":"query","required":false,"description":"Optional Room id filter from listRooms.","schema":{"type":"integer"}},{"name":"zone_id","in":"query","required":false,"description":"Optional Zone id filter from listZones. Use null only in request bodies, not query strings.","schema":{"type":"integer"}},{"name":"supplier_id","in":"query","required":false,"description":"Optional Supplier id filter from searchSuplus supplier results.","schema":{"type":"integer"}},{"name":"limit","in":"query","required":false,"description":"Result limit from 1 to 200.","schema":{"type":"integer"}}],"responses":{"200":{"description":"Supplies matching the selected filters.","content":{"application\/json":{"schema":{"type":"array","items":{"$ref":"#\/components\/schemas\/Supply"}}}}},"401":{"$ref":"#\/components\/responses\/Unauthorized"}}}},"\/spaces\/{space}\/rooms\/{room}\/supplies":{"get":{"summary":"List supplies in a room","operationId":"listRoomSupplies","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Do not use a space name or list position.","schema":{"type":"integer"}},{"name":"room","in":"path","required":true,"description":"Numeric Room id from listRooms. Do not use a room name or list position.","schema":{"type":"integer"}}],"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"}}},"post":{"summary":"Create a supply in a room","operationId":"createSupply","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Requires owner or full access.","schema":{"type":"integer"}},{"name":"room","in":"path","required":true,"description":"Numeric Room id from listRooms. Do not use a room name or list position.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"status":{"$ref":"#\/components\/schemas\/SupplyStatus"},"zone_id":{"type":["integer","null"],"description":"Optional Zone id from listZones in the same room."},"note":{"type":["string","null"]},"stores":{"type":"array","items":{"$ref":"#\/components\/schemas\/SupplyStoreInput"}}},"required":["name","status"]}}}},"responses":{"201":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"},"422":{"$ref":"#\/components\/responses\/ValidationError"}}}},"\/supplies\/{supply}":{"get":{"summary":"Get one supply","operationId":"getSupply","parameters":[{"name":"supply","in":"path","required":true,"description":"Numeric Supply id from searchSuplus or listSupplies.","schema":{"type":"integer"}}],"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"}}},"patch":{"summary":"Rename or edit a supply","operationId":"updateSupply","parameters":[{"name":"supply","in":"path","required":true,"description":"Numeric Supply id from searchSuplus or listSupplies. Requires owner or full access.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"status":{"$ref":"#\/components\/schemas\/SupplyStatus"},"room_id":{"type":"integer","description":"Optional target Room id in the same space."},"zone_id":{"type":["integer","null"],"description":"Optional target Zone id in the target room, or null for no zone."},"note":{"type":["string","null"]},"stores":{"type":"array","items":{"$ref":"#\/components\/schemas\/SupplyStoreInput"}}}}}}},"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"},"422":{"$ref":"#\/components\/responses\/ValidationError"}}},"delete":{"summary":"Delete a supply","operationId":"deleteSupply","description":"Destructive action. The assistant must ask for explicit confirmation before calling this operation.","parameters":[{"name":"supply","in":"path","required":true,"description":"Numeric Supply id from searchSuplus or listSupplies. Requires owner or full access.","schema":{"type":"integer"}}],"responses":{"204":{"$ref":"#\/components\/responses\/NoContent"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"}}}},"\/supplies\/{supply}\/status":{"patch":{"summary":"Update a supply status","operationId":"updateSupplyStatus","parameters":[{"name":"supply","in":"path","required":true,"description":"Supply id.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"$ref":"#\/components\/schemas\/SupplyStatus"}}}}}},"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"}}}},"\/supplies\/{supply}\/move":{"patch":{"summary":"Move a supply to another room or zone in the same space","operationId":"moveSupply","parameters":[{"name":"supply","in":"path","required":true,"description":"Numeric Supply id from searchSuplus or listSupplies. Requires owner or full access.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"room_id":{"type":"integer","description":"Target Room id in the same space."},"zone_id":{"type":["integer","null"],"description":"Target Zone id in the target room, or null for no zone."}},"required":["room_id"]}}}},"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"},"422":{"$ref":"#\/components\/responses\/ValidationError"}}}},"\/spaces\/{space}\/suppliers":{"get":{"summary":"List suppliers in a space","operationId":"listSuppliers","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Do not use a space name or list position.","schema":{"type":"integer"}}],"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"}}},"post":{"summary":"Create a supplier","operationId":"createSupplier","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Requires owner or full access.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":["string","null"],"format":"uri"},"address":{"type":["string","null"]},"phone":{"type":["string","null"]},"categories":{"type":"array","items":{"type":"string"}},"note":{"type":["string","null"]}},"required":["name"]}}}},"responses":{"201":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"422":{"$ref":"#\/components\/responses\/ValidationError"}}}},"\/spaces\/{space}\/suppliers\/{supplier}":{"get":{"summary":"Get one supplier","operationId":"getSupplier","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Do not use a space name or list position.","schema":{"type":"integer"}},{"name":"supplier","in":"path","required":true,"description":"Numeric Supplier id from listSuppliers or searchSuplus.","schema":{"type":"integer"}}],"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"}}},"patch":{"summary":"Edit a supplier","operationId":"updateSupplier","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Requires owner or full access.","schema":{"type":"integer"}},{"name":"supplier","in":"path","required":true,"description":"Numeric Supplier id from listSuppliers or searchSuplus.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":["string","null"],"format":"uri"},"address":{"type":["string","null"]},"phone":{"type":["string","null"]},"categories":{"type":"array","items":{"type":"string"}},"note":{"type":["string","null"]}}}}}},"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"},"422":{"$ref":"#\/components\/responses\/ValidationError"}}},"delete":{"summary":"Delete a supplier","operationId":"deleteSupplier","description":"Destructive action. The assistant must ask for explicit confirmation before calling this operation.","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Requires owner or full access.","schema":{"type":"integer"}},{"name":"supplier","in":"path","required":true,"description":"Numeric Supplier id from listSuppliers or searchSuplus.","schema":{"type":"integer"}}],"responses":{"204":{"$ref":"#\/components\/responses\/NoContent"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"}}}},"\/spaces\/{space}\/members":{"get":{"summary":"List space owner and members","operationId":"listSpaceMembers","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces.","schema":{"type":"integer"}}],"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"}}}},"\/spaces\/{space}\/members\/{membership}":{"patch":{"summary":"Change a member access level","operationId":"updateSpaceMember","description":"Owner-only action.","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Requires owner access.","schema":{"type":"integer"}},{"name":"membership","in":"path","required":true,"description":"Numeric membership id from listSpaceMembers.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"access_level":{"$ref":"#\/components\/schemas\/AccessLevel"}},"required":["access_level"]}}}},"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"},"422":{"$ref":"#\/components\/responses\/ValidationError"}}},"delete":{"summary":"Remove a member from a space","operationId":"deleteSpaceMember","description":"Owner-only destructive action. The assistant must ask for explicit confirmation before calling this operation.","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Requires owner access.","schema":{"type":"integer"}},{"name":"membership","in":"path","required":true,"description":"Numeric membership id from listSpaceMembers.","schema":{"type":"integer"}}],"responses":{"204":{"$ref":"#\/components\/responses\/NoContent"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"}}}},"\/spaces\/{space}\/invitations":{"get":{"summary":"List invitations sent for a space","operationId":"listSpaceInvitations","description":"Owner-only action.","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Requires owner access.","schema":{"type":"integer"}}],"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"}}},"post":{"summary":"Invite a member by email","operationId":"createSpaceInvitation","description":"Owner-only action. Sends an email invitation.","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Requires owner access.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"access_level":{"$ref":"#\/components\/schemas\/AccessLevel"}},"required":["email","access_level"]}}}},"responses":{"201":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"422":{"$ref":"#\/components\/responses\/ValidationError"}}}},"\/spaces\/{space}\/invitations\/{invitation}\/resend":{"post":{"summary":"Resend an invitation","operationId":"resendSpaceInvitation","description":"Owner-only action. Sends another email invitation.","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Requires owner access.","schema":{"type":"integer"}},{"name":"invitation","in":"path","required":true,"description":"Numeric invitation id from listSpaceInvitations.","schema":{"type":"integer"}}],"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"}}}},"\/spaces\/{space}\/invitations\/{invitation}":{"delete":{"summary":"Cancel an invitation","operationId":"deleteSpaceInvitation","description":"Owner-only destructive action. The assistant must ask for explicit confirmation before calling this operation.","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Requires owner access.","schema":{"type":"integer"}},{"name":"invitation","in":"path","required":true,"description":"Numeric invitation id from listSpaceInvitations.","schema":{"type":"integer"}}],"responses":{"204":{"$ref":"#\/components\/responses\/NoContent"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"}}}},"\/spaces\/{space}\/shopping-list":{"get":{"summary":"Get active shopping list","operationId":"getShoppingList","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Do not use a space name or list position.","schema":{"type":"integer"}}],"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"}}},"post":{"summary":"Add an item to the shopping list","operationId":"addShoppingListEntry","description":"If supply_id is provided, the existing supply is marked low when needed. Otherwise a one-off purchase is created.","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Do not use a space name or list position.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"supply_id":{"type":["integer","null"]},"name":{"type":["string","null"]},"note":{"type":["string","null"]},"status":{"$ref":"#\/components\/schemas\/ManualShoppingStatus"},"supplier_id":{"type":["integer","null"]}}}}}},"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"201":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"422":{"$ref":"#\/components\/responses\/ValidationError"}}}},"\/spaces\/{space}\/manual-shopping-entries":{"get":{"summary":"List manual shopping entries","operationId":"listManualShoppingEntries","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Do not use a space name or list position.","schema":{"type":"integer"}}],"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"}}},"post":{"summary":"Create a one-off purchase","operationId":"createOneOffPurchase","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Do not use a space name or list position.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"note":{"type":["string","null"]},"supplier_id":{"type":["integer","null"]}}}}}},"responses":{"201":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"}}}},"\/spaces\/{space}\/manual-shopping-entries\/{manualShoppingEntry}":{"get":{"summary":"Get one manual shopping entry","operationId":"getManualShoppingEntry","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces.","schema":{"type":"integer"}},{"name":"manualShoppingEntry","in":"path","required":true,"description":"Numeric manual shopping entry id from listManualShoppingEntries or getShoppingList.","schema":{"type":"integer"}}],"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"}}},"patch":{"summary":"Edit a manual shopping entry","operationId":"updateManualShoppingEntry","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces.","schema":{"type":"integer"}},{"name":"manualShoppingEntry","in":"path","required":true,"description":"Numeric manual shopping entry id from listManualShoppingEntries or getShoppingList.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"note":{"type":["string","null"]},"status":{"$ref":"#\/components\/schemas\/ManualShoppingStatus"},"supplier_id":{"type":["integer","null"]}}}}}},"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"},"422":{"$ref":"#\/components\/responses\/ValidationError"}}},"delete":{"summary":"Delete a manual shopping entry","operationId":"deleteManualShoppingEntry","description":"Destructive action. The assistant must ask for explicit confirmation before calling this operation.","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces.","schema":{"type":"integer"}},{"name":"manualShoppingEntry","in":"path","required":true,"description":"Numeric manual shopping entry id from listManualShoppingEntries or getShoppingList.","schema":{"type":"integer"}}],"responses":{"204":{"$ref":"#\/components\/responses\/NoContent"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"}}}},"\/spaces\/{space}\/manual-shopping-entries\/{manualShoppingEntry}\/ordered":{"patch":{"summary":"Mark a manual shopping entry ordered","operationId":"orderManualShoppingEntry","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces.","schema":{"type":"integer"}},{"name":"manualShoppingEntry","in":"path","required":true,"description":"Numeric manual shopping entry id from listManualShoppingEntries or getShoppingList.","schema":{"type":"integer"}}],"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"}}}},"\/spaces\/{space}\/manual-shopping-entries\/{manualShoppingEntry}\/completed":{"patch":{"summary":"Mark a manual shopping entry completed","operationId":"completeManualShoppingEntry","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces.","schema":{"type":"integer"}},{"name":"manualShoppingEntry","in":"path","required":true,"description":"Numeric manual shopping entry id from listManualShoppingEntries or getShoppingList.","schema":{"type":"integer"}}],"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"}}}},"\/spaces\/{space}\/manual-shopping-entries\/{manualShoppingEntry}\/repeat":{"patch":{"summary":"Repeat a manual shopping entry","operationId":"repeatManualShoppingEntry","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces.","schema":{"type":"integer"}},{"name":"manualShoppingEntry","in":"path","required":true,"description":"Numeric manual shopping entry id from listManualShoppingEntries or getShoppingList.","schema":{"type":"integer"}}],"responses":{"200":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"}}}},"\/spaces\/{space}\/manual-shopping-entries\/{manualShoppingEntry}\/regular":{"post":{"summary":"Convert a manual shopping entry to a regular supply","operationId":"convertManualShoppingEntryToSupply","parameters":[{"name":"space","in":"path","required":true,"description":"Numeric Space id from listSpaces. Requires owner or full access.","schema":{"type":"integer"}},{"name":"manualShoppingEntry","in":"path","required":true,"description":"Numeric manual shopping entry id from listManualShoppingEntries or getShoppingList.","schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"room_id":{"type":"integer"},"zone_id":{"type":["integer","null"]},"zone_name":{"type":["string","null"]}},"required":["room_id"]}}}},"responses":{"201":{"$ref":"#\/components\/responses\/Ok"},"401":{"$ref":"#\/components\/responses\/Unauthorized"},"403":{"$ref":"#\/components\/responses\/Forbidden"},"404":{"$ref":"#\/components\/responses\/NotFound"},"422":{"$ref":"#\/components\/responses\/ValidationError"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"responses":{"Ok":{"description":"Successful response."},"NoContent":{"description":"Successful empty response."},"Unauthorized":{"description":"Missing, expired, or invalid authentication.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"}}}},"Forbidden":{"description":"The authenticated user cannot perform this action.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"}}}},"NotFound":{"description":"Resource was not found or is not accessible.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"}}}},"RateLimited":{"description":"Too many requests.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ApiError"}}}},"ValidationError":{"description":"The request body or parameters are invalid.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ValidationApiError"}}}}},"schemas":{"SpaceKind":{"type":"string","enum":["home","workspace","hobby"]},"AccessLevel":{"type":"string","enum":["full","limited"]},"ManualShoppingStatus":{"type":"string","enum":["new","ordered","completed"]},"SpaceSummary":{"type":"object","required":["id","name","kind","current_user_access"],"properties":{"id":{"type":"integer","description":"Database id. Use this exact value as the space path parameter."},"name":{"type":"string"},"kind":{"type":"string","enum":["home","workspace","hobby"]},"owner_id":{"type":"integer"},"current_user_access":{"type":"string","enum":["owner","full","limited"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"Room":{"type":"object","required":["id","space_id","name"],"properties":{"id":{"type":"integer","description":"Database id. Use this exact value as the room path parameter."},"space_id":{"type":"integer"},"name":{"type":"string"},"sort_order":{"type":["integer","null"]},"is_default":{"type":"boolean"},"is_unsorted":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"SupplyStatus":{"type":"string","enum":["ok","low","out","ordered"]},"Supply":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"status":{"$ref":"#\/components\/schemas\/SupplyStatus"},"room_id":{"type":"integer"},"zone_id":{"type":["integer","null"]},"note":{"type":["string","null"]},"room":{"$ref":"#\/components\/schemas\/Room"},"zone":{"anyOf":[{"$ref":"#\/components\/schemas\/Zone"},{"type":"null"}]}}},"Zone":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"room_id":{"type":"integer"},"sort_order":{"type":["integer","null"]},"room":{"$ref":"#\/components\/schemas\/Room"}}},"Supplier":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"space_id":{"type":"integer"}}},"SupplyStoreInput":{"type":"object","properties":{"supplier_id":{"type":["integer","null"]},"name":{"type":["string","null"]},"url":{"type":["string","null"],"format":"uri"}}},"ApiError":{"type":"object","required":["message","code","details"],"properties":{"message":{"type":"string"},"code":{"type":"string"},"details":{"type":"object"}}},"ValidationApiError":{"type":"object","required":["message","code","errors"],"properties":{"message":{"type":"string"},"code":{"type":"string","enum":["validation_failed"]},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}}}}}