Control your Philips lights, Sonos speakers, Roborock vacuums and more with Port OS cloud.
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
Control connected devices and services, retrieve results, and capture camera snapshots. Discover the device with endpoint_query or the room with group_query. Copy its full id, message and optional routeId; use the documented payload for the declared message. Send a matching payload ({} for a command without fields). Preserve the account that returned the IDs and clarify ambiguous targets before writes. Most controls return status accepted: dispatch succeeded, but the physical outcome is unconfirmed. For result-returning commands, such as search, library pages and get-snapshot, set waitForResult=true. A correlated result returns status responded; snapshots also return image pixels and timeOfSample. Outbound declarations include events, so they do not guarantee that every command responds. For playback, volume and power, omit waitForResult and verify fresh state using endpoint_query or group_query with declared expand capabilities and forceDeviceAttributeQuery=true. Live music queue recipe for "set up a playlist and play it on my Sonos": build an active playback queue unless the customer also asks to save a reusable library playlist. This recipe is available to tools-only clients without resources/read or bundled skills. 1. Discover the Spotify library and the requested speaker or native group. On the library's declared media-search/search-media message, use payload {"query":"<artist or mood>","type":"track"} and waitForResult=true. Copy playable canonical track IDs from the returned tracks; do not invent IDs or pass a search phrase to playback. 2. Select the target route declaring media-queue, preferring the native Sonos route when available. Check its supportedMediaResources and maxItemsPerPlay. Send one play-queue message with payload {"mediaIds":["<returned track ID>","<returned track ID>"]} and the copied routeId. This starts a new ordered selection. play-queue has no queueVersion field; requiresQueueVersion applies only to add-to-queue. Do not emulate a queue with repeated single-track play-media commands. 3. Send get-queue with payload {} and waitForResult=true on the same target and route. queue-contents returns currentMediaId, upcoming mediaIds, complete and an optional queueVersion. complete=false is a limited window, not proof that other songs are absent. Read FRESH media-player observations with endpoint_query/group_query, expand=["media-player"] and forceDeviceAttributeQuery=true before claiming playback. 4. To add music without restarting, search for another track and send add-to-queue once with {"mediaId":"<returned track ID>"}. If requiresQueueVersion=true, first read get-queue and include its exact queueVersion in that append payload. Spotify Connect does not accept queueVersion; omit it there. Read the queue again after each append. A conflict or uncertain write requires inspection, never an automatic retry or replacement selection. No saved-playlist command is needed for this live-queue workflow. A failed search does not establish that the speaker stopped or the whole connection is unavailable. Preserve current playback, report the failed operation, and use fresh device observations for playback claims. Do not substitute remembered song names or invented IDs for returned playable tracks. The search payload type is lowercase "track", not the uppercase capability configuration label "TRACK". Room lighting scenes: use group_query with expand:["scene"] and forceDeviceAttributeQuery:true, select the requested native provider group/route, and inspect its declared messages. To recall an available scene, send scene/activate with {"sceneId":"<returned scene ID>"} on that group and route. To save a new scene, first set the requested member lighting states, then send its declared scene/create-scene with {"name":"<scene name>"} and waitForResult=true. This snapshots the group's current light settings; it does not activate the scene. Use the returned scene-created.sceneId for activate, and fresh-query available-scenes before repeating an uncertain create. After recall, verify each affected light's fresh power/brightness and supported color state; dispatch acceptance or a scene label alone does not prove every light changed. Never create or recall a scene on another room or provider route as a fallback. Use only capabilities and commands declared by the selected device or service. Examples of device classes and providers, subject to the connected integration's support: - Lights, switches and plugs: on/off and brightness (Philips Hue, Tuya, TP-Link). - Phones, tablets, laptops, wallets and trackers: locate or ring (Apple Find My, Tile). - Thermostats and temperature sensors: heat/cool settings; read ambient temperature with endpoint_query (Nest, Tuya, ecobee). - Cameras: request a declared get-snapshot command and inspect the returned pixels (Ring, Nest and other cameras). A snapshot is distinct from live video. - Connectivity and battery: check declared observations with endpoint_query for phones, watches, locks and other devices. - Smart locks and PINs: use declared lock and PIN commands (August, Yale, Ring, Seam). - Home appliances: supported controls and running-state observations (Samsung, LG, Xiaomi). - Robot vacuums: clean rooms and return to dock (Roomba, Roborock, Dreame). Send clean-room to the robot listing the room in controllableGroups with {"groupIds": [<group ID>]}. Bounded remote driving requires fresh visual feedback; cleaning is not navigation. - Speakers and announcements: supported speech and audio playback (Sonos, Alexa, Nest cameras). - TVs, remotes and media libraries: playback, volume, search and declared playlist operations (Spotify, Fire TV, YouTube, Chrome, TCL, Samsung, LG). - Files and photos: declared browse, download, upload, rename, move and delete commands (iCloud Photos, iCloud Drive, Google Drive, Outlook). download-file returns a URI; catalog presence alone does not establish upload support. - Litter robots and pet appliances: declared cleaning, waste and dispensing observations or controls. - Water sensors and sprinklers: declared water detection, watering state and controls. - Calendars and reminders: declared list, create, complete, reschedule and delete operations (iCloud Calendar and Reminders). Connected reminders are distinct from assistant-created scheduled tasks. Read the relevant bundled skill reference or portos://guides/index for unfamiliar workflows. File/reminder deletion and PIN changes modify account data. Inspect partial or uncertain writes before another action. result_timeout means unknown outcome: read state before considering a retry. MESSAGE_UNSUPPORTED or MESSAGE_AMBIGUOUS means nothing was sent; correct the message from discovery. An unreachable device rejected the command. Never automatically retry a state-changing command or claim success from conflicting observations. Use endpoint_manage/group_manage to change names, types, membership or merges.
Full Port OS endpoint ID (…/endpoints/…) from endpoint_query or group ID (…/endpoint-groups/…) from group_query.
Full message ID copied from the target's messages: <capability-interface-namespace>/messages/<message-name>, with an @<version> suffix only when the listed ID has one.
JSON object matching the message payload schema. Use {} for messages without fields.
Optional provider route ID copied from the target routes. Reuse it for pause, resume and volume after playing through that provider. It must belong to id and advertise the requested message. Without it, the route declaring the most interfaces is used, then the highest route ID.
Wait for one correlated, schema-validated result for commands that retrieve results, such as camera snapshots, media search or library pages, when outboundMessages are declared. Playback and volume commands do not return correlated results. For power and other response-less controls omit it, then read fresh state with endpoint_query.
Optional caller-provided correlation token.
The server marks this tool as destructive. Running it may delete or overwrite data on the server or in any account you connected with your headers.
Control connected devices and services, retrieve results, and capture camera snapshots. Discover the device with endpoint_query or the room with group_query. Copy its full id, message and optional routeId; use the documented payload for the declared message. Send a matching payload ({} for a command without fields). Preserve the account that returned the IDs and clarify ambiguous targets before writes. Most controls return status accepted: dispatch succeeded, but the physical outcome is unconfirmed. For result-returning commands, such as search, library pages and get-snapshot, set waitForResult=true. A correlated result returns status responded; snapshots also return image pixels and timeOfSample. Outbound declarations include events, so they do not guarantee that every command responds. For playback, volume and power, omit waitForResult and verify fresh state using endpoint_query or group_query with declared expand capabilities and forceDeviceAttributeQuery=true. Live music queue recipe for "set up a playlist and play it on my Sonos": build an active playback queue unless the customer also asks to save a reusable library playlist. This recipe is available to tools-only clients without resources/read or bundled skills. 1. Discover the Spotify library and the requested speaker or native group. On the library's declared media-search/search-media message, use payload {"query":"<artist or mood>","type":"track"} and waitForResult=true. Copy playable canonical track IDs from the returned tracks; do not invent IDs or pass a search phrase to playback. 2. Select the target route declaring media-queue, preferring the native Sonos route when available. Check its supportedMediaResources and maxItemsPerPlay. Send one play-queue message with payload {"mediaIds":["<returned track ID>","<returned track ID>"]} and the copied routeId. This starts a new ordered selection. play-queue has no queueVersion field; requiresQueueVersion applies only to add-to-queue. Do not emulate a queue with repeated single-track play-media commands. 3. Send get-queue with payload {} and waitForResult=true on the same target and route. queue-contents returns currentMediaId, upcoming mediaIds, complete and an optional queueVersion. complete=false is a limited window, not proof that other songs are absent. Read FRESH media-player observations with endpoint_query/group_query, expand=["media-player"] and forceDeviceAttributeQuery=true before claiming playback. 4. To add music without restarting, search for another track and send add-to-queue once with {"mediaId":"<returned track ID>"}. If requiresQueueVersion=true, first read get-queue and include its exact queueVersion in that append payload. Spotify Connect does not accept queueVersion; omit it there. Read the queue again after each append. A conflict or uncertain write requires inspection, never an automatic retry or replacement selection. No saved-playlist command is needed for this live-queue workflow. A failed search does not establish that the speaker stopped or the whole connection is unavailable. Preserve current playback, report the failed operation, and use fresh device observations for playback claims. Do not substitute remembered song names or invented IDs for returned playable tracks. The search payload type is lowercase "track", not the uppercase capability configuration label "TRACK". Room lighting scenes: use group_query with expand:["scene"] and forceDeviceAttributeQuery:true, select the requested native provider group/route, and inspect its declared messages. To recall an available scene, send scene/activate with {"sceneId":"<returned scene ID>"} on that group and route. To save a new scene, first set the requested member lighting states, then send its declared scene/create-scene with {"name":"<scene name>"} and waitForResult=true. This snapshots the group's current light settings; it does not activate the scene. Use the returned scene-created.sceneId for activate, and fresh-query available-scenes before repeating an uncertain create. After recall, verify each affected light's fresh power/brightness and supported color state; dispatch acceptance or a scene label alone does not prove every light changed. Never create or recall a scene on another room or provider route as a fallback. Use only capabilities and commands declared by the selected device or service. Examples of device classes and providers, subject to the connected integration's support: - Lights, switches and plugs: on/off and brightness (Philips Hue, Tuya, TP-Link). - Phones, tablets, laptops, wallets and trackers: locate or ring (Apple Find My, Tile). - Thermostats and temperature sensors: heat/cool settings; read ambient temperature with endpoint_query (Nest, Tuya, ecobee). - Cameras: request a declared get-snapshot command and inspect the returned pixels (Ring, Nest and other cameras). A snapshot is distinct from live video. - Connectivity and battery: check declared observations with endpoint_query for phones, watches, locks and other devices. - Smart locks and PINs: use declared lock and PIN commands (August, Yale, Ring, Seam). - Home appliances: supported controls and running-state observations (Samsung, LG, Xiaomi). - Robot vacuums: clean rooms and return to dock (Roomba, Roborock, Dreame). Send clean-room to the robot listing the room in controllableGroups with {"groupIds": [<group ID>]}. Bounded remote driving requires fresh visual feedback; cleaning is not navigation. - Speakers and announcements: supported speech and audio playback (Sonos, Alexa, Nest cameras). - TVs, remotes and media libraries: playback, volume, search and declared playlist operations (Spotify, Fire TV, YouTube, Chrome, TCL, Samsung, LG). - Files and photos: declared browse, download, upload, rename, move and delete commands (iCloud Photos, iCloud Drive, Google Drive, Outlook). download-file returns a URI; catalog presence alone does not establish upload support. - Litter robots and pet appliances: declared cleaning, waste and dispensing observations or controls. - Water sensors and sprinklers: declared water detection, watering state and controls. - Calendars and reminders: declared list, create, complete, reschedule and delete operations (iCloud Calendar and Reminders). Connected reminders are distinct from assistant-created scheduled tasks. Read the relevant bundled skill reference or portos://guides/index for unfamiliar workflows. File/reminder deletion and PIN changes modify account data. Inspect partial or uncertain writes before another action. result_timeout means unknown outcome: read state before considering a retry. MESSAGE_UNSUPPORTED or MESSAGE_AMBIGUOUS means nothing was sent; correct the message from discovery. An unreachable device rejected the command. Never automatically retry a state-changing command or claim success from conflicting observations. Use endpoint_manage/group_manage to change names, types, membership or merges.
| Argument | Type | Description |
|---|---|---|
| id* | string | Full Port OS endpoint ID (…/endpoints/…) from endpoint_query or group ID (…/endpoint-groups/…) from group_query. |
| message* | string | Full message ID copied from the target's messages: <capability-interface-namespace>/messages/<message-name>, with an @<version> suffix only when the listed ID has one. |
| payload* | object | JSON object matching the message payload schema. Use {} for messages without fields. |
| routeId | string | Optional provider route ID copied from the target routes. Reuse it for pause, resume and volume after playing through that provider. It must belong to id and advertise the requested message. Without it, the route declaring the most interfaces is used, then the highest route ID. |
| waitForResult | boolean | Wait for one correlated, schema-validated result for commands that retrieve results, such as camera snapshots, media search or library pages, when outboundMessages are declared. Playback and volume commands do not return correlated results. For power and other response-less controls omit it, then read fresh state with endpoint_query. |
| correlationToken | string | Optional caller-provided correlation token. |
{
"type": "object",
"required": [
"id",
"message",
"payload"
],
"properties": {
"id": {
"type": "string",
"description": "Full Port OS endpoint ID (…/endpoints/…) from endpoint_query or group ID (…/endpoint-groups/…) from group_query."
},
"message": {
"type": "string",
"description": "Full message ID copied from the target's messages: <capability-interface-namespace>/messages/<message-name>, with an @<version> suffix only when the listed ID has one."
},
"payload": {
"type": "object",
"properties": {},
"description": "JSON object matching the message payload schema. Use {} for messages without fields.",
"x-validation-kind": "MESSAGE_PAYLOAD"
},
"routeId": {
"type": "string",
"description": "Optional provider route ID copied from the target routes. Reuse it for pause, resume and volume after playing through that provider. It must belong to id and advertise the requested message. Without it, the route declaring the most interfaces is used, then the highest route ID."
},
"waitForResult": {
"type": "boolean",
"description": "Wait for one correlated, schema-validated result for commands that retrieve results, such as camera snapshots, media search or library pages, when outboundMessages are declared. Playback and volume commands do not return correlated results. For power and other response-less controls omit it, then read fresh state with endpoint_query."
},
"correlationToken": {
"type": "string",
"description": "Optional caller-provided correlation token."
}
},
"additionalProperties": false
}Manage the names, types and registry entries of your devices and connected services. Choose one operation: RENAME, SET_TYPE, SET_ENABLEMENT, MERGE_INTO, or DELETE. Use endpoint_query first and copy the full endpoint ID. Rename and type changes are durable across provider rediscovery. Disabled endpoints stay available for explicit metadata reads, but cannot receive messages; rediscovery preserves the disabled state. DELETE removes the registry entry, though a provider may rediscover it later. MERGE_INTO retains the source endpoint as disabled and moves supported references to the target; it does not create a source-ID alias, a simulator endpoint can merge only into a target without a simulator route (two simulator endpoints return 409 CONFLICT; disable or delete the duplicate instead), and the target's enablement remains in effect. Before MERGE_INTO or DELETE, identify the actual endpoint and explain the effect to the user; never assume two endpoints are duplicates because their names match. This tool changes registry metadata only and never performs physical control.
| Argument | Type | Description |
|---|---|---|
| name | string | New endpoint name; only for RENAME. |
| type | string | New ontological endpoint type; only for SET_TYPE. |
| mergeInto | string | Full target endpoint ID; only for MERGE_INTO. |
| operation* | string | |
| enablement | string | New endpoint enablement; only for SET_ENABLEMENT. |
Find connected devices and services, discover their controls, and read their state. Start with a focused name, room or category query; follow paginationContext.nextToken. Results include full IDs, device types, provider routes, capabilities and accepted message IDs. An endpoint is a device or connected service, including a filesystem or media library. Copy IDs verbatim into control. For a known device, use endpointId; inspect its declared capabilities, commands and outbound message IDs. Use group_query for rooms and endpoint_manage for requested inventory cleanup. To read state, set expand to the declared capabilities you need, for example ["power","connectivity"] or ["battery"]. expand adds observations; it does not discover more devices or send controls. Add forceDeviceAttributeQuery=true to refresh selected attributes from the provider; otherwise readings may come from cache. Only FRESH observations establish the current state. A FRESH value is the current state; a STALE value is the last known state, reported with its sampledAt and never as live or unknown (a forced read may refresh it). Errored, missing or invalid values are unknown, not OFF or a dead battery, and a STALE value alone must not support a safety claim such as locked or off. An attribute with error.code PROVIDER_NO_STATE (forced reads only) means the provider answered but has no value for it: state is unknown and retrying will not help until the provider reports one. FRESH UNREACHABLE means offline even if a power value is present; STALE UNREACHABLE is the last known connectivity. An ID-only lookup retrieves metadata without requesting fresh state. Supported discovery includes: - Lights, switches and plugs: select by name and power/brightness capabilities as well as type; a light may be typed SWITCH or PLUG. - Thermostats and sensors: read temperature-sensor for ambient temperature; a setpoint is not room temperature. Clarify indoor versus outdoor temperature when ambiguous. - Cameras, locks, appliances, vacuums, pet appliances, sprinklers and water sensors: inspect declared controls and observations. - Phones, Apple Watch and trackers: read battery, charging, connectivity or location capabilities; use control for a declared ring command. - Speakers, TVs and media services: discover playback, volume, search and playlist commands. Alexa devices may be VOICE_ASSISTANT. - Filesystems, photos, calendars and reminders: choose a concrete route-backed service, rather than a generic plugin catalog or an old unrouted record. Read portos://guides/index or the bundled Port OS skill references for device workflows. Keep the account with every ID; check relevant authorized accounts before reporting a device missing. Names alone do not prove identity. Preserve routeId for the chosen provider and establish identity before merging records. By default lists contain enabled devices; enablement=DISABLED selects disabled devices and enablement=* includes both. Exact endpointId lookup can read metadata regardless of enablement. With group:read, controllableGroups lists rooms a device can act on. Simulator state does not establish household device state.
Show Port OS devices with their supported controls. To show a device, always call this tool: the widget it opens is the device's UI, so never render a second card, map or controls for it; answer in a sentence or two. Uses the same selection, expansion and pagination arguments as endpoint_query. A single matching device opens its full view with now playing, transport, volume and other controls; several matches open only a list of names to choose from, so pass one full endpoint ID (or a query matching one device) to control a device. Showing a device does not start live video or send a control command. Pass primary to choose which card leads, one of the device's card ids (every result lists them as cardIds; an unknown id is rejected with the available ones). The device's usual card and every other card stay behind the details toggle. Examples: "what's the battery on the vacuum" -> primary battery; "turn the thermostat fan on" -> primary fan; "how open are the blinds" -> primary closure; "show me the camera on the roborock" -> primary camera. "where is my phone" or "show its location" -> primary location; "show the roborock's map" or "pick a room to clean" -> primary house-map. Every result already includes the cached readings of the cards it lists (cardIds), so you can answer without a second call; pass expand to choose different capabilities. primary refreshes that card's readings from the device, so the answer is current. Always state the value in words: a FRESH reading is current; a STALE reading is the last known value, so say it is last known and give its age.
| Argument | Type | Description |
|---|---|---|
| query | object | Optional field-first filter. Omit it to load full context; filter only when the account is large. Each key is a field or a combinator, and all keys of one object must match: {"name": {"like": "living"}, "type": {"in": ["LIGHT", "SWITCH"]}}. Combinators: {"and": [query, ...]}, {"or": [query, ...]}, {"not": query}. Text operators: eq (exact), in (any of a list), like (case-insensitive substring), lt and gt (lexical order). List operators: has (contains the exact value), like (some value contains the substring, case-insensitive). Fields: id (text) full endpoint ID; name (text) endpoint name; type (text) effective endpoint type, including customer overrides, such as LIGHT, SWITCH, PLUG or ROBOT_VACUUM; manufacturer (text) manufacturer name; model (text) model name; ownerId (text, eq only at the top level) principal whose endpoints to list; defaults to the caller; interfaces (list) full capability interface namespaces; messages (list) full message IDs the endpoint accepts; controllableGroups (list) IDs of groups the endpoint can act on, such as rooms a vacuum can clean (needs group:read). |
Organize rooms and device groups: create, rename, change members, enable, disable, merge or delete them. Create, delete, add/remove members, MOVE_MEMBER and rename default to providerSync BEST_EFFORT: send supported native group changes first, verify provider readback, then save Port OS intent. A provider failure falls back locally and is PARTIALLY_APPLIED. PORTOS_ONLY sends nothing; FAIL_ON_PROVIDER_ERROR fails customer intent if a required provider change fails, while retaining received provider facts. Native effects cannot be rolled back. Undeclared support is NOT_SUPPORTED with reason NOT_DECLARED and does not by itself make the result partial. OUTSIDE_PRINCIPAL means native changes are not attempted through another principal's account; the authorized Port OS change can still apply. Read group IDs and etags with group_query first. Every reference to one group in a batch uses the same starting etag. MOVE_MEMBER takes memberEndpointId plus source and target group references with both etags; a lone add cannot implicitly displace another exclusive native group. Contradictory edits return 400; list position is not a procedural ordering mechanism. MERGE_INTO and aggregate/route enablement accept only PORTOS_ONLY. Rename does not automatically merge groups. DELETE_GROUP can delete provider groups. Routes not confirmed retired are disabled and orphaned, so rediscovery cannot resurrect the deleted group. SET_ENABLEMENT can hide an aggregate without deleting it; SET_GROUP_ROUTE_ENABLEMENT changes one provider route's contribution locally. Obtain explicit user authorization for the exact MERGE_INTO or DELETE_GROUP targets and effects before calling. Hue supports native group creation, deletion, membership and rename. Roborock supports room rename only; membership changes do not reshape robot maps. Sonos native group mutations are not implemented. Declared support is authoritative. Use control for device actions such as power, playback or cleaning. Customer intent commits as one batch. Set validateOnly=true to report PLANNED or NOT_SUPPORTED dispatches without sending or writing. idempotencyKey is required otherwise: use one unique key per intended change, and reuse it only for the identical request after a lost or uncertain response. A stale etag returns PRECONDITION_FAILED; re-read and resolve the change before a new request. Inspect status COMMITTED, PARTIALLY_SUCCEEDED or FAILED, each result's APPLIED, PARTIALLY_APPLIED or NOT_APPLIED status, and providerDispatches. Failed batches retain provider facts and report operations whose messages were sent as NOT_APPLIED without group etags; errors identify failing operations. Do not report a partial save as fully synchronized or automatically repeat native writes.
Find rooms, floors, zones, homes and device groups, with their members and supported controls. Returns canonical IDs, names, etags, spatial roles, parent paths, children, member devices, controllers and providers. Call it without arguments first to load full context and follow every paginationContext.nextToken; filter with query only when the account is large. Controllers are the endpoints that can act on the group, with the message IDs that accept it: to clean a room, call control on the controller endpoint with one of those message IDs and payload {"groupIds": [<group ID>]}. Messages are message IDs the group itself accepts: send one with control, using the group ID as id. Port OS uses a native group only when it respects effective membership; otherwise it dispatches equivalent actions to individual members or returns unsupported. Disabled provider routes are never control candidates. Room cleaning is not a group message; use the controller as above. If two groups match a spoken room name, ask the user which one, naming each group's parentPath. Pass id to read one group; a merged group ID resolves to the surviving group and reports redirectedFrom. To show a room map or let someone pick rooms, call endpoint_show on the vacuum (controller) with primary house-map; never draw a map yourself from spatial geometry. Expand accepts capability names as in endpoint_query (for example ["speaker","media-player"]); forceDeviceAttributeQuery refreshes those observations. Read route attribute status before trusting a value: omitted or failed fresh values are unavailable. Each route's membershipComplete is provider-declared: false means incomplete or unreported, and absent means unknown. members lists resolved endpoints, so an empty list does not prove a provider group has no members. Disabled groups are hidden unless enablement is DISABLED or *; they cannot be targeted, and group_manage SET_ENABLEMENT enables them again. Copy group IDs and etags verbatim into control and group_manage.
| Argument | Type | Description |
|---|---|---|
| id | string | Return one group by its full group ID. Cannot be combined with query, maxResults or nextToken. |
Stop watching by cancelling one Port OS event subscription using its exact ID from subscription_list or subscription_inspect. Cancellation is idempotent. Select the intended subscription by name, source endpoint and catalog event; names are not cancellation keys. A stopped monitor requires a new subscription to watch again.
| Argument | Type | Description |
|---|---|---|
| id* | string | Exact subscription ID returned by subscription_list. Never use a display name or endpoint ID. |
{
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"pattern": "\\S",
"maxLength": 2048,
"minLength": 1,
"description": "Exact subscription ID returned by subscription_list. Never use a display name or endpoint ID."
}
},
"additionalProperties": false
}Inspect one Port OS event subscription by its exact ID returned by subscription_list. Returns its safe query, source endpoint, catalog name and lifecycle status. A retained active subscription establishes registration; it does not prove that any client has received or acted on a camera event.
| Argument | Type | Description |
|---|---|---|
| id* | string | Exact subscription ID returned by subscription_list. Never use a display name or endpoint ID. |
{
"type": "object",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"pattern": "\\S",
"maxLength": 2048,
"minLength": 1,
"description": "Exact subscription ID returned by subscription_list. Never use a display name or endpoint ID."
}
},
"additionalProperties": false
}Change only the display name of one Port OS event subscription by exact ID. Use a PLAIN name-value object. The event, endpoint, filter and destination are immutable; to change what is watched, establish a replacement monitor and cancel the old ID.
| Argument | Type | Description |
|---|---|---|
| id* | string | Exact subscription ID returned by subscription_list. Never use a display name or endpoint ID. |
| name* | object |
{
"type": "object",
"required": [
"id",
"name"
],
"properties": {
"id": {
"type": "string",
"pattern": "\\S",
"maxLength": 2048,
"minLength": 1,
"description": "Exact subscription ID returned by subscription_list. Never use a display name or endpoint ID."
},
"name": {
"type": "object",
"required": [
"type",
"value"
],
"properties": {
"type": {
"const": "PLAIN"
},
"value": {
"type": "string",
"pattern": "\\S",
"maxLength": 256,
"minLength": 1
}
},
"additionalProperties": false
}
},
"additionalProperties": false
}Enumerate the user's Port OS event subscriptions, including their exact IDs, names, source endpoint, catalog event and status. For requests to stop watching a camera, list subscriptions and follow every nextCursor, select the intended monitor, then use subscription_cancel with its exact ID. Creating a monitor uses the host's events/subscribe capability after discovering supported camera events; these tools never accept callback URLs or signing keys.
| Argument | Type | Description |
|---|---|---|
| cursor | string | Opaque nextCursor from the preceding subscription_list page. Omit for the first page. |
{
"type": "object",
"required": [],
"properties": {
"cursor": {
"type": "string",
"pattern": "\\S",
"maxLength": 4096,
"minLength": 1,
"description": "Opaque nextCursor from the preceding subscription_list page. Omit for the first page."
}
},
"additionalProperties": false
}| endpointId* | string | Full endpoint ID from endpoint_query. |
{
"type": "object",
"required": [
"operation",
"endpointId"
],
"properties": {
"name": {
"type": "string",
"description": "New endpoint name; only for RENAME."
},
"type": {
"type": "string",
"description": "New ontological endpoint type; only for SET_TYPE."
},
"mergeInto": {
"type": "string",
"description": "Full target endpoint ID; only for MERGE_INTO."
},
"operation": {
"enum": [
"RENAME",
"SET_TYPE",
"SET_ENABLEMENT",
"MERGE_INTO",
"DELETE"
],
"type": "string"
},
"enablement": {
"enum": [
"ENABLED",
"DISABLED"
],
"type": "string",
"description": "New endpoint enablement; only for SET_ENABLEMENT."
},
"endpointId": {
"type": "string",
"description": "Full endpoint ID from endpoint_query."
}
},
"additionalProperties": false
}| Argument | Type | Description |
|---|---|---|
| query | object | Optional field-first filter. Omit it to load full context; filter only when the account is large. Each key is a field or a combinator, and all keys of one object must match: {"name": {"like": "living"}, "type": {"in": ["LIGHT", "SWITCH"]}}. Combinators: {"and": [query, ...]}, {"or": [query, ...]}, {"not": query}. Text operators: eq (exact), in (any of a list), like (case-insensitive substring), lt and gt (lexical order). List operators: has (contains the exact value), like (some value contains the substring, case-insensitive). Fields: id (text) full endpoint ID; name (text) endpoint name; type (text) effective endpoint type, including customer overrides, such as LIGHT, SWITCH, PLUG or ROBOT_VACUUM; manufacturer (text) manufacturer name; model (text) model name; ownerId (text, eq only at the top level) principal whose endpoints to list; defaults to the caller; interfaces (list) full capability interface namespaces; messages (list) full message IDs the endpoint accepts; controllableGroups (list) IDs of groups the endpoint can act on, such as rooms a vacuum can clean (needs group:read). |
| expand | array | Select observations to add to each device result, for example ["power", "connectivity"] or ["battery"]. Use capability names or full namespaces declared by the device. This reads attributes; it does not send commands or broaden the device search. Short names use port1/systems/zero/capability-interfaces. No state reads by default. |
| nextToken | string | Opaque cursor returned by a previous endpoint_query call. |
| enablement | string | Filter by ENABLED (default), DISABLED, or * for both. This filter is preserved by pagination. |
| endpointId | string | Return one endpoint by its full Port OS identifier. Cannot be combined with other filters or pagination. Results advertise its declared command and outbound message IDs. |
| maxResults | integer | Maximum number of results (default 10, maximum 100). |
| forceDeviceAttributeQuery | boolean | Read selected attributes from devices instead of cache. Requires nonempty expand. Failed reads remain unavailable. |
{
"type": "object",
"required": [],
"properties": {
"query": {
"type": "object",
"properties": {},
"description": "Optional field-first filter. Omit it to load full context; filter only when the account is large. Each key is a field or a combinator, and all keys of one object must match: {\"name\": {\"like\": \"living\"}, \"type\": {\"in\": [\"LIGHT\", \"SWITCH\"]}}. Combinators: {\"and\": [query, ...]}, {\"or\": [query, ...]}, {\"not\": query}. Text operators: eq (exact), in (any of a list), like (case-insensitive substring), lt and gt (lexical order). List operators: has (contains the exact value), like (some value contains the substring, case-insensitive). Fields: id (text) full endpoint ID; name (text) endpoint name; type (text) effective endpoint type, including customer overrides, such as LIGHT, SWITCH, PLUG or ROBOT_VACUUM; manufacturer (text) manufacturer name; model (text) model name; ownerId (text, eq only at the top level) principal whose endpoints to list; defaults to the caller; interfaces (list) full capability interface namespaces; messages (list) full message IDs the endpoint accepts; controllableGroups (list) IDs of groups the endpoint can act on, such as rooms a vacuum can clean (needs group:read)."
},
"expand": {
"type": "array",
"items": {
"type": "string"
},
"description": "Select observations to add to each device result, for example [\"power\", \"connectivity\"] or [\"battery\"]. Use capability names or full namespaces declared by the device. This reads attributes; it does not send commands or broaden the device search. Short names use port1/systems/zero/capability-interfaces. No state reads by default."
},
"nextToken": {
"type": "string",
"description": "Opaque cursor returned by a previous endpoint_query call."
},
"enablement": {
"enum": [
"ENABLED",
"DISABLED",
"*"
],
"type": "string",
"default": "ENABLED",
"description": "Filter by ENABLED (default), DISABLED, or * for both. This filter is preserved by pagination."
},
"endpointId": {
"type": "string",
"description": "Return one endpoint by its full Port OS identifier. Cannot be combined with other filters or pagination. Results advertise its declared command and outbound message IDs."
},
"maxResults": {
"type": "integer",
"minimum": 1,
"description": "Maximum number of results (default 10, maximum 100)."
},
"forceDeviceAttributeQuery": {
"type": "boolean",
"description": "Read selected attributes from devices instead of cache. Requires nonempty expand. Failed reads remain unavailable."
}
},
"additionalProperties": false
}| expand | array | Select observations to add to each device result, for example ["power", "connectivity"] or ["battery"]. Use capability names or full namespaces declared by the device. This reads attributes; it does not send commands or broaden the device search. Short names use port1/systems/zero/capability-interfaces. endpoint_show already includes cached readings for the cards it lists; expand replaces that selection. |
| primary | string | The card to lead with, one of the device's card ids (shown as cardIds in the result), for example battery, fan, closure, thermostat, camera or remote; house-map for a vacuum's map or room picking (never draw your own map). Needs endpointId. Every other card stays behind the details toggle. |
| nextToken | string | Opaque cursor returned by a previous endpoint_query call. |
| enablement | string | Filter by ENABLED (default), DISABLED, or * for both. This filter is preserved by pagination. |
| endpointId | string | Return one endpoint by its full Port OS identifier. Cannot be combined with other filters or pagination. Results advertise its declared command and outbound message IDs. |
| maxResults | integer | Maximum number of results (default 10, maximum 100). |
| forceDeviceAttributeQuery | boolean | Read selected attributes from devices instead of cache. Requires nonempty expand. Failed reads remain unavailable. |
{
"type": "object",
"required": [],
"properties": {
"query": {
"type": "object",
"properties": {},
"description": "Optional field-first filter. Omit it to load full context; filter only when the account is large. Each key is a field or a combinator, and all keys of one object must match: {\"name\": {\"like\": \"living\"}, \"type\": {\"in\": [\"LIGHT\", \"SWITCH\"]}}. Combinators: {\"and\": [query, ...]}, {\"or\": [query, ...]}, {\"not\": query}. Text operators: eq (exact), in (any of a list), like (case-insensitive substring), lt and gt (lexical order). List operators: has (contains the exact value), like (some value contains the substring, case-insensitive). Fields: id (text) full endpoint ID; name (text) endpoint name; type (text) effective endpoint type, including customer overrides, such as LIGHT, SWITCH, PLUG or ROBOT_VACUUM; manufacturer (text) manufacturer name; model (text) model name; ownerId (text, eq only at the top level) principal whose endpoints to list; defaults to the caller; interfaces (list) full capability interface namespaces; messages (list) full message IDs the endpoint accepts; controllableGroups (list) IDs of groups the endpoint can act on, such as rooms a vacuum can clean (needs group:read)."
},
"expand": {
"type": "array",
"items": {
"type": "string"
},
"description": "Select observations to add to each device result, for example [\"power\", \"connectivity\"] or [\"battery\"]. Use capability names or full namespaces declared by the device. This reads attributes; it does not send commands or broaden the device search. Short names use port1/systems/zero/capability-interfaces. endpoint_show already includes cached readings for the cards it lists; expand replaces that selection."
},
"primary": {
"type": "string",
"description": "The card to lead with, one of the device's card ids (shown as cardIds in the result), for example battery, fan, closure, thermostat, camera or remote; house-map for a vacuum's map or room picking (never draw your own map). Needs endpointId. Every other card stays behind the details toggle."
},
"nextToken": {
"type": "string",
"description": "Opaque cursor returned by a previous endpoint_query call."
},
"enablement": {
"enum": [
"ENABLED",
"DISABLED",
"*"
],
"type": "string",
"default": "ENABLED",
"description": "Filter by ENABLED (default), DISABLED, or * for both. This filter is preserved by pagination."
},
"endpointId": {
"type": "string",
"description": "Return one endpoint by its full Port OS identifier. Cannot be combined with other filters or pagination. Results advertise its declared command and outbound message IDs."
},
"maxResults": {
"type": "integer",
"minimum": 1,
"description": "Maximum number of results (default 10, maximum 100)."
},
"forceDeviceAttributeQuery": {
"type": "boolean",
"description": "Read selected attributes from devices instead of cache. Requires nonempty expand. Failed reads remain unavailable."
}
},
"additionalProperties": false
}| Argument | Type | Description |
|---|---|---|
| operations* | array | Compatible intended changes in one customer batch. Reuse each group's starting etag across its references; contradictory edits cannot be resolved by list order. |
| validateOnly | boolean | Validate and authorize the batch and report planned or unsupported provider dispatches without sending messages or writing. |
| idempotencyKey | string | Unique key for this intended change, at most 255 characters. Required unless validateOnly is true. |
{
"type": "object",
"required": [
"operations"
],
"properties": {
"operations": {
"type": "array",
"items": {
"oneOf": [
{
"type": "object",
"required": [
"requestId",
"operation",
"name"
],
"properties": {
"name": {
"type": "object",
"required": [
"type",
"value"
],
"properties": {
"type": {
"type": "string",
"description": "The type identifier of the name value, defined as plain when not defined."
},
"value": {
"type": "string",
"description": "the raw value of a plain name."
}
}
},
"operation": {
"enum": [
"CREATE_GROUP"
],
"type": "string",
"description": "Operation discriminator."
},
"requestId": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "Client-chosen identifier for one operation in a batch request. It must be unique within the request and is echoed in the matching result or error so items are correlated by ID, never by position.\n"
},
"providerSync": {
"allOf": [
{
"enum": [
"PORTOS_ONLY",
"BEST_EFFORT",
"FAIL_ON_PROVIDER_ERROR"
],
"type": "string",
"default": "BEST_EFFORT",
"description": "Provider synchronization policy. BEST_EFFORT asks declared providers first and saves local fallback intent on failure. FAIL_ON_PROVIDER_ERROR fails the customer batch on a failed supported dispatch while retaining received provider truth. PORTOS_ONLY changes local intent. Undeclared messages are reported as NOT_SUPPORTED and do not prevent local changes."
}
],
"default": "BEST_EFFORT",
"description": "Provider synchronization policy; defaults to BEST_EFFORT."
},
"memberEndpointIds": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"maxItems": 100,
"minItems": 1,
"description": "Endpoint IDs.",
"uniqueItems": true
}
},
"description": "Creates a user group. Its new ID and etag are returned in the result; later operations in the same batch cannot reference it. A user group name is `{\"type\": \"PLAIN\", \"value\": ...}` whose value is non-blank UTF-8 text of at most 256 bytes with no control characters; anything else is rejected with BAD_REQUEST. Each added member must be the ID of an existing endpoint the caller can read; a malformed ID is BAD_REQUEST, and a missing or unreadable endpoint is NOT_FOUND.\n",
"additionalProperties": false
},
{
"type": "object",
"required": [
"requestId",
"operation",
"groupId",
"etag"
],
"properties": {
"etag": {
"type": "string",
"minLength": 1,
"description": "The group starting etag the client last read, shared by all references in this batch. A meaningful change advances the group once at final commit; results use its final etag.\n"
},
"groupId": {
"type": "string",
"minLength": 1,
"description": "The endpoint group to modify."
},
"operation": {
"enum": [
"DELETE_GROUP"
],
"type": "string",
"description": "Operation discriminator."
},
"requestId": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "Client-chosen identifier for one operation in a batch request. It must be unique within the request and is echoed in the matching result or error so items are correlated by ID, never by position.\n"
},
"providerSync": {
"allOf": [
{
"enum": [
"PORTOS_ONLY",
"BEST_EFFORT",
"FAIL_ON_PROVIDER_ERROR"
],
"type": "string",
"default": "BEST_EFFORT",
"description": "Provider synchronization policy. BEST_EFFORT asks declared providers first and saves local fallback intent on failure. FAIL_ON_PROVIDER_ERROR fails the customer batch on a failed supported dispatch while retaining received provider truth. PORTOS_ONLY changes local intent. Undeclared messages are reported as NOT_SUPPORTED and do not prevent local changes."
}
],
"default": "BEST_EFFORT",
"description": "Provider synchronization policy; defaults to BEST_EFFORT."
}
},
"description": "Deletes a group.",
"additionalProperties": false
},
{
"type": "object",
"required": [
"requestId",
"operation",
"groupId",
"etag",
"name"
],
"properties": {
"etag": {
"type": "string",
"minLength": 1,
"description": "The group starting etag the client last read, shared by all references in this batch. A meaningful change advances the group once at final commit; results use its final etag.\n"
},
"name": {
"type": "object",
"required": [
"type",
"value"
],
"properties": {
"type": {
"type": "string",
"description": "The type identifier of the name value, defined as plain when not defined."
},
"value": {
"type": "string",
"description": "the raw value of a plain name."
}
}
},
"groupId": {
"type": "string",
"minLength": 1,
"description": "The endpoint group to modify."
},
"operation": {
"enum": [
"SET_NAME"
],
"type": "string",
"description": "Operation discriminator."
},
"requestId": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "Client-chosen identifier for one operation in a batch request. It must be unique within the request and is echoed in the matching result or error so items are correlated by ID, never by position.\n"
},
"providerSync": {
"allOf": [
{
"enum": [
"PORTOS_ONLY",
"BEST_EFFORT",
"FAIL_ON_PROVIDER_ERROR"
],
"type": "string",
"default": "BEST_EFFORT",
"description": "Provider synchronization policy. BEST_EFFORT asks declared providers first and saves local fallback intent on failure. FAIL_ON_PROVIDER_ERROR fails the customer batch on a failed supported dispatch while retaining received provider truth. PORTOS_ONLY changes local intent. Undeclared messages are reported as NOT_SUPPORTED and do not prevent local changes."
}
],
"default": "BEST_EFFORT",
"description": "Provider synchronization policy; defaults to BEST_EFFORT."
}
},
"description": "Renames a group. The name is a user override that survives rediscovery. A user group name is `{\"type\": \"PLAIN\", \"value\": ...}` whose value is non-blank UTF-8 text of at most 256 bytes with no control characters; anything else is rejected with BAD_REQUEST.\n",
"additionalProperties": false
},
{
"type": "object",
"required": [
"requestId",
"operation",
"groupId",
"etag",
"memberEndpointIds"
],
"properties": {
"etag": {
"type": "string",
"minLength": 1,
"description": "The group starting etag the client last read, shared by all references in this batch. A meaningful change advances the group once at final commit; results use its final etag.\n"
},
"groupId": {
"type": "string",
"minLength": 1,
"description": "The endpoint group to modify."
},
"operation": {
"enum": [
"ADD_MEMBERS"
],
"type": "string",
"description": "Operation discriminator."
},
"requestId": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "Client-chosen identifier for one operation in a batch request. It must be unique within the request and is echoed in the matching result or error so items are correlated by ID, never by position.\n"
},
"providerSync": {
"allOf": [
{
"enum": [
"PORTOS_ONLY",
"BEST_EFFORT",
"FAIL_ON_PROVIDER_ERROR"
],
"type": "string",
"default": "BEST_EFFORT",
"description": "Provider synchronization policy. BEST_EFFORT asks declared providers first and saves local fallback intent on failure. FAIL_ON_PROVIDER_ERROR fails the customer batch on a failed supported dispatch while retaining received provider truth. PORTOS_ONLY changes local intent. Undeclared messages are reported as NOT_SUPPORTED and do not prevent local changes."
}
],
"default": "BEST_EFFORT",
"description": "Provider synchronization policy; defaults to BEST_EFFORT."
},
"memberEndpointIds": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"maxItems": 100,
"minItems": 1,
"description": "Endpoint IDs.",
"uniqueItems": true
}
},
"description": "Adds endpoint members to a group. Each added member must be the ID of an existing endpoint the caller can read; a malformed ID is BAD_REQUEST, and a missing or unreadable endpoint is NOT_FOUND.\n",
"additionalProperties": false
},
{
"type": "object",
"required": [
"requestId",
"operation",
"groupId",
"etag",
"memberEndpointIds"
],
"properties": {
"etag": {
"type": "string",
"minLength": 1,
"description": "The group starting etag the client last read, shared by all references in this batch. A meaningful change advances the group once at final commit; results use its final etag.\n"
},
"groupId": {
"type": "string",
"minLength": 1,
"description": "The endpoint group to modify."
},
"operation": {
"enum": [
"REMOVE_MEMBERS"
],
"type": "string",
"description": "Operation discriminator."
},
"requestId": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "Client-chosen identifier for one operation in a batch request. It must be unique within the request and is echoed in the matching result or error so items are correlated by ID, never by position.\n"
},
"providerSync": {
"allOf": [
{
"enum": [
"PORTOS_ONLY",
"BEST_EFFORT",
"FAIL_ON_PROVIDER_ERROR"
],
"type": "string",
"default": "BEST_EFFORT",
"description": "Provider synchronization policy. BEST_EFFORT asks declared providers first and saves local fallback intent on failure. FAIL_ON_PROVIDER_ERROR fails the customer batch on a failed supported dispatch while retaining received provider truth. PORTOS_ONLY changes local intent. Undeclared messages are reported as NOT_SUPPORTED and do not prevent local changes."
}
],
"default": "BEST_EFFORT",
"description": "Provider synchronization policy; defaults to BEST_EFFORT."
},
"memberEndpointIds": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"maxItems": 100,
"minItems": 1,
"description": "Endpoint IDs.",
"uniqueItems": true
}
},
"description": "Removes endpoint members from a group. IDs that are not members are ignored.\n",
"additionalProperties": false
},
{
"type": "object",
"required": [
"requestId",
"operation",
"sources",
"target"
],
"properties": {
"target": {
"type": "object",
"required": [
"groupId",
"etag"
],
"properties": {
"etag": {
"type": "string",
"minLength": 1,
"description": "The group's `etag` as last read by the client."
},
"groupId": {
"type": "string",
"minLength": 1,
"description": "The endpoint group ID."
}
},
"description": "A group addressed together with the etag the client last read, validated inside the management transaction.",
"additionalProperties": false
},
"sources": {
"type": "array",
"items": {
"type": "object",
"required": [
"groupId",
"etag"
],
"properties": {
"etag": {
"type": "string",
"minLength": 1,
"description": "The group's `etag` as last read by the client."
},
"groupId": {
"type": "string",
"minLength": 1,
"description": "The endpoint group ID."
}
},
"description": "A group addressed together with the etag the client last read, validated inside the management transaction.",
"additionalProperties": false
},
"maxItems": 20,
"minItems": 1,
"description": "Groups merged into the target; each must be distinct from the target and from each other."
},
"operation": {
"enum": [
"MERGE_INTO"
],
"type": "string",
"description": "Operation discriminator."
},
"requestId": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "Client-chosen identifier for one operation in a batch request. It must be unique within the request and is echoed in the matching result or error so items are correlated by ID, never by position.\n"
},
"providerSync": {
"allOf": [
{
"enum": [
"PORTOS_ONLY",
"BEST_EFFORT",
"FAIL_ON_PROVIDER_ERROR"
],
"type": "string",
"default": "BEST_EFFORT",
"description": "Provider synchronization policy. BEST_EFFORT asks declared providers first and saves local fallback intent on failure. FAIL_ON_PROVIDER_ERROR fails the customer batch on a failed supported dispatch while retaining received provider truth. PORTOS_ONLY changes local intent. Undeclared messages are reported as NOT_SUPPORTED and do not prevent local changes."
}
],
"default": "PORTOS_ONLY",
"description": "Only PORTOS_ONLY is supported; another mode returns 422 PROVIDER_SYNC_UNSUPPORTED."
}
},
"description": "Merges source groups into a target group. Source group routes are rehomed to the target, memberships are unioned, and each source ID becomes a redirect to the target. Identity decision that requires explicit user confirmation.",
"additionalProperties": false
},
{
"type": "object",
"required": [
"requestId",
"operation",
"groupId",
"etag",
"enablement"
],
"properties": {
"etag": {
"type": "string",
"minLength": 1,
"description": "The group starting etag the client last read, shared by all references in this batch. A meaningful change advances the group once at final commit; results use its final etag.\n"
},
"groupId": {
"type": "string",
"minLength": 1,
"description": "The endpoint group to modify."
},
"operation": {
"enum": [
"SET_ENABLEMENT"
],
"type": "string",
"description": "Operation discriminator."
},
"requestId": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "Client-chosen identifier for one operation in a batch request. It must be unique within the request and is echoed in the matching result or error so items are correlated by ID, never by position.\n"
},
"enablement": {
"enum": [
"ENABLED",
"DISABLED"
],
"type": "string",
"default": "ENABLED",
"description": "Whether Port OS uses an endpoint or group. A disabled one is hidden from collections by default and cannot be sent device messages or targeted by them; exact authorized reads still return it. Rediscovery never changes it, so disabling is how a user hides a discovered device or room for good.\n"
},
"providerSync": {
"allOf": [
{
"enum": [
"PORTOS_ONLY",
"BEST_EFFORT",
"FAIL_ON_PROVIDER_ERROR"
],
"type": "string",
"default": "BEST_EFFORT",
"description": "Provider synchronization policy. BEST_EFFORT asks declared providers first and saves local fallback intent on failure. FAIL_ON_PROVIDER_ERROR fails the customer batch on a failed supported dispatch while retaining received provider truth. PORTOS_ONLY changes local intent. Undeclared messages are reported as NOT_SUPPORTED and do not prevent local changes."
}
],
"default": "PORTOS_ONLY",
"description": "Only PORTOS_ONLY is supported; another mode returns 422 PROVIDER_SYNC_UNSUPPORTED."
}
},
"description": "Enables or disables a group. A disabled group is hidden from group lists by default and cannot be targeted by messages such as clean-room. Rediscovery never re-enables it, so disabling (not deleting) is how a user hides a discovered group, such as a robot's room, for good.\n",
"additionalProperties": false
},
{
"type": "object",
"required": [
"requestId",
"operation",
"memberEndpointId",
"source",
"target"
],
"properties": {
"source": {
"type": "object",
"required": [
"groupId",
"etag"
],
"properties": {
"etag": {
"type": "string",
"minLength": 1,
"description": "The group's `etag` as last read by the client."
},
"groupId": {
"type": "string",
"minLength": 1,
"description": "The endpoint group ID."
}
},
"description": "A group addressed together with the etag the client last read, validated inside the management transaction.",
"additionalProperties": false
},
"target": {
"type": "object",
"required": [
"groupId",
"etag"
],
"properties": {
"etag": {
"type": "string",
"minLength": 1,
"description": "The group's `etag` as last read by the client."
},
"groupId": {
"type": "string",
"minLength": 1,
"description": "The endpoint group ID."
}
},
"description": "A group addressed together with the etag the client last read, validated inside the management transaction.",
"additionalProperties": false
},
"operation": {
"enum": [
"MOVE_MEMBER"
],
"type": "string",
"description": "Operation discriminator."
},
"requestId": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "Client-chosen identifier for one operation in a batch request. It must be unique within the request and is echoed in the matching result or error so items are correlated by ID, never by position.\n"
},
"providerSync": {
"allOf": [
{
"enum": [
"PORTOS_ONLY",
"BEST_EFFORT",
"FAIL_ON_PROVIDER_ERROR"
],
"type": "string",
"default": "BEST_EFFORT",
"description": "Provider synchronization policy. BEST_EFFORT asks declared providers first and saves local fallback intent on failure. FAIL_ON_PROVIDER_ERROR fails the customer batch on a failed supported dispatch while retaining received provider truth. PORTOS_ONLY changes local intent. Undeclared messages are reported as NOT_SUPPORTED and do not prevent local changes."
}
],
"default": "BEST_EFFORT",
"description": "Provider synchronization policy; defaults to BEST_EFFORT."
},
"memberEndpointId": {
"type": "string",
"minLength": 1,
"description": "The existing endpoint to move."
}
},
"description": "Moves one endpoint between distinct groups. Both references use their starting etags, shared with every other reference to these groups in this batch. The caller must be authorized to remove the member from the source, add it to the target and read the endpoint. Provider removal precedes addition. An exclusive add that would displace another group requires this operation rather than an implicit move.",
"additionalProperties": false
},
{
"type": "object",
"required": [
"requestId",
"operation",
"groupRouteId",
"enablement"
],
"properties": {
"etag": {
"type": "string",
"minLength": 1,
"description": "The associated group's starting etag; omit only for an orphaned route."
},
"operation": {
"enum": [
"SET_GROUP_ROUTE_ENABLEMENT"
],
"type": "string",
"description": "Operation discriminator."
},
"requestId": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "Client-chosen identifier for one operation in a batch request. It must be unique within the request and is echoed in the matching result or error so items are correlated by ID, never by position.\n"
},
"enablement": {
"enum": [
"ENABLED",
"DISABLED"
],
"type": "string",
"default": "ENABLED",
"description": "Whether Port OS uses an endpoint or group. A disabled one is hidden from collections by default and cannot be sent device messages or targeted by them; exact authorized reads still return it. Rediscovery never changes it, so disabling is how a user hides a discovered device or room for good.\n"
},
"groupRouteId": {
"type": "string",
"minLength": 1,
"description": "The Port OS group route ID."
},
"providerSync": {
"allOf": [
{
"enum": [
"PORTOS_ONLY",
"BEST_EFFORT",
"FAIL_ON_PROVIDER_ERROR"
],
"type": "string",
"default": "BEST_EFFORT",
"description": "Provider synchronization policy. BEST_EFFORT asks declared providers first and saves local fallback intent on failure. FAIL_ON_PROVIDER_ERROR fails the customer batch on a failed supported dispatch while retaining received provider truth. PORTOS_ONLY changes local intent. Undeclared messages are reported as NOT_SUPPORTED and do not prevent local changes."
}
],
"default": "PORTOS_ONLY",
"description": "Only PORTOS_ONLY is supported, and it is the default."
}
},
"description": "Enables or disables one stored provider group route. Disabling retains its observations but removes its membership and interfaces from resolution. Enabling an orphan can create or attach a group. The associated group's starting etag is required when the route has a group. Only PORTOS_ONLY is supported; another mode returns 422 PROVIDER_SYNC_UNSUPPORTED.",
"additionalProperties": false
}
],
"description": "One endpoint group management operation, discriminated by `operation`. Unknown operations are rejected with 400.",
"discriminator": {
"mapping": {
"SET_NAME": "#/components/schemas/EndpointGroupsSetNameOperation",
"MERGE_INTO": "#/components/schemas/EndpointGroupsMergeIntoOperation",
"ADD_MEMBERS": "#/components/schemas/EndpointGroupsAddMembersOperation",
"MOVE_MEMBER": "#/components/schemas/EndpointGroupsMoveMemberOperation",
"CREATE_GROUP": "#/components/schemas/EndpointGroupsCreateGroupOperation",
"DELETE_GROUP": "#/components/schemas/EndpointGroupsDeleteGroupOperation",
"REMOVE_MEMBERS": "#/components/schemas/EndpointGroupsRemoveMembersOperation",
"SET_ENABLEMENT": "#/components/schemas/EndpointGroupsSetEnablementOperation",
"SET_GROUP_ROUTE_ENABLEMENT": "#/components/schemas/EndpointGroupsSetGroupRouteEnablementOperation"
},
"propertyName": "operation"
}
},
"maxItems": 20,
"minItems": 1,
"description": "Compatible intended changes in one customer batch. Reuse each group's starting etag across its references; contradictory edits cannot be resolved by list order."
},
"validateOnly": {
"type": "boolean",
"description": "Validate and authorize the batch and report planned or unsupported provider dispatches without sending messages or writing."
},
"idempotencyKey": {
"type": "string",
"description": "Unique key for this intended change, at most 255 characters. Required unless validateOnly is true."
}
},
"additionalProperties": false
}| query | object | Optional field-first filter. Omit it to load full context; filter only when the account is large. Each key is a field or a combinator, and all keys of one object must match: {"role": {"eq": "ROOM"}, "name": {"like": "kitchen"}}. Combinators: {"and": [query, ...]}, {"or": [query, ...]}, {"not": query}. Text operators: eq (exact), in (any of a list), like (case-insensitive substring), lt and gt (lexical order). List operators: has (contains the exact value), like (some value contains the substring, case-insensitive). Fields: id (text) full group ID; name (text) group name; role (text) spatial role a provider declares: HOME, FLOOR, ROOM or ZONE; parentGroupId (text) ID of the containing group; ownerId (text, eq only at the top level) principal whose groups to list; defaults to the caller; children (list) IDs of contained groups; members (list) member endpoint IDs; controllers (list) IDs of endpoints that can act on the group, such as a robot that cleans the room; messages (list) full message IDs the group itself accepts; providers (list) names of the plugins that report the group. |
| expand | array | Select declared capabilities whose route observations to return, for example ["speaker", "media-player"]. Requires id. This adds state readings to the selected group; it does not expand group membership or send commands. Expanding spatial returns raw room geometry for reading only. To show a map or let someone pick rooms, call endpoint_show on the vacuum with primary house-map; never draw one yourself. |
| nextToken | string | Opaque cursor returned by a previous group_query call with the same query and maxResults. |
| enablement | string | Filter by ENABLED (default), DISABLED, or * for both. This filter is preserved by pagination; id reads ignore it. |
| maxResults | integer | Maximum number of groups (default 25, maximum 100). |
| forceDeviceAttributeQuery | boolean | Requires id and nonempty expand; refresh provider state before returning route observations. |
{
"type": "object",
"required": [],
"properties": {
"id": {
"type": "string",
"description": "Return one group by its full group ID. Cannot be combined with query, maxResults or nextToken."
},
"query": {
"type": "object",
"properties": {},
"description": "Optional field-first filter. Omit it to load full context; filter only when the account is large. Each key is a field or a combinator, and all keys of one object must match: {\"role\": {\"eq\": \"ROOM\"}, \"name\": {\"like\": \"kitchen\"}}. Combinators: {\"and\": [query, ...]}, {\"or\": [query, ...]}, {\"not\": query}. Text operators: eq (exact), in (any of a list), like (case-insensitive substring), lt and gt (lexical order). List operators: has (contains the exact value), like (some value contains the substring, case-insensitive). Fields: id (text) full group ID; name (text) group name; role (text) spatial role a provider declares: HOME, FLOOR, ROOM or ZONE; parentGroupId (text) ID of the containing group; ownerId (text, eq only at the top level) principal whose groups to list; defaults to the caller; children (list) IDs of contained groups; members (list) member endpoint IDs; controllers (list) IDs of endpoints that can act on the group, such as a robot that cleans the room; messages (list) full message IDs the group itself accepts; providers (list) names of the plugins that report the group."
},
"expand": {
"type": "array",
"items": {
"type": "string"
},
"description": "Select declared capabilities whose route observations to return, for example [\"speaker\", \"media-player\"]. Requires id. This adds state readings to the selected group; it does not expand group membership or send commands. Expanding spatial returns raw room geometry for reading only. To show a map or let someone pick rooms, call endpoint_show on the vacuum with primary house-map; never draw one yourself."
},
"nextToken": {
"type": "string",
"description": "Opaque cursor returned by a previous group_query call with the same query and maxResults."
},
"enablement": {
"enum": [
"ENABLED",
"DISABLED",
"*"
],
"type": "string",
"default": "ENABLED",
"description": "Filter by ENABLED (default), DISABLED, or * for both. This filter is preserved by pagination; id reads ignore it."
},
"maxResults": {
"type": "integer",
"minimum": 1,
"description": "Maximum number of groups (default 25, maximum 100)."
},
"forceDeviceAttributeQuery": {
"type": "boolean",
"description": "Requires id and nonempty expand; refresh provider state before returning route observations."
}
},
"additionalProperties": false
}