changedOutput schema / oneOf
Previous value: -[
- {
- "additionalProperties": false,
- "properties": {
- "paginationContext": {
- "properties": {
- "nextToken": {
- "type": "string"
- }
- },
- "required": [
- "nextToken"
- ],
- "type": "object"
- },
- "primary": {
- "description": "The card endpoint_show was asked to lead with. Present only when the call set primary.",
- "type": "string"
- },
- "results": {
- "items": {
- "properties": {
- "cardIds": {
- "description": "Card ids the device can show as its primary card in endpoint_show. Present only on endpoint_show results.",
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "childEndpointIds": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "controllableGroups": {
- "items": {
- "properties": {
- "geometry": {
- "description": "The room outline from the group's stored spatial geometry (cached, never a provider read). Present on every single-endpoint read (endpoint_show or endpoint_query with endpointId), never on lists, and only for rooms whose geometry is usable; rooms without it stay listed. Rooms sharing a frameId are one map. Tiny speckle and excess detail are dropped to keep the result bounded.",
- "properties": {
- "coordinateSystem": {
- "description": "The spatial capability's declared axes. Drawing must flip y when yAxis is UP.",
- "properties": {
- "unit": {
- "type": "string"
- },
- "xAxis": {
- "type": "string"
- },
- "yAxis": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "frameId": {
- "description": "The group route the coordinates are relative to; rooms of one map share it.",
- "type": "string"
- },
- "shape": {
- "properties": {
- "coordinates": {
- "description": "Polygons, each a list of rings of [x, y] points; the first ring is the outline, the others are holes.",
- "items": {},
- "type": "array"
- },
- "type": {
- "enum": [
- "MultiPolygon"
- ],
- "type": "string"
- }
- },
- "required": [
- "type",
- "coordinates"
- ],
- "type": "object"
- }
- },
- "required": [
- "shape"
- ],
- "type": "object"
- },
- "groupId": {
- "type": "string"
- },
- "messages": {
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "name": {
- "type": "string"
- },
- "parentPath": {
- "items": {
- "properties": {
- "groupId": {
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "role": {
- "type": "string"
- }
- },
- "required": [
- "groupId",
- "name"
- ],
- "type": "object"
- },
- "type": "array"
- }
- },
- "required": [
- "groupId",
- "name",
- "parentPath",
- "messages"
- ],
- "type": "object"
- },
- "type": "array"
- },
- "description": {
- "properties": {
- "type": {
- "type": "string"
- },
- "value": {
- "type": "string"
- }
- },
- "required": [
- "type",
- "value"
- ],
- "type": "object"
- },
- "enablement": {
- "enum": [
- "ENABLED",
- "DISABLED"
- ],
- "type": "string"
- },
- "id": {
- "type": "string"
- },
- "interfaces": {
- "items": {
- "properties": {
- "attributes": {
- "items": {
- "oneOf": [
- {
- "additionalProperties": false,
- "properties": {
- "name": {
- "type": "string"
- }
- },
- "required": [
- "name"
- ],
- "type": "object"
- },
- {
- "additionalProperties": false,
- "properties": {
- "autoUpdateFrequency": {
- "description": "Declared frequency at which the serving route automatically updates this attribute.",
- "enum": [
- "REALTIME",
- "MINUTES",
- "HOURLY",
- "DAILY",
- "NEVER"
- ],
- "type": "string"
- },
- "error": {
- "description": "The one Port OS error shape, returned by every REST error response and every MCP tool error. `code` names the specific failure and `family` its broad class; both are closed enums, so clients branch on them and show `message`, which says what failed and what to do next.",
- "properties": {
- "code": {
- "description": "The specific error, one of a closed set of Port OS codes. Every REST error body, MCP tool error, batch item error and discovery item error uses this enum; each code belongs to an `ErrorFamily` that decides its HTTP status. Provider-specific codes are never codes: they travel in `details.providerCode`. New failure kinds are added here, never as free strings.",
- "enum": [
- "BAD_REQUEST",
- "UNAUTHORIZED",
- "FORBIDDEN",
- "INSUFFICIENT_SCOPE",
- "NOT_FOUND",
- "CONFLICT",
- "UNPROCESSABLE_ENTITY",
- "UNSUPPORTED_OPERATION",
- "TOO_MANY_REQUESTS",
- "SERVICE_UNAVAILABLE",
- "NOT_IMPLEMENTED",
- "INTERNAL",
- "CHECKSUM_MISMATCH",
- "FILE_TOO_LARGE",
- "STORAGE_UNAVAILABLE",
- "INSUFFICIENT_PERMISSIONS",
- "INVALID_FILE_TYPE",
- "QUOTA_EXCEEDED",
- "CONCURRENT_MODIFICATION",
- "ENDPOINT_UNREACHABLE",
- "BRIDGE_UNREACHABLE",
- "CLOUD_CONTROL_DISABLED",
- "ENDPOINT_BUSY",
- "ENDPOINT_LOW_POWER",
- "AUTHORIZATION_CREDENTIAL_INVALID",
- "AUTHORIZATION_CREDENTIAL_EXPIRED",
- "INVALID_DIRECTIVE",
- "INVALID_VALUE",
- "VALUE_OUT_OF_RANGE",
- "NOT_SUPPORTED_IN_CURRENT_MODE",
- "RATE_LIMIT_EXCEEDED",
- "PROVIDER_SERVICE_UNAVAILABLE",
- "PROVIDER_TIMEOUT",
- "PROVIDER_INTERNAL_ERROR",
- "INVALID_PROVIDER_RESPONSE",
- "OUTCOME_UNKNOWN",
- "PRECONDITION_FAILED",
- "AUTH_LINK_NOT_READY",
- "AUTH_LINK_NOT_DISCONNECTABLE",
- "PRECONDITION_REQUIRED",
- "IDEMPOTENCY_KEY_REQUIRED",
- "IDEMPOTENCY_KEY_REUSED",
- "IDEMPOTENCY_KEY_IN_FLIGHT",
- "IDEMPOTENCY_KEY_INVALID",
- "GROUP_MERGED",
- "MULTI_ROOM_UNSUPPORTED",
- "MAP_NOT_ACTIVE",
- "TARGET_UNSUPPORTED",
- "TARGET_AMBIGUOUS",
- "TARGET_GROUP_NOT_FOUND",
- "TARGET_GROUP_DISABLED",
- "DUPLICATE_TARGET_GROUP",
- "MESSAGE_UNSUPPORTED",
- "MESSAGE_AMBIGUOUS",
- "ENDPOINT_DISABLED",
- "ENDPOINT_ROUTE_CHANGED",
- "ENDPOINT_HAS_DEPENDENCIES",
- "ENDPOINT_EVENT_SUBSCRIPTIONS_ACTIVE",
- "ENDPOINT_COMMITTED_CLEANUP_PENDING",
- "DEEP_QUERY_FAILED",
- "PROVIDER_NO_STATE",
- "EVENT_MANAGEMENT_DISABLED",
- "SUBSCRIPTION_IDENTITY_IMMUTABLE",
- "UNSUPPORTED_MEDIA_TYPE",
- "EVENT_PAYLOAD_TOO_LARGE",
- "REQUEST_BODY_TOO_LARGE",
- "EVENT_IDENTITY_CONFLICT",
- "EVENT_INGRESS_QUOTA_EXCEEDED",
- "EVENT_RECEIPT_EXPIRED",
- "EVENT_STORAGE_UNAVAILABLE",
- "EVENT_DEAD_LETTER_NOT_FOUND",
- "EVENT_REDRIVE_CONFLICT",
- "EVENT_REDRIVE_EXPIRED",
- "RECEIPT_CONTEXT_EXPIRED",
- "EVENT_MAINTENANCE_INCOMPLETE",
- "UNKNOWN_INTERFACE",
- "INVALID_CONFIGURATION",
- "INVALID_PLUGIN_MANIFEST",
- "INVALID_ATTRIBUTE",
- "INVALID_PROVIDER_MESSAGE",
- "UNDECLARED_CAPABILITY",
- "PLUGIN_ROUTE_ID_CONFLICT",
- "UNRESOLVED_REFERENCE",
- "INVALID_RELATIONSHIP",
- "RELATIONSHIP_CYCLE",
- "MULTIPLE_PARENTS",
- "FLOW_VALIDATION_FAILED",
- "PROVIDER_SYNC_UNSUPPORTED"
- ],
- "type": "string"
- },
- "details": {
- "description": "Optional typed context for an error. Fields are additive and only populated when the error can safely expose that context to API clients.\n",
- "properties": {
- "actual": {
- "description": "String representation of the submitted value when the plugin can safely report it.",
- "type": "string"
- },
- "correlationId": {
- "description": "Provider or plugin correlation ID useful for support.",
- "type": "string"
- },
- "correlationToken": {
- "description": "Token that correlates an outcome-unknown dispatch with its eventual result.",
- "type": "string"
- },
- "currentMode": {
- "description": "Current endpoint mode when `code` is `NOT_SUPPORTED_IN_CURRENT_MODE`.",
- "type": "string"
- },
- "directive": {
- "description": "Message namespace and name or provider directive that failed.",
- "type": "string"
- },
- "discoveryEndpointId": {
- "description": "Port OS provider endpoint (type ENDPOINT_PLUGIN) of the connection to send `discover-routes` to when `code` is `TARGET_UNSUPPORTED` because the route must be rediscovered.",
- "type": "string"
- },
- "endpointId": {
- "description": "Port OS endpoint ID involved in the failed dispatch.",
- "type": "string"
- },
- "fieldErrors": {
- "description": "The request fields that were rejected, when the error is about the request's content.",
- "items": {
- "description": "One rejected request field of an error.",
- "properties": {
- "field": {
- "description": "Name or JSON path of the rejected field.",
- "type": "string"
- },
- "reason": {
- "description": "Why the field was rejected and what an accepted value looks like.",
- "type": "string"
- }
- },
- "required": [
- "field",
- "reason"
- ],
- "type": "object"
- },
- "type": "array"
- },
- "maximum": {
- "description": "Maximum accepted value when `code` is `VALUE_OUT_OF_RANGE`.",
- "type": "number"
- },
- "minimum": {
- "description": "Minimum accepted value when `code` is `VALUE_OUT_OF_RANGE`.",
- "type": "number"
- },
- "parameter": {
- "description": "Request parameter or capability value that caused the failure.",
- "type": "string"
- },
- "pluginId": {
- "description": "Port OS plugin ID that reported the failure.",
- "type": "string"
- },
- "pluginRouteId": {
- "description": "Plugin-owned route identifier involved in the failed dispatch.",
- "type": "string"
- },
- "provider": {
- "description": "Third-party provider or bridge name that reported the failure.",
- "type": "string"
- },
- "providerCode": {
- "description": "The third-party provider's own error code, for support. It is opaque and provider-specific; branch on `code` and `family` instead.",
- "type": "string"
- },
- "retryAfterSeconds": {
- "description": "Suggested retry delay for rate-limit or provider-unavailable failures.",
- "minimum": 0,
- "type": "integer"
- }
- },
- "type": "object"
- },
- "errors": {
- "description": "Every rejected item when a request that is validated item by item and applied atomically fails, such as a discovery `SynchronizationRequest` whose routes, group routes or relationships are rejected. Omitted for single-item failures.\n",
- "items": {
- "description": "One rejected discovery item of a `SynchronizationRequest`, keyed by the plugin-owned identity of the rejected item: `pluginRouteId` for a route or group route, or `relationshipExternalId` for a relationship. Exactly one of the two is set. It shares the `code`, `family`, `status` and `message` fields of `BatchItemError`; discovery items are keyed by plugin-owned identity because they carry no `requestId`. A request with any rejected item is rejected as a whole and lists every rejected item.\n",
- "properties": {
- "code": {
- "description": "The specific error, one of a closed set of Port OS codes. Every REST error body, MCP tool error, batch item error and discovery item error uses this enum; each code belongs to an `ErrorFamily` that decides its HTTP status. Provider-specific codes are never codes: they travel in `details.providerCode`. New failure kinds are added here, never as free strings.",
- "enum": [
- "BAD_REQUEST",
- "UNAUTHORIZED",
- "FORBIDDEN",
- "INSUFFICIENT_SCOPE",
- "NOT_FOUND",
- "CONFLICT",
- "UNPROCESSABLE_ENTITY",
- "UNSUPPORTED_OPERATION",
- "TOO_MANY_REQUESTS",
- "SERVICE_UNAVAILABLE",
- "NOT_IMPLEMENTED",
- "INTERNAL",
- "CHECKSUM_MISMATCH",
- "FILE_TOO_LARGE",
- "STORAGE_UNAVAILABLE",
- "INSUFFICIENT_PERMISSIONS",
- "INVALID_FILE_TYPE",
- "QUOTA_EXCEEDED",
- "CONCURRENT_MODIFICATION",
- "ENDPOINT_UNREACHABLE",
- "BRIDGE_UNREACHABLE",
- "CLOUD_CONTROL_DISABLED",
- "ENDPOINT_BUSY",
- "ENDPOINT_LOW_POWER",
- "AUTHORIZATION_CREDENTIAL_INVALID",
- "AUTHORIZATION_CREDENTIAL_EXPIRED",
- "INVALID_DIRECTIVE",
- "INVALID_VALUE",
- "VALUE_OUT_OF_RANGE",
- "NOT_SUPPORTED_IN_CURRENT_MODE",
- "RATE_LIMIT_EXCEEDED",
- "PROVIDER_SERVICE_UNAVAILABLE",
- "PROVIDER_TIMEOUT",
- "PROVIDER_INTERNAL_ERROR",
- "INVALID_PROVIDER_RESPONSE",
- "OUTCOME_UNKNOWN",
- "PRECONDITION_FAILED",
- "AUTH_LINK_NOT_READY",
- "AUTH_LINK_NOT_DISCONNECTABLE",
- "PRECONDITION_REQUIRED",
- "IDEMPOTENCY_KEY_REQUIRED",
- "IDEMPOTENCY_KEY_REUSED",
- "IDEMPOTENCY_KEY_IN_FLIGHT",
- "IDEMPOTENCY_KEY_INVALID",
- "GROUP_MERGED",
- "MULTI_ROOM_UNSUPPORTED",
- "MAP_NOT_ACTIVE",
- "TARGET_UNSUPPORTED",
- "TARGET_AMBIGUOUS",
- "TARGET_GROUP_NOT_FOUND",
- "TARGET_GROUP_DISABLED",
- "DUPLICATE_TARGET_GROUP",
- "MESSAGE_UNSUPPORTED",
- "MESSAGE_AMBIGUOUS",
- "ENDPOINT_DISABLED",
- "ENDPOINT_ROUTE_CHANGED",
- "ENDPOINT_HAS_DEPENDENCIES",
- "ENDPOINT_EVENT_SUBSCRIPTIONS_ACTIVE",
- "ENDPOINT_COMMITTED_CLEANUP_PENDING",
- "DEEP_QUERY_FAILED",
- "PROVIDER_NO_STATE",
- "EVENT_MANAGEMENT_DISABLED",
- "SUBSCRIPTION_IDENTITY_IMMUTABLE",
- "UNSUPPORTED_MEDIA_TYPE",
- "EVENT_PAYLOAD_TOO_LARGE",
- "REQUEST_BODY_TOO_LARGE",
- "EVENT_IDENTITY_CONFLICT",
- "EVENT_INGRESS_QUOTA_EXCEEDED",
- "EVENT_RECEIPT_EXPIRED",
- "EVENT_STORAGE_UNAVAILABLE",
- "EVENT_DEAD_LETTER_NOT_FOUND",
- "EVENT_REDRIVE_CONFLICT",
- "EVENT_REDRIVE_EXPIRED",
- "RECEIPT_CONTEXT_EXPIRED",
- "EVENT_MAINTENANCE_INCOMPLETE",
- "UNKNOWN_INTERFACE",
- "INVALID_CONFIGURATION",
- "INVALID_PLUGIN_MANIFEST",
- "INVALID_ATTRIBUTE",
- "INVALID_PROVIDER_MESSAGE",
- "UNDECLARED_CAPABILITY",
- "PLUGIN_ROUTE_ID_CONFLICT",
- "UNRESOLVED_REFERENCE",
- "INVALID_RELATIONSHIP",
- "RELATIONSHIP_CYCLE",
- "MULTIPLE_PARENTS",
- "FLOW_VALIDATION_FAILED",
- "PROVIDER_SYNC_UNSUPPORTED"
- ],
- "type": "string"
- },
- "family": {
- "description": "The broad class of an error. The family decides the HTTP status of a REST error, so clients can handle every code of a family alike.",
- "enum": [
- "NOT_FOUND",
- "BAD_REQUEST",
- "UNAUTHORIZED",
- "FORBIDDEN",
- "CONFLICT",
- "GONE",
- "PRECONDITION_FAILED",
- "PRECONDITION_REQUIRED",
- "PAYLOAD_TOO_LARGE",
- "UNSUPPORTED_MEDIA_TYPE",
- "UNPROCESSABLE_ENTITY",
- "LOCKED",
- "TOO_MANY_REQUESTS",
- "BAD_GATEWAY",
- "SERVICE_UNAVAILABLE",
- "GATEWAY_TIMEOUT",
- "NOT_IMPLEMENTED",
- "INTERNAL_SERVER_ERROR",
- "REQUEST_INVALID",
- "AUTHENTICATION",
- "PERMISSION",
- "ENDPOINT_NOT_FOUND",
- "ENDPOINT_STATE_CONFLICT",
- "ENDPOINT_UNAVAILABLE",
- "RATE_LIMIT",
- "PROVIDER_BAD_RESPONSE",
- "PROVIDER_UNAVAILABLE",
- "PROVIDER_TIMEOUT"
- ],
- "type": "string"
- },
- "interface": {
- "description": "Canonical capability interface name the failure applies to, when the failure is interface-specific.",
- "type": "string"
- },
- "message": {
- "description": "Plain-language description of the failure and the suggested fix.",
- "type": "string"
- },
- "pluginRouteId": {
- "description": "Plugin-owned identifier of the rejected route or group route. Set unless the item is a relationship.",
- "type": "string"
- },
- "relationshipExternalId": {
- "description": "Plugin-owned `externalId` of the rejected relationship. Set only for relationship items.",
- "type": "string"
- },
- "status": {
- "description": "HTTP-equivalent status code of the item failure.",
- "maximum": 599,
- "minimum": 400,
- "type": "integer"
- },
- "version": {
- "description": "Declared capability interface version the failure applies to, when the failure is interface-specific.",
- "type": "string"
- }
- },
- "required": [
- "code",
- "family",
- "status",
- "message"
- ],
- "type": "object"
- },
- "type": "array"
- },
- "family": {
- "description": "The broad class of an error. The family decides the HTTP status of a REST error, so clients can handle every code of a family alike.",
- "enum": [
- "NOT_FOUND",
- "BAD_REQUEST",
- "UNAUTHORIZED",
- "FORBIDDEN",
- "CONFLICT",
- "GONE",
- "PRECONDITION_FAILED",
- "PRECONDITION_REQUIRED",
- "PAYLOAD_TOO_LARGE",
- "UNSUPPORTED_MEDIA_TYPE",
- "UNPROCESSABLE_ENTITY",
- "LOCKED",
- "TOO_MANY_REQUESTS",
- "BAD_GATEWAY",
- "SERVICE_UNAVAILABLE",
- "GATEWAY_TIMEOUT",
- "NOT_IMPLEMENTED",
- "INTERNAL_SERVER_ERROR",
- "REQUEST_INVALID",
- "AUTHENTICATION",
- "PERMISSION",
- "ENDPOINT_NOT_FOUND",
- "ENDPOINT_STATE_CONFLICT",
- "ENDPOINT_UNAVAILABLE",
- "RATE_LIMIT",
- "PROVIDER_BAD_RESPONSE",
- "PROVIDER_UNAVAILABLE",
- "PROVIDER_TIMEOUT"
- ],
- "type": "string"
- },
- "message": {
- "description": "Plain-language description of the failure and the suggested next action.",
- "type": "string"
- }
- },
- "required": [
- "family",
- "code",
- "message"
- ],
- "type": "object"
- },
- "freshness": {
- "description": "Whether the value is current enough to present as the device's present state.\n\n`FRESH`: the provider reported a sample within the last 30 seconds, or a\nforced refresh (`forceDeviceAttributeQuery=true` or `forceDeviceQuery`) read the\nprovider during this request and the provider reported no sample time.\n\n`STALE`: the value is older than 30 seconds, came from stored state, or is a\nprovider's own last known value. A forced refresh cannot make a provider's old\nsample newer: when the provider (for example a thermostat reached through a\nvoice-assistant account) answers with the sample it already holds, the value\nkeeps its original `sampledAt` and is `STALE`. Report the value together with\n`sampledAt`, never as the present reading.\n",
- "enum": [
- "FRESH",
- "STALE"
- ],
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "retrievability": {
- "description": "Whether the serving route supports retrieving this attribute.",
- "enum": [
- "RETRIEVABLE",
- "NOT_RETRIEVABLE"
- ],
- "type": "string"
- },
- "sampledAt": {
- "format": "date-time",
- "type": "string"
- },
- "value": {
- "additionalProperties": true,
- "type": "object"
- }
- },
- "required": [
- "name",
- "retrievability",
- "autoUpdateFrequency"
- ],
- "type": "object"
- }
- ]
- },
- "type": "array"
- },
- "configuration": {
- "type": "object"
- },
- "messages": {
- "items": {
- "properties": {
- "id": {
- "type": "string"
- },
- "name": {
- "type": "string"
- }
- },
- "required": [
- "id",
- "name"
- ],
- "type": "object"
- },
- "type": "array"
- },
- "name": {
- "type": "string"
- },
- "outboundMessages": {
- "description": "Declared outbound message types, including results and events. Not every command returns a correlated result. These IDs cannot be sent as commands.",
- "items": {
- "properties": {
- "id": {
- "type": "string"
- },
- "name": {
- "type": "string"
- }
- },
- "required": [
- "id",
- "name"
- ],
- "type": "object"
- },
- "type": "array"
- },
- "version": {
- "type": "string"
- }
- },
- "required": [
- "name",
- "version",
- "messages",
- "attributes"
- ],
- "type": "object"
- },
- "type": "array"
- },
- "manufacturer": {
- "properties": {
- "type": {
- "type": "string"
- },
- "value": {
- "type": "string"
- }
- },
- "required": [
- "type",
- "value"
- ],
- "type": "object"
- },
- "model": {
- "properties": {
- "type": {
- "type": "string"
- },
- "value": {
- "type": "string"
- }
- },
- "required": [
- "type",
- "value"
- ],
- "type": "object"
- },
- "name": {
- "properties": {
- "type": {
- "type": "string"
- },
- "value": {
- "type": "string"
- }
- },
- "required": [
- "type",
- "value"
- ],
- "type": "object"
- },
- "parentEndpointId": {
- "type": "string"
- },
- "routes": {
- "items": {
- "properties": {
- "id": {
- "type": "string"
- },
- "interfaces": {
- "items": {
- "properties": {
- "attributes": {
- "items": {
- "oneOf": [
- {
- "additionalProperties": false,
- "properties": {
- "name": {
- "type": "string"
- }
- },
- "required": [
- "name"
- ],
- "type": "object"
- },
- {
- "additionalProperties": false,
- "properties": {
- "autoUpdateFrequency": {
- "description": "Declared frequency at which the serving route automatically updates this attribute.",
- "enum": [
- "REALTIME",
- "MINUTES",
- "HOURLY",
- "DAILY",
- "NEVER"
- ],
- "type": "string"
- },
- "error": {
- "description": "The one Port OS error shape, returned by every REST error response and every MCP tool error. `code` names the specific failure and `family` its broad class; both are closed enums, so clients branch on them and show `message`, which says what failed and what to do next.",
- "properties": {
- "code": {
- "description": "The specific error, one of a closed set of Port OS codes. Every REST error body, MCP tool error, batch item error and discovery item error uses this enum; each code belongs to an `ErrorFamily` that decides its HTTP status. Provider-specific codes are never codes: they travel in `details.providerCode`. New failure kinds are added here, never as free strings.",
- "enum": [
- "BAD_REQUEST",
- "UNAUTHORIZED",
- "FORBIDDEN",
- "INSUFFICIENT_SCOPE",
- "NOT_FOUND",
- "CONFLICT",
- "UNPROCESSABLE_ENTITY",
- "UNSUPPORTED_OPERATION",
- "TOO_MANY_REQUESTS",
- "SERVICE_UNAVAILABLE",
- "NOT_IMPLEMENTED",
- "INTERNAL",
- "CHECKSUM_MISMATCH",
- "FILE_TOO_LARGE",
- "STORAGE_UNAVAILABLE",
- "INSUFFICIENT_PERMISSIONS",
- "INVALID_FILE_TYPE",
- "QUOTA_EXCEEDED",
- "CONCURRENT_MODIFICATION",
- "ENDPOINT_UNREACHABLE",
- "BRIDGE_UNREACHABLE",
- "CLOUD_CONTROL_DISABLED",
- "ENDPOINT_BUSY",
- "ENDPOINT_LOW_POWER",
- "AUTHORIZATION_CREDENTIAL_INVALID",
- "AUTHORIZATION_CREDENTIAL_EXPIRED",
- "INVALID_DIRECTIVE",
- "INVALID_VALUE",
- "VALUE_OUT_OF_RANGE",
- "NOT_SUPPORTED_IN_CURRENT_MODE",
- "RATE_LIMIT_EXCEEDED",
- "PROVIDER_SERVICE_UNAVAILABLE",
- "PROVIDER_TIMEOUT",
- "PROVIDER_INTERNAL_ERROR",
- "INVALID_PROVIDER_RESPONSE",
- "OUTCOME_UNKNOWN",
- "PRECONDITION_FAILED",
- "AUTH_LINK_NOT_READY",
- "AUTH_LINK_NOT_DISCONNECTABLE",
- "PRECONDITION_REQUIRED",
- "IDEMPOTENCY_KEY_REQUIRED",
- "IDEMPOTENCY_KEY_REUSED",
- "IDEMPOTENCY_KEY_IN_FLIGHT",
- "IDEMPOTENCY_KEY_INVALID",
- "GROUP_MERGED",
- "MULTI_ROOM_UNSUPPORTED",
- "MAP_NOT_ACTIVE",
- "TARGET_UNSUPPORTED",
- "TARGET_AMBIGUOUS",
- "TARGET_GROUP_NOT_FOUND",
- "TARGET_GROUP_DISABLED",
- "DUPLICATE_TARGET_GROUP",
- "MESSAGE_UNSUPPORTED",
- "MESSAGE_AMBIGUOUS",
- "ENDPOINT_DISABLED",
- "ENDPOINT_ROUTE_CHANGED",
- "ENDPOINT_HAS_DEPENDENCIES",
- "ENDPOINT_EVENT_SUBSCRIPTIONS_ACTIVE",
- "ENDPOINT_COMMITTED_CLEANUP_PENDING",
- "DEEP_QUERY_FAILED",
- "PROVIDER_NO_STATE",
- "EVENT_MANAGEMENT_DISABLED",
- "SUBSCRIPTION_IDENTITY_IMMUTABLE",
- "UNSUPPORTED_MEDIA_TYPE",
- "EVENT_PAYLOAD_TOO_LARGE",
- "REQUEST_BODY_TOO_LARGE",
- "EVENT_IDENTITY_CONFLICT",
- "EVENT_INGRESS_QUOTA_EXCEEDED",
- "EVENT_RECEIPT_EXPIRED",
- "EVENT_STORAGE_UNAVAILABLE",
- "EVENT_DEAD_LETTER_NOT_FOUND",
- "EVENT_REDRIVE_CONFLICT",
- "EVENT_REDRIVE_EXPIRED",
- "RECEIPT_CONTEXT_EXPIRED",
- "EVENT_MAINTENANCE_INCOMPLETE",
- "UNKNOWN_INTERFACE",
- "INVALID_CONFIGURATION",
- "INVALID_PLUGIN_MANIFEST",
- "INVALID_ATTRIBUTE",
- "INVALID_PROVIDER_MESSAGE",
- "UNDECLARED_CAPABILITY",
- "PLUGIN_ROUTE_ID_CONFLICT",
- "UNRESOLVED_REFERENCE",
- "INVALID_RELATIONSHIP",
- "RELATIONSHIP_CYCLE",
- "MULTIPLE_PARENTS",
- "FLOW_VALIDATION_FAILED",
- "PROVIDER_SYNC_UNSUPPORTED"
- ],
- "type": "string"
- },
- "details": {
- "description": "Optional typed context for an error. Fields are additive and only populated when the error can safely expose that context to API clients.\n",
- "properties": {
- "actual": {
- "description": "String representation of the submitted value when the plugin can safely report it.",
- "type": "string"
- },
- "correlationId": {
- "description": "Provider or plugin correlation ID useful for support.",
- "type": "string"
- },
- "correlationToken": {
- "description": "Token that correlates an outcome-unknown dispatch with its eventual result.",
- "type": "string"
- },
- "currentMode": {
- "description": "Current endpoint mode when `code` is `NOT_SUPPORTED_IN_CURRENT_MODE`.",
- "type": "string"
- },
- "directive": {
- "description": "Message namespace and name or provider directive that failed.",
- "type": "string"
- },
- "discoveryEndpointId": {
- "description": "Port OS provider endpoint (type ENDPOINT_PLUGIN) of the connection to send `discover-routes` to when `code` is `TARGET_UNSUPPORTED` because the route must be rediscovered.",
- "type": "string"
- },
- "endpointId": {
- "description": "Port OS endpoint ID involved in the failed dispatch.",
- "type": "string"
- },
- "fieldErrors": {
- "description": "The request fields that were rejected, when the error is about the request's content.",
- "items": {
- "description": "One rejected request field of an error.",
- "properties": {
- "field": {
- "description": "Name or JSON path of the rejected field.",
- "type": "string"
- },
- "reason": {
- "description": "Why the field was rejected and what an accepted value looks like.",
- "type": "string"
- }
- },
- "required": [
- "field",
- "reason"
- ],
- "type": "object"
- },
- "type": "array"
- },
- "maximum": {
- "description": "Maximum accepted value when `code` is `VALUE_OUT_OF_RANGE`.",
- "type": "number"
- },
- "minimum": {
- "description": "Minimum accepted value when `code` is `VALUE_OUT_OF_RANGE`.",
- "type": "number"
- },
- "parameter": {
- "description": "Request parameter or capability value that caused the failure.",
- "type": "string"
- },
- "pluginId": {
- "description": "Port OS plugin ID that reported the failure.",
- "type": "string"
- },
- "pluginRouteId": {
- "description": "Plugin-owned route identifier involved in the failed dispatch.",
- "type": "string"
- },
- "provider": {
- "description": "Third-party provider or bridge name that reported the failure.",
- "type": "string"
- },
- "providerCode": {
- "description": "The third-party provider's own error code, for support. It is opaque and provider-specific; branch on `code` and `family` instead.",
- "type": "string"
- },
- "retryAfterSeconds": {
- "description": "Suggested retry delay for rate-limit or provider-unavailable failures.",
- "minimum": 0,
- "type": "integer"
- }
- },
- "type": "object"
- },
- "errors": {
- "description": "Every rejected item when a request that is validated item by item and applied atomically fails, such as a discovery `SynchronizationRequest` whose routes, group routes or relationships are rejected. Omitted for single-item failures.\n",
- "items": {
- "description": "One rejected discovery item of a `SynchronizationRequest`, keyed by the plugin-owned identity of the rejected item: `pluginRouteId` for a route or group route, or `relationshipExternalId` for a relationship. Exactly one of the two is set. It shares the `code`, `family`, `status` and `message` fields of `BatchItemError`; discovery items are keyed by plugin-owned identity because they carry no `requestId`. A request with any rejected item is rejected as a whole and lists every rejected item.\n",
- "properties": {
- "code": {
- "description": "The specific error, one of a closed set of Port OS codes. Every REST error body, MCP tool error, batch item error and discovery item error uses this enum; each code belongs to an `ErrorFamily` that decides its HTTP status. Provider-specific codes are never codes: they travel in `details.providerCode`. New failure kinds are added here, never as free strings.",
- "enum": [
- "BAD_REQUEST",
- "UNAUTHORIZED",
- "FORBIDDEN",
- "INSUFFICIENT_SCOPE",
- "NOT_FOUND",
- "CONFLICT",
- "UNPROCESSABLE_ENTITY",
- "UNSUPPORTED_OPERATION",
- "TOO_MANY_REQUESTS",
- "SERVICE_UNAVAILABLE",
- "NOT_IMPLEMENTED",
- "INTERNAL",
- "CHECKSUM_MISMATCH",
- "FILE_TOO_LARGE",
- "STORAGE_UNAVAILABLE",
- "INSUFFICIENT_PERMISSIONS",
- "INVALID_FILE_TYPE",
- "QUOTA_EXCEEDED",
- "CONCURRENT_MODIFICATION",
- "ENDPOINT_UNREACHABLE",
- "BRIDGE_UNREACHABLE",
- "CLOUD_CONTROL_DISABLED",
- "ENDPOINT_BUSY",
- "ENDPOINT_LOW_POWER",
- "AUTHORIZATION_CREDENTIAL_INVALID",
- "AUTHORIZATION_CREDENTIAL_EXPIRED",
- "INVALID_DIRECTIVE",
- "INVALID_VALUE",
- "VALUE_OUT_OF_RANGE",
- "NOT_SUPPORTED_IN_CURRENT_MODE",
- "RATE_LIMIT_EXCEEDED",
- "PROVIDER_SERVICE_UNAVAILABLE",
- "PROVIDER_TIMEOUT",
- "PROVIDER_INTERNAL_ERROR",
- "INVALID_PROVIDER_RESPONSE",
- "OUTCOME_UNKNOWN",
- "PRECONDITION_FAILED",
- "AUTH_LINK_NOT_READY",
- "AUTH_LINK_NOT_DISCONNECTABLE",
- "PRECONDITION_REQUIRED",
- "IDEMPOTENCY_KEY_REQUIRED",
- "IDEMPOTENCY_KEY_REUSED",
- "IDEMPOTENCY_KEY_IN_FLIGHT",
- "IDEMPOTENCY_KEY_INVALID",
- "GROUP_MERGED",
- "MULTI_ROOM_UNSUPPORTED",
- "MAP_NOT_ACTIVE",
- "TARGET_UNSUPPORTED",
- "TARGET_AMBIGUOUS",
- "TARGET_GROUP_NOT_FOUND",
- "TARGET_GROUP_DISABLED",
- "DUPLICATE_TARGET_GROUP",
- "MESSAGE_UNSUPPORTED",
- "MESSAGE_AMBIGUOUS",
- "ENDPOINT_DISABLED",
- "ENDPOINT_ROUTE_CHANGED",
- "ENDPOINT_HAS_DEPENDENCIES",
- "ENDPOINT_EVENT_SUBSCRIPTIONS_ACTIVE",
- "ENDPOINT_COMMITTED_CLEANUP_PENDING",
- "DEEP_QUERY_FAILED",
- "PROVIDER_NO_STATE",
- "EVENT_MANAGEMENT_DISABLED",
- "SUBSCRIPTION_IDENTITY_IMMUTABLE",
- "UNSUPPORTED_MEDIA_TYPE",
- "EVENT_PAYLOAD_TOO_LARGE",
- "REQUEST_BODY_TOO_LARGE",
- "EVENT_IDENTITY_CONFLICT",
- "EVENT_INGRESS_QUOTA_EXCEEDED",
- "EVENT_RECEIPT_EXPIRED",
- "EVENT_STORAGE_UNAVAILABLE",
- "EVENT_DEAD_LETTER_NOT_FOUND",
- "EVENT_REDRIVE_CONFLICT",
- "EVENT_REDRIVE_EXPIRED",
- "RECEIPT_CONTEXT_EXPIRED",
- "EVENT_MAINTENANCE_INCOMPLETE",
- "UNKNOWN_INTERFACE",
- "INVALID_CONFIGURATION",
- "INVALID_PLUGIN_MANIFEST",
- "INVALID_ATTRIBUTE",
- "INVALID_PROVIDER_MESSAGE",
- "UNDECLARED_CAPABILITY",
- "PLUGIN_ROUTE_ID_CONFLICT",
- "UNRESOLVED_REFERENCE",
- "INVALID_RELATIONSHIP",
- "RELATIONSHIP_CYCLE",
- "MULTIPLE_PARENTS",
- "FLOW_VALIDATION_FAILED",
- "PROVIDER_SYNC_UNSUPPORTED"
- ],
- "type": "string"
- },
- "family": {
- "description": "The broad class of an error. The family decides the HTTP status of a REST error, so clients can handle every code of a family alike.",
- "enum": [
- "NOT_FOUND",
- "BAD_REQUEST",
- "UNAUTHORIZED",
- "FORBIDDEN",
- "CONFLICT",
- "GONE",
- "PRECONDITION_FAILED",
- "PRECONDITION_REQUIRED",
- "PAYLOAD_TOO_LARGE",
- "UNSUPPORTED_MEDIA_TYPE",
- "UNPROCESSABLE_ENTITY",
- "LOCKED",
- "TOO_MANY_REQUESTS",
- "BAD_GATEWAY",
- "SERVICE_UNAVAILABLE",
- "GATEWAY_TIMEOUT",
- "NOT_IMPLEMENTED",
- "INTERNAL_SERVER_ERROR",
- "REQUEST_INVALID",
- "AUTHENTICATION",
- "PERMISSION",
- "ENDPOINT_NOT_FOUND",
- "ENDPOINT_STATE_CONFLICT",
- "ENDPOINT_UNAVAILABLE",
- "RATE_LIMIT",
- "PROVIDER_BAD_RESPONSE",
- "PROVIDER_UNAVAILABLE",
- "PROVIDER_TIMEOUT"
- ],
- "type": "string"
- },
- "interface": {
- "description": "Canonical capability interface name the failure applies to, when the failure is interface-specific.",
- "type": "string"
- },
- "message": {
- "description": "Plain-language description of the failure and the suggested fix.",
- "type": "string"
- },
- "pluginRouteId": {
- "description": "Plugin-owned identifier of the rejected route or group route. Set unless the item is a relationship.",
- "type": "string"
- },
- "relationshipExternalId": {
- "description": "Plugin-owned `externalId` of the rejected relationship. Set only for relationship items.",
- "type": "string"
- },
- "status": {
- "description": "HTTP-equivalent status code of the item failure.",
- "maximum": 599,
- "minimum": 400,
- "type": "integer"
- },
- "version": {
- "description": "Declared capability interface version the failure applies to, when the failure is interface-specific.",
- "type": "string"
- }
- },
- "required": [
- "code",
- "family",
- "status",
- "message"
- ],
- "type": "object"
- },
- "type": "array"
- },
- "family": {
- "description": "The broad class of an error. The family decides the HTTP status of a REST error, so clients can handle every code of a family alike.",
- "enum": [
- "NOT_FOUND",
- "BAD_REQUEST",
- "UNAUTHORIZED",
- "FORBIDDEN",
- "CONFLICT",
- "GONE",
- "PRECONDITION_FAILED",
- "PRECONDITION_REQUIRED",
- "PAYLOAD_TOO_LARGE",
- "UNSUPPORTED_MEDIA_TYPE",
- "UNPROCESSABLE_ENTITY",
- "LOCKED",
- "TOO_MANY_REQUESTS",
- "BAD_GATEWAY",
- "SERVICE_UNAVAILABLE",
- "GATEWAY_TIMEOUT",
- "NOT_IMPLEMENTED",
- "INTERNAL_SERVER_ERROR",
- "REQUEST_INVALID",
- "AUTHENTICATION",
- "PERMISSION",
- "ENDPOINT_NOT_FOUND",
- "ENDPOINT_STATE_CONFLICT",
- "ENDPOINT_UNAVAILABLE",
- "RATE_LIMIT",
- "PROVIDER_BAD_RESPONSE",
- "PROVIDER_UNAVAILABLE",
- "PROVIDER_TIMEOUT"
- ],
- "type": "string"
- },
- "message": {
- "description": "Plain-language description of the failure and the suggested next action.",
- "type": "string"
- }
- },
- "required": [
- "family",
- "code",
- "message"
- ],
- "type": "object"
- },
- "freshness": {
- "description": "Whether the value is current enough to present as the device's present state.\n\n`FRESH`: the provider reported a sample within the last 30 seconds, or a\nforced refresh (`forceDeviceAttributeQuery=true` or `forceDeviceQuery`) read the\nprovider during this request and the provider reported no sample time.\n\n`STALE`: the value is older than 30 seconds, came from stored state, or is a\nprovider's own last known value. A forced refresh cannot make a provider's old\nsample newer: when the provider (for example a thermostat reached through a\nvoice-assistant account) answers with the sample it already holds, the value\nkeeps its original `sampledAt` and is `STALE`. Report the value together with\n`sampledAt`, never as the present reading.\n",
- "enum": [
- "FRESH",
- "STALE"
- ],
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "retrievability": {
- "description": "Whether the serving route supports retrieving this attribute.",
- "enum": [
- "RETRIEVABLE",
- "NOT_RETRIEVABLE"
- ],
- "type": "string"
- },
- "sampledAt": {
- "format": "date-time",
- "type": "string"
- },
- "value": {
- "additionalProperties": true,
- "type": "object"
- }
- },
- "required": [
- "name",
- "retrievability",
- "autoUpdateFrequency"
- ],
- "type": "object"
- }
- ]
- },
- "type": "array"
- },
- "configuration": {
- "type": "object"
- },
- "messages": {
- "items": {
- "properties": {
- "id": {
- "type": "string"
- },
- "name": {
- "type": "string"
- }
- },
- "required": [
- "id",
- "name"
- ],
- "type": "object"
- },
- "type": "array"
- },
- "name": {
- "type": "string"
- },
- "outboundMessages": {
- "description": "Declared outbound message types, including results and events. Not every command returns a correlated result. These IDs cannot be sent as commands.",
- "items": {
- "properties": {
- "id": {
- "type": "string"
- },
- "name": {
- "type": "string"
- }
- },
- "required": [
- "id",
- "name"
- ],
- "type": "object"
- },
- "type": "array"
- },
- "version": {
- "type": "string"
- }
- },
- "required": [
- "name",
- "version",
- "messages",
- "attributes"
- ],
- "type": "object"
- },
- "type": "array"
- },
- "name": {
- "type": "string"
- },
- "providerId": {
- "type": "string"
- },
- "providerName": {
- "type": "string"
- }
- },
- "required": [
- "id",
- "providerId",
- "providerName",
- "interfaces"
- ],
- "type": "object"
- },
- "type": "array"
- },
- "serialNumber": {
- "properties": {
- "type": {
- "type": "string"
- },
- "value": {
- "type": "string"
- }
- },
- "required": [
- "type",
- "value"
- ],
- "type": "object"
- },
- "type": {
- "type": "string"
- }
- },
- "required": [
- "id",
- "name",
- "type",
- "enablement",
- "interfaces"
- ],
- "type": "object"
- },
- "type": "array"
- }
- },
- "required": [
- "results"
- ],
- "type": "object"
- },
- {
- "additionalProperties": false,
- "description": "The one Port OS error shape, returned by every REST error response and every MCP tool error. `code` names the specific failure and `family` its broad class; both are closed enums, so clients branch on them and show `message`, which says what failed and what to do next.",
- "properties": {
- "code": {
- "description": "The specific error, one of a closed set of Port OS codes. Every REST error body, MCP tool error, batch item error and discovery item error uses this enum; each code belongs to an `ErrorFamily` that decides its HTTP status. Provider-specific codes are never codes: they travel in `details.providerCode`. New failure kinds are added here, never as free strings.",
- "enum": [
- "BAD_REQUEST",
- "UNAUTHORIZED",
- "FORBIDDEN",
- "INSUFFICIENT_SCOPE",
- "NOT_FOUND",
- "CONFLICT",
- "UNPROCESSABLE_ENTITY",
- "UNSUPPORTED_OPERATION",
- "TOO_MANY_REQUESTS",
- "SERVICE_UNAVAILABLE",
- "NOT_IMPLEMENTED",
- "INTERNAL",
- "CHECKSUM_MISMATCH",
- "FILE_TOO_LARGE",
- "STORAGE_UNAVAILABLE",
- "INSUFFICIENT_PERMISSIONS",
- "INVALID_FILE_TYPE",
- "QUOTA_EXCEEDED",
- "CONCURRENT_MODIFICATION",
- "ENDPOINT_UNREACHABLE",
- "BRIDGE_UNREACHABLE",
- "CLOUD_CONTROL_DISABLED",
- "ENDPOINT_BUSY",
- "ENDPOINT_LOW_POWER",
- "AUTHORIZATION_CREDENTIAL_INVALID",
- "AUTHORIZATION_CREDENTIAL_EXPIRED",
- "INVALID_DIRECTIVE",
- "INVALID_VALUE",
- "VALUE_OUT_OF_RANGE",
- "NOT_SUPPORTED_IN_CURRENT_MODE",
- "RATE_LIMIT_EXCEEDED",
- "PROVIDER_SERVICE_UNAVAILABLE",
- "PROVIDER_TIMEOUT",
- "PROVIDER_INTERNAL_ERROR",
- "INVALID_PROVIDER_RESPONSE",
- "OUTCOME_UNKNOWN",
- "PRECONDITION_FAILED",
- "AUTH_LINK_NOT_READY",
- "AUTH_LINK_NOT_DISCONNECTABLE",
- "PRECONDITION_REQUIRED",
- "IDEMPOTENCY_KEY_REQUIRED",
- "IDEMPOTENCY_KEY_REUSED",
- "IDEMPOTENCY_KEY_IN_FLIGHT",
- "IDEMPOTENCY_KEY_INVALID",
- "GROUP_MERGED",
- "MULTI_ROOM_UNSUPPORTED",
- "MAP_NOT_ACTIVE",
- "TARGET_UNSUPPORTED",
- "TARGET_AMBIGUOUS",
- "TARGET_GROUP_NOT_FOUND",
- "TARGET_GROUP_DISABLED",
- "DUPLICATE_TARGET_GROUP",
- "MESSAGE_UNSUPPORTED",
- "MESSAGE_AMBIGUOUS",
- "ENDPOINT_DISABLED",
- "ENDPOINT_ROUTE_CHANGED",
- "ENDPOINT_HAS_DEPENDENCIES",
- "ENDPOINT_EVENT_SUBSCRIPTIONS_ACTIVE",
- "ENDPOINT_COMMITTED_CLEANUP_PENDING",
- "DEEP_QUERY_FAILED",
- "PROVIDER_NO_STATE",
- "EVENT_MANAGEMENT_DISABLED",
- "SUBSCRIPTION_IDENTITY_IMMUTABLE",
- "UNSUPPORTED_MEDIA_TYPE",
- "EVENT_PAYLOAD_TOO_LARGE",
- "REQUEST_BODY_TOO_LARGE",
- "EVENT_IDENTITY_CONFLICT",
- "EVENT_INGRESS_QUOTA_EXCEEDED",
- "EVENT_RECEIPT_EXPIRED",
- "EVENT_STORAGE_UNAVAILABLE",
- "EVENT_DEAD_LETTER_NOT_FOUND",
- "EVENT_REDRIVE_CONFLICT",
- "EVENT_REDRIVE_EXPIRED",
- "RECEIPT_CONTEXT_EXPIRED",
- "EVENT_MAINTENANCE_INCOMPLETE",
- "UNKNOWN_INTERFACE",
- "INVALID_CONFIGURATION",
- "INVALID_PLUGIN_MANIFEST",
- "INVALID_ATTRIBUTE",
- "INVALID_PROVIDER_MESSAGE",
- "UNDECLARED_CAPABILITY",
- "PLUGIN_ROUTE_ID_CONFLICT",
- "UNRESOLVED_REFERENCE",
- "INVALID_RELATIONSHIP",
- "RELATIONSHIP_CYCLE",
- "MULTIPLE_PARENTS",
- "FLOW_VALIDATION_FAILED",
- "PROVIDER_SYNC_UNSUPPORTED"
- ],
- "type": "string"
- },
- "details": {
- "description": "Optional typed context for an error. Fields are additive and only populated when the error can safely expose that context to API clients.\n",
- "properties": {
- "actual": {
- "description": "String representation of the submitted value when the plugin can safely report it.",
- "type": "string"
- },
- "correlationId": {
- "description": "Provider or plugin correlation ID useful for support.",
- "type": "string"
- },
- "correlationToken": {
- "description": "Token that correlates an outcome-unknown dispatch with its eventual result.",
- "type": "string"
- },
- "currentMode": {
- "description": "Current endpoint mode when `code` is `NOT_SUPPORTED_IN_CURRENT_MODE`.",
- "type": "string"
- },
- "directive": {
- "description": "Message namespace and name or provider directive that failed.",
- "type": "string"
- },
- "discoveryEndpointId": {
- "description": "Port OS provider endpoint (type ENDPOINT_PLUGIN) of the connection to send `discover-routes` to when `code` is `TARGET_UNSUPPORTED` because the route must be rediscovered.",
- "type": "string"
- },
- "endpointId": {
- "description": "Port OS endpoint ID involved in the failed dispatch.",
- "type": "string"
- },
- "fieldErrors": {
- "description": "The request fields that were rejected, when the error is about the request's content.",
- "items": {
- "description": "One rejected request field of an error.",
- "properties": {
- "field": {
- "description": "Name or JSON path of the rejected field.",
- "type": "string"
- },
- "reason": {
- "description": "Why the field was rejected and what an accepted value looks like.",
- "type": "string"
- }
- },
- "required": [
- "field",
- "reason"
- ],
- "type": "object"
- },
- "type": "array"
- },
- "maximum": {
- "description": "Maximum accepted value when `code` is `VALUE_OUT_OF_RANGE`.",
- "type": "number"
- },
- "minimum": {
- "description": "Minimum accepted value when `code` is `VALUE_OUT_OF_RANGE`.",
- "type": "number"
- },
- "parameter": {
- "description": "Request parameter or capability value that caused the failure.",
- "type": "string"
- },
- "pluginId": {
- "description": "Port OS plugin ID that reported the failure.",
- "type": "string"
- },
- "pluginRouteId": {
- "description": "Plugin-owned route identifier involved in the failed dispatch.",
- "type": "string"
- },
- "provider": {
- "description": "Third-party provider or bridge name that reported the failure.",
- "type": "string"
- },
- "providerCode": {
- "description": "The third-party provider's own error code, for support. It is opaque and provider-specific; branch on `code` and `family` instead.",
- "type": "string"
- },
- "retryAfterSeconds": {
- "description": "Suggested retry delay for rate-limit or provider-unavailable failures.",
- "minimum": 0,
- "type": "integer"
- }
- },
- "type": "object"
- },
- "errors": {
- "description": "Every rejected item when a request that is validated item by item and applied atomically fails, such as a discovery `SynchronizationRequest` whose routes, group routes or relationships are rejected. Omitted for single-item failures.\n",
- "items": {
- "description": "One rejected discovery item of a `SynchronizationRequest`, keyed by the plugin-owned identity of the rejected item: `pluginRouteId` for a route or group route, or `relationshipExternalId` for a relationship. Exactly one of the two is set. It shares the `code`, `family`, `status` and `message` fields of `BatchItemError`; discovery items are keyed by plugin-owned identity because they carry no `requestId`. A request with any rejected item is rejected as a whole and lists every rejected item.\n",
- "properties": {
- "code": {
- "description": "The specific error, one of a closed set of Port OS codes. Every REST error body, MCP tool error, batch item error and discovery item error uses this enum; each code belongs to an `ErrorFamily` that decides its HTTP status. Provider-specific codes are never codes: they travel in `details.providerCode`. New failure kinds are added here, never as free strings.",
- "enum": [
- "BAD_REQUEST",
- "UNAUTHORIZED",
- "FORBIDDEN",
- "INSUFFICIENT_SCOPE",
- "NOT_FOUND",
- "CONFLICT",
- "UNPROCESSABLE_ENTITY",
- "UNSUPPORTED_OPERATION",
- "TOO_MANY_REQUESTS",
- "SERVICE_UNAVAILABLE",
- "NOT_IMPLEMENTED",
- "INTERNAL",
- "CHECKSUM_MISMATCH",
- "FILE_TOO_LARGE",
- "STORAGE_UNAVAILABLE",
- "INSUFFICIENT_PERMISSIONS",
- "INVALID_FILE_TYPE",
- "QUOTA_EXCEEDED",
- "CONCURRENT_MODIFICATION",
- "ENDPOINT_UNREACHABLE",
- "BRIDGE_UNREACHABLE",
- "CLOUD_CONTROL_DISABLED",
- "ENDPOINT_BUSY",
- "ENDPOINT_LOW_POWER",
- "AUTHORIZATION_CREDENTIAL_INVALID",
- "AUTHORIZATION_CREDENTIAL_EXPIRED",
- "INVALID_DIRECTIVE",
- "INVALID_VALUE",
- "VALUE_OUT_OF_RANGE",
- "NOT_SUPPORTED_IN_CURRENT_MODE",
- "RATE_LIMIT_EXCEEDED",
- "PROVIDER_SERVICE_UNAVAILABLE",
- "PROVIDER_TIMEOUT",
- "PROVIDER_INTERNAL_ERROR",
- "INVALID_PROVIDER_RESPONSE",
- "OUTCOME_UNKNOWN",
- "PRECONDITION_FAILED",
- "AUTH_LINK_NOT_READY",
- "AUTH_LINK_NOT_DISCONNECTABLE",
- "PRECONDITION_REQUIRED",
- "IDEMPOTENCY_KEY_REQUIRED",
- "IDEMPOTENCY_KEY_REUSED",
- "IDEMPOTENCY_KEY_IN_FLIGHT",
- "IDEMPOTENCY_KEY_INVALID",
- "GROUP_MERGED",
- "MULTI_ROOM_UNSUPPORTED",
- "MAP_NOT_ACTIVE",
- "TARGET_UNSUPPORTED",
- "TARGET_AMBIGUOUS",
- "TARGET_GROUP_NOT_FOUND",
- "TARGET_GROUP_DISABLED",
- "DUPLICATE_TARGET_GROUP",
- "MESSAGE_UNSUPPORTED",
- "MESSAGE_AMBIGUOUS",
- "ENDPOINT_DISABLED",
- "ENDPOINT_ROUTE_CHANGED",
- "ENDPOINT_HAS_DEPENDENCIES",
- "ENDPOINT_EVENT_SUBSCRIPTIONS_ACTIVE",
- "ENDPOINT_COMMITTED_CLEANUP_PENDING",
- "DEEP_QUERY_FAILED",
- "PROVIDER_NO_STATE",
- "EVENT_MANAGEMENT_DISABLED",
- "SUBSCRIPTION_IDENTITY_IMMUTABLE",
- "UNSUPPORTED_MEDIA_TYPE",
- "EVENT_PAYLOAD_TOO_LARGE",
- "REQUEST_BODY_TOO_LARGE",
- "EVENT_IDENTITY_CONFLICT",
- "EVENT_INGRESS_QUOTA_EXCEEDED",
- "EVENT_RECEIPT_EXPIRED",
- "EVENT_STORAGE_UNAVAILABLE",
- "EVENT_DEAD_LETTER_NOT_FOUND",
- "EVENT_REDRIVE_CONFLICT",
- "EVENT_REDRIVE_EXPIRED",
- "RECEIPT_CONTEXT_EXPIRED",
- "EVENT_MAINTENANCE_INCOMPLETE",
- "UNKNOWN_INTERFACE",
- "INVALID_CONFIGURATION",
- "INVALID_PLUGIN_MANIFEST",
- "INVALID_ATTRIBUTE",
- "INVALID_PROVIDER_MESSAGE",
- "UNDECLARED_CAPABILITY",
- "PLUGIN_ROUTE_ID_CONFLICT",
- "UNRESOLVED_REFERENCE",
- "INVALID_RELATIONSHIP",
- "RELATIONSHIP_CYCLE",
- "MULTIPLE_PARENTS",
- "FLOW_VALIDATION_FAILED",
- "PROVIDER_SYNC_UNSUPPORTED"
- ],
- "type": "string"
- },
- "family": {
- "description": "The broad class of an error. The family decides the HTTP status of a REST error, so clients can handle every code of a family alike.",
- "enum": [
- "NOT_FOUND",
- "BAD_REQUEST",
- "UNAUTHORIZED",
- "FORBIDDEN",
- "CONFLICT",
- "GONE",
- "PRECONDITION_FAILED",
- "PRECONDITION_REQUIRED",
- "PAYLOAD_TOO_LARGE",
- "UNSUPPORTED_MEDIA_TYPE",
- "UNPROCESSABLE_ENTITY",
- "LOCKED",
- "TOO_MANY_REQUESTS",
- "BAD_GATEWAY",
- "SERVICE_UNAVAILABLE",
- "GATEWAY_TIMEOUT",
- "NOT_IMPLEMENTED",
- "INTERNAL_SERVER_ERROR",
- "REQUEST_INVALID",
- "AUTHENTICATION",
- "PERMISSION",
- "ENDPOINT_NOT_FOUND",
- "ENDPOINT_STATE_CONFLICT",
- "ENDPOINT_UNAVAILABLE",
- "RATE_LIMIT",
- "PROVIDER_BAD_RESPONSE",
- "PROVIDER_UNAVAILABLE",
- "PROVIDER_TIMEOUT"
- ],
- "type": "string"
- },
- "interface": {
- "description": "Canonical capability interface name the failure applies to, when the failure is interface-specific.",
- "type": "string"
- },
- "message": {
- "description": "Plain-language description of the failure and the suggested fix.",
- "type": "string"
- },
- "pluginRouteId": {
- "description": "Plugin-owned identifier of the rejected route or group route. Set unless the item is a relationship.",
- "type": "string"
- },
- "relationshipExternalId": {
- "description": "Plugin-owned `externalId` of the rejected relationship. Set only for relationship items.",
- "type": "string"
- },
- "status": {
- "description": "HTTP-equivalent status code of the item failure.",
- "maximum": 599,
- "minimum": 400,
- "type": "integer"
- },
- "version": {
- "description": "Declared capability interface version the failure applies to, when the failure is interface-specific.",
- "type": "string"
- }
- },
- "required": [
- "code",
- "family",
- "status",
- "message"
- ],
- "type": "object"
- },
- "type": "array"
- },
- "family": {
- "description": "The broad class of an error. The family decides the HTTP status of a REST error, so clients can handle every code of a family alike.",
- "enum": [
- "NOT_FOUND",
- "BAD_REQUEST",
- "UNAUTHORIZED",
- "FORBIDDEN",
- "CONFLICT",
- "GONE",
- "PRECONDITION_FAILED",
- "PRECONDITION_REQUIRED",
- "PAYLOAD_TOO_LARGE",
- "UNSUPPORTED_MEDIA_TYPE",
- "UNPROCESSABLE_ENTITY",
- "LOCKED",
- "TOO_MANY_REQUESTS",
- "BAD_GATEWAY",
- "SERVICE_UNAVAILABLE",
- "GATEWAY_TIMEOUT",
- "NOT_IMPLEMENTED",
- "INTERNAL_SERVER_ERROR",
- "REQUEST_INVALID",
- "AUTHENTICATION",
- "PERMISSION",
- "ENDPOINT_NOT_FOUND",
- "ENDPOINT_STATE_CONFLICT",
- "ENDPOINT_UNAVAILABLE",
- "RATE_LIMIT",
- "PROVIDER_BAD_RESPONSE",
- "PROVIDER_UNAVAILABLE",
- "PROVIDER_TIMEOUT"
- ],
- "type": "string"
- },
- "message": {
- "description": "Plain-language description of the failure and the suggested next action.",
- "type": "string"
- }
- },
- "required": [
- "family",
- "code",
- "message"
- ],
- "type": "object"
- }
-]New value: +[
+ {
+ "additionalProperties": false,
+ "properties": {
+ "paginationContext": {
+ "properties": {
+ "nextToken": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "nextToken"
+ ],
+ "type": "object"
+ },
+ "primary": {
+ "description": "The card endpoint_show was asked to lead with. Present only when the call set primary.",
+ "type": "string"
+ },
+ "results": {
+ "items": {
+ "properties": {
+ "cardIds": {
+ "description": "Card ids the device can show as its primary card in endpoint_show. Present only on endpoint_show results.",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "childEndpointIds": {
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "controllableGroups": {
+ "items": {
+ "properties": {
+ "geometry": {
+ "description": "The room outline from the group's stored spatial geometry (cached, never a provider read). Present on every single-endpoint read (endpoint_show or endpoint_query with endpointId), never on lists, and only for rooms whose geometry is usable; rooms without it stay listed. Rooms sharing a frameId are one map. Tiny speckle and excess detail are dropped to keep the result bounded.",
+ "properties": {
+ "coordinateSystem": {
+ "description": "The spatial capability's declared axes. Drawing must flip y when yAxis is UP.",
+ "properties": {
+ "unit": {
+ "type": "string"
+ },
+ "xAxis": {
+ "type": "string"
+ },
+ "yAxis": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "frameId": {
+ "description": "The group route the coordinates are relative to; rooms of one map share it.",
+ "type": "string"
+ },
+ "shape": {
+ "properties": {
+ "coordinates": {
+ "description": "Polygons, each a list of rings of [x, y] points; the first ring is the outline, the others are holes.",
+ "items": {},
+ "type": "array"
+ },
+ "type": {
+ "enum": [
+ "MultiPolygon"
+ ],
+ "type": "string"
+ }
+ },
+ "required": [
+ "type",
+ "coordinates"
+ ],
+ "type": "object"
+ }
+ },
+ "required": [
+ "shape"
+ ],
+ "type": "object"
+ },
+ "groupId": {
+ "type": "string"
+ },
+ "messages": {
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "name": {
+ "type": "string"
+ },
+ "parentPath": {
+ "items": {
+ "properties": {
+ "groupId": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "role": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "groupId",
+ "name"
+ ],
+ "type": "object"
+ },
+ "type": "array"
+ }
+ },
+ "required": [
+ "groupId",
+ "name",
+ "parentPath",
+ "messages"
+ ],
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "description": {
+ "properties": {
+ "type": {
+ "type": "string"
+ },
+ "value": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "type",
+ "value"
+ ],
+ "type": "object"
+ },
+ "enablement": {
+ "enum": [
+ "ENABLED",
+ "DISABLED"
+ ],
+ "type": "string"
+ },
+ "etag": {
+ "description": "Strong version of the writable name, type and enablement document.",
+ "type": "string"
+ },
+ "id": {
+ "type": "string"
+ },
+ "interfaces": {
+ "items": {
+ "properties": {
+ "attributes": {
+ "items": {
+ "oneOf": [
+ {
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "name"
+ ],
+ "type": "object"
+ },
+ {
+ "additionalProperties": false,
+ "properties": {
+ "autoUpdateFrequency": {
+ "description": "Declared frequency at which the serving route automatically updates this attribute.",
+ "enum": [
+ "REALTIME",
+ "MINUTES",
+ "HOURLY",
+ "DAILY",
+ "NEVER"
+ ],
+ "type": "string"
+ },
+ "error": {
+ "description": "The one Port OS error shape, returned by every REST error response and every MCP tool error. `code` names the specific failure and `family` its broad class; both are closed enums, so clients branch on them and show `message`, which says what failed and what to do next.",
+ "properties": {
+ "code": {
+ "description": "The specific error, one of a closed set of Port OS codes. Every REST error body, MCP tool error, batch item error and discovery item error uses this enum; each code belongs to an `ErrorFamily` that decides its HTTP status. Provider-specific codes are never codes: they travel in `details.providerCode`. New failure kinds are added here, never as free strings.",
+ "enum": [
+ "BAD_REQUEST",
+ "UNAUTHORIZED",
+ "FORBIDDEN",
+ "INSUFFICIENT_SCOPE",
+ "NOT_FOUND",
+ "CONFLICT",
+ "UNPROCESSABLE_ENTITY",
+ "UNSUPPORTED_OPERATION",
+ "TOO_MANY_REQUESTS",
+ "SERVICE_UNAVAILABLE",
+ "NOT_IMPLEMENTED",
+ "INTERNAL",
+ "CHECKSUM_MISMATCH",
+ "FILE_TOO_LARGE",
+ "STORAGE_UNAVAILABLE",
+ "INSUFFICIENT_PERMISSIONS",
+ "INVALID_FILE_TYPE",
+ "QUOTA_EXCEEDED",
+ "CONCURRENT_MODIFICATION",
+ "ENDPOINT_UNREACHABLE",
+ "BRIDGE_UNREACHABLE",
+ "CLOUD_CONTROL_DISABLED",
+ "ENDPOINT_BUSY",
+ "ENDPOINT_LOW_POWER",
+ "AUTHORIZATION_CREDENTIAL_INVALID",
+ "AUTHORIZATION_CREDENTIAL_EXPIRED",
+ "INVALID_DIRECTIVE",
+ "INVALID_VALUE",
+ "VALUE_OUT_OF_RANGE",
+ "NOT_SUPPORTED_IN_CURRENT_MODE",
+ "RATE_LIMIT_EXCEEDED",
+ "PROVIDER_SERVICE_UNAVAILABLE",
+ "PROVIDER_TIMEOUT",
+ "PROVIDER_INTERNAL_ERROR",
+ "INVALID_PROVIDER_RESPONSE",
+ "OUTCOME_UNKNOWN",
+ "PRECONDITION_FAILED",
+ "AUTH_LINK_NOT_READY",
+ "AUTH_LINK_NOT_DISCONNECTABLE",
+ "PRECONDITION_REQUIRED",
+ "IDEMPOTENCY_KEY_REQUIRED",
+ "IDEMPOTENCY_KEY_REUSED",
+ "IDEMPOTENCY_KEY_IN_FLIGHT",
+ "IDEMPOTENCY_KEY_INVALID",
+ "GROUP_MERGED",
+ "MULTI_ROOM_UNSUPPORTED",
+ "MAP_NOT_ACTIVE",
+ "TARGET_UNSUPPORTED",
+ "TARGET_AMBIGUOUS",
+ "TARGET_GROUP_NOT_FOUND",
+ "TARGET_GROUP_DISABLED",
+ "DUPLICATE_TARGET_GROUP",
+ "MESSAGE_UNSUPPORTED",
+ "MESSAGE_AMBIGUOUS",
+ "ENDPOINT_DISABLED",
+ "ENDPOINT_ROUTE_CHANGED",
+ "ENDPOINT_HAS_DEPENDENCIES",
+ "ENDPOINT_EVENT_SUBSCRIPTIONS_ACTIVE",
+ "ENDPOINT_COMMITTED_CLEANUP_PENDING",
+ "DEEP_QUERY_FAILED",
+ "PROVIDER_NO_STATE",
+ "EVENT_MANAGEMENT_DISABLED",
+ "SUBSCRIPTION_IDENTITY_IMMUTABLE",
+ "UNSUPPORTED_MEDIA_TYPE",
+ "EVENT_PAYLOAD_TOO_LARGE",
+ "REQUEST_BODY_TOO_LARGE",
+ "EVENT_IDENTITY_CONFLICT",
+ "EVENT_INGRESS_QUOTA_EXCEEDED",
+ "EVENT_RECEIPT_EXPIRED",
+ "EVENT_STORAGE_UNAVAILABLE",
+ "EVENT_DEAD_LETTER_NOT_FOUND",
+ "EVENT_REDRIVE_CONFLICT",
+ "EVENT_REDRIVE_EXPIRED",
+ "RECEIPT_CONTEXT_EXPIRED",
+ "EVENT_MAINTENANCE_INCOMPLETE",
+ "UNKNOWN_INTERFACE",
+ "INVALID_CONFIGURATION",
+ "INVALID_PLUGIN_MANIFEST",
+ "INVALID_ATTRIBUTE",
+ "INVALID_PROVIDER_MESSAGE",
+ "UNDECLARED_CAPABILITY",
+ "PLUGIN_ROUTE_ID_CONFLICT",
+ "UNRESOLVED_REFERENCE",
+ "INVALID_RELATIONSHIP",
+ "RELATIONSHIP_CYCLE",
+ "MULTIPLE_PARENTS",
+ "FLOW_VALIDATION_FAILED",
+ "PROVIDER_SYNC_UNSUPPORTED"
+ ],
+ "type": "string"
+ },
+ "details": {
+ "description": "Optional typed context for an error. Fields are additive and only populated when the error can safely expose that context to API clients.\n",
+ "properties": {
+ "actual": {
+ "description": "String representation of the submitted value when the plugin can safely report it.",
+ "type": "string"
+ },
+ "correlationId": {
+ "description": "Provider or plugin correlation ID useful for support.",
+ "type": "string"
+ },
+ "correlationToken": {
+ "description": "Token that correlates an outcome-unknown dispatch with its eventual result.",
+ "type": "string"
+ },
+ "currentMode": {
+ "description": "Current endpoint mode when `code` is `NOT_SUPPORTED_IN_CURRENT_MODE`.",
+ "type": "string"
+ },
+ "directive": {
+ "description": "Message namespace and name or provider directive that failed.",
+ "type": "string"
+ },
+ "discoveryEndpointId": {
+ "description": "Port OS provider endpoint (type ENDPOINT_PLUGIN) of the connection to send `discover-routes` to when `code` is `TARGET_UNSUPPORTED` because the route must be rediscovered.",
+ "type": "string"
+ },
+ "endpointId": {
+ "description": "Port OS endpoint ID involved in the failed dispatch.",
+ "type": "string"
+ },
+ "fieldErrors": {
+ "description": "The request fields that were rejected, when the error is about the request's content.",
+ "items": {
+ "description": "One rejected request field of an error.",
+ "properties": {
+ "field": {
+ "description": "Name or JSON path of the rejected field.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Why the field was rejected and what an accepted value looks like.",
+ "type": "string"
+ }
+ },
+ "required": [
+ "field",
+ "reason"
+ ],
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "maximum": {
+ "description": "Maximum accepted value when `code` is `VALUE_OUT_OF_RANGE`.",
+ "type": "number"
+ },
+ "minimum": {
+ "description": "Minimum accepted value when `code` is `VALUE_OUT_OF_RANGE`.",
+ "type": "number"
+ },
+ "parameter": {
+ "description": "Request parameter or capability value that caused the failure.",
+ "type": "string"
+ },
+ "pluginId": {
+ "description": "Port OS plugin ID that reported the failure.",
+ "type": "string"
+ },
+ "pluginRouteId": {
+ "description": "Plugin-owned route identifier involved in the failed dispatch.",
+ "type": "string"
+ },
+ "provider": {
+ "description": "Third-party provider or bridge name that reported the failure.",
+ "type": "string"
+ },
+ "providerCode": {
+ "description": "The third-party provider's own error code, for support. It is opaque and provider-specific; branch on `code` and `family` instead.",
+ "type": "string"
+ },
+ "retryAfterSeconds": {
+ "description": "Suggested retry delay for rate-limit or provider-unavailable failures.",
+ "minimum": 0,
+ "type": "integer"
+ }
+ },
+ "type": "object"
+ },
+ "errors": {
+ "description": "Every rejected item when a request that is validated item by item and applied atomically fails, such as a discovery `SynchronizationRequest` whose routes, group routes or relationships are rejected. Omitted for single-item failures.\n",
+ "items": {
+ "description": "One rejected discovery item of a `SynchronizationRequest`, keyed by the plugin-owned identity of the rejected item: `pluginRouteId` for a route or group route, or `relationshipExternalId` for a relationship. Exactly one of the two is set. It shares the `code`, `family`, `status` and `message` fields of `BatchItemError`; discovery items are keyed by plugin-owned identity because they carry no `requestId`. A request with any rejected item is rejected as a whole and lists every rejected item.\n",
+ "properties": {
+ "code": {
+ "description": "The specific error, one of a closed set of Port OS codes. Every REST error body, MCP tool error, batch item error and discovery item error uses this enum; each code belongs to an `ErrorFamily` that decides its HTTP status. Provider-specific codes are never codes: they travel in `details.providerCode`. New failure kinds are added here, never as free strings.",
+ "enum": [
+ "BAD_REQUEST",
+ "UNAUTHORIZED",
+ "FORBIDDEN",
+ "INSUFFICIENT_SCOPE",
+ "NOT_FOUND",
+ "CONFLICT",
+ "UNPROCESSABLE_ENTITY",
+ "UNSUPPORTED_OPERATION",
+ "TOO_MANY_REQUESTS",
+ "SERVICE_UNAVAILABLE",
+ "NOT_IMPLEMENTED",
+ "INTERNAL",
+ "CHECKSUM_MISMATCH",
+ "FILE_TOO_LARGE",
+ "STORAGE_UNAVAILABLE",
+ "INSUFFICIENT_PERMISSIONS",
+ "INVALID_FILE_TYPE",
+ "QUOTA_EXCEEDED",
+ "CONCURRENT_MODIFICATION",
+ "ENDPOINT_UNREACHABLE",
+ "BRIDGE_UNREACHABLE",
+ "CLOUD_CONTROL_DISABLED",
+ "ENDPOINT_BUSY",
+ "ENDPOINT_LOW_POWER",
+ "AUTHORIZATION_CREDENTIAL_INVALID",
+ "AUTHORIZATION_CREDENTIAL_EXPIRED",
+ "INVALID_DIRECTIVE",
+ "INVALID_VALUE",
+ "VALUE_OUT_OF_RANGE",
+ "NOT_SUPPORTED_IN_CURRENT_MODE",
+ "RATE_LIMIT_EXCEEDED",
+ "PROVIDER_SERVICE_UNAVAILABLE",
+ "PROVIDER_TIMEOUT",
+ "PROVIDER_INTERNAL_ERROR",
+ "INVALID_PROVIDER_RESPONSE",
+ "OUTCOME_UNKNOWN",
+ "PRECONDITION_FAILED",
+ "AUTH_LINK_NOT_READY",
+ "AUTH_LINK_NOT_DISCONNECTABLE",
+ "PRECONDITION_REQUIRED",
+ "IDEMPOTENCY_KEY_REQUIRED",
+ "IDEMPOTENCY_KEY_REUSED",
+ "IDEMPOTENCY_KEY_IN_FLIGHT",
+ "IDEMPOTENCY_KEY_INVALID",
+ "GROUP_MERGED",
+ "MULTI_ROOM_UNSUPPORTED",
+ "MAP_NOT_ACTIVE",
+ "TARGET_UNSUPPORTED",
+ "TARGET_AMBIGUOUS",
+ "TARGET_GROUP_NOT_FOUND",
+ "TARGET_GROUP_DISABLED",
+ "DUPLICATE_TARGET_GROUP",
+ "MESSAGE_UNSUPPORTED",
+ "MESSAGE_AMBIGUOUS",
+ "ENDPOINT_DISABLED",
+ "ENDPOINT_ROUTE_CHANGED",
+ "ENDPOINT_HAS_DEPENDENCIES",
+ "ENDPOINT_EVENT_SUBSCRIPTIONS_ACTIVE",
+ "ENDPOINT_COMMITTED_CLEANUP_PENDING",
+ "DEEP_QUERY_FAILED",
+ "PROVIDER_NO_STATE",
+ "EVENT_MANAGEMENT_DISABLED",
+ "SUBSCRIPTION_IDENTITY_IMMUTABLE",
+ "UNSUPPORTED_MEDIA_TYPE",
+ "EVENT_PAYLOAD_TOO_LARGE",
+ "REQUEST_BODY_TOO_LARGE",
+ "EVENT_IDENTITY_CONFLICT",
+ "EVENT_INGRESS_QUOTA_EXCEEDED",
+ "EVENT_RECEIPT_EXPIRED",
+ "EVENT_STORAGE_UNAVAILABLE",
+ "EVENT_DEAD_LETTER_NOT_FOUND",
+ "EVENT_REDRIVE_CONFLICT",
+ "EVENT_REDRIVE_EXPIRED",
+ "RECEIPT_CONTEXT_EXPIRED",
+ "EVENT_MAINTENANCE_INCOMPLETE",
+ "UNKNOWN_INTERFACE",
+ "INVALID_CONFIGURATION",
+ "INVALID_PLUGIN_MANIFEST",
+ "INVALID_ATTRIBUTE",
+ "INVALID_PROVIDER_MESSAGE",
+ "UNDECLARED_CAPABILITY",
+ "PLUGIN_ROUTE_ID_CONFLICT",
+ "UNRESOLVED_REFERENCE",
+ "INVALID_RELATIONSHIP",
+ "RELATIONSHIP_CYCLE",
+ "MULTIPLE_PARENTS",
+ "FLOW_VALIDATION_FAILED",
+ "PROVIDER_SYNC_UNSUPPORTED"
+ ],
+ "type": "string"
+ },
+ "family": {
+ "description": "The broad class of an error. The family decides the HTTP status of a REST error, so clients can handle every code of a family alike.",
+ "enum": [
+ "NOT_FOUND",
+ "BAD_REQUEST",
+ "UNAUTHORIZED",
+ "FORBIDDEN",
+ "CONFLICT",
+ "GONE",
+ "PRECONDITION_FAILED",
+ "PRECONDITION_REQUIRED",
+ "PAYLOAD_TOO_LARGE",
+ "UNSUPPORTED_MEDIA_TYPE",
+ "UNPROCESSABLE_ENTITY",
+ "LOCKED",
+ "TOO_MANY_REQUESTS",
+ "BAD_GATEWAY",
+ "SERVICE_UNAVAILABLE",
+ "GATEWAY_TIMEOUT",
+ "NOT_IMPLEMENTED",
+ "INTERNAL_SERVER_ERROR",
+ "REQUEST_INVALID",
+ "AUTHENTICATION",
+ "PERMISSION",
+ "ENDPOINT_NOT_FOUND",
+ "ENDPOINT_STATE_CONFLICT",
+ "ENDPOINT_UNAVAILABLE",
+ "RATE_LIMIT",
+ "PROVIDER_BAD_RESPONSE",
+ "PROVIDER_UNAVAILABLE",
+ "PROVIDER_TIMEOUT"
+ ],
+ "type": "string"
+ },
+ "interface": {
+ "description": "Canonical capability interface name the failure applies to, when the failure is interface-specific.",
+ "type": "string"
+ },
+ "message": {
+ "description": "Plain-language description of the failure and the suggested fix.",
+ "type": "string"
+ },
+ "pluginRouteId": {
+ "description": "Plugin-owned identifier of the rejected route or group route. Set unless the item is a relationship.",
+ "type": "string"
+ },
+ "relationshipExternalId": {
+ "description": "Plugin-owned `externalId` of the rejected relationship. Set only for relationship items.",
+ "type": "string"
+ },
+ "status": {
+ "description": "HTTP-equivalent status code of the item failure.",
+ "maximum": 599,
+ "minimum": 400,
+ "type": "integer"
+ },
+ "version": {
+ "description": "Declared capability interface version the failure applies to, when the failure is interface-specific.",
+ "type": "string"
+ }
+ },
+ "required": [
+ "code",
+ "family",
+ "status",
+ "message"
+ ],
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "family": {
+ "description": "The broad class of an error. The family decides the HTTP status of a REST error, so clients can handle every code of a family alike.",
+ "enum": [
+ "NOT_FOUND",
+ "BAD_REQUEST",
+ "UNAUTHORIZED",
+ "FORBIDDEN",
+ "CONFLICT",
+ "GONE",
+ "PRECONDITION_FAILED",
+ "PRECONDITION_REQUIRED",
+ "PAYLOAD_TOO_LARGE",
+ "UNSUPPORTED_MEDIA_TYPE",
+ "UNPROCESSABLE_ENTITY",
+ "LOCKED",
+ "TOO_MANY_REQUESTS",
+ "BAD_GATEWAY",
+ "SERVICE_UNAVAILABLE",
+ "GATEWAY_TIMEOUT",
+ "NOT_IMPLEMENTED",
+ "INTERNAL_SERVER_ERROR",
+ "REQUEST_INVALID",
+ "AUTHENTICATION",
+ "PERMISSION",
+ "ENDPOINT_NOT_FOUND",
+ "ENDPOINT_STATE_CONFLICT",
+ "ENDPOINT_UNAVAILABLE",
+ "RATE_LIMIT",
+ "PROVIDER_BAD_RESPONSE",
+ "PROVIDER_UNAVAILABLE",
+ "PROVIDER_TIMEOUT"
+ ],
+ "type": "string"
+ },
+ "message": {
+ "description": "Plain-language description of the failure and the suggested next action.",
+ "type": "string"
+ }
+ },
+ "required": [
+ "family",
+ "code",
+ "message"
+ ],
+ "type": "object"
+ },
+ "freshness": {
+ "description": "Whether the value is current enough to present as the device's present state.\n\n`FRESH`: the provider reported a sample within the last 30 seconds, or a\nforced refresh (`forceDeviceAttributeQuery=true` or `forceDeviceQuery`) read the\nprovider during this request and the provider reported no sample time.\n\n`STALE`: the value is older than 30 seconds, came from stored state, or is a\nprovider's own last known value. A forced refresh cannot make a provider's old\nsample newer: when the provider (for example a thermostat reached through a\nvoice-assistant account) answers with the sample it already holds, the value\nkeeps its original `sampledAt` and is `STALE`. Report the value together with\n`sampledAt`, never as the present reading.\n",
+ "enum": [
+ "FRESH",
+ "STALE"
+ ],
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "retrievability": {
+ "description": "Whether the serving route supports retrieving this attribute.",
+ "enum": [
+ "RETRIEVABLE",
+ "NOT_RETRIEVABLE"
+ ],
+ "type": "string"
+ },
+ "sampledAt": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "value": {
+ "additionalProperties": true,
+ "type": "object"
+ }
+ },
+ "required": [
+ "name",
+ "retrievability",
+ "autoUpdateFrequency"
+ ],
+ "type": "object"
+ }
+ ]
+ },
+ "type": "array"
+ },
+ "configuration": {
+ "type": "object"
+ },
+ "messages": {
+ "items": {
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "id",
+ "name"
+ ],
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "name": {
+ "type": "string"
+ },
+ "outboundMessages": {
+ "description": "Declared outbound message types, including results and events. Not every command returns a correlated result. These IDs cannot be sent as commands.",
+ "items": {
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "id",
+ "name"
+ ],
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "version": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "name",
+ "version",
+ "messages",
+ "attributes"
+ ],
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "manufacturer": {
+ "properties": {
+ "type": {
+ "type": "string"
+ },
+ "value": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "type",
+ "value"
+ ],
+ "type": "object"
+ },
+ "model": {
+ "properties": {
+ "type": {
+ "type": "string"
+ },
+ "value": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "type",
+ "value"
+ ],
+ "type": "object"
+ },
+ "name": {
+ "properties": {
+ "type": {
+ "type": "string"
+ },
+ "value": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "type",
+ "value"
+ ],
+ "type": "object"
+ },
+ "parentEndpointId": {
+ "type": "string"
+ },
+ "routes": {
+ "items": {
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "interfaces": {
+ "items": {
+ "properties": {
+ "attributes": {
+ "items": {
+ "oneOf": [
+ {
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "name"
+ ],
+ "type": "object"
+ },
+ {
+ "additionalProperties": false,
+ "properties": {
+ "autoUpdateFrequency": {
+ "description": "Declared frequency at which the serving route automatically updates this attribute.",
+ "enum": [
+ "REALTIME",
+ "MINUTES",
+ "HOURLY",
+ "DAILY",
+ "NEVER"
+ ],
+ "type": "string"
+ },
+ "error": {
+ "description": "The one Port OS error shape, returned by every REST error response and every MCP tool error. `code` names the specific failure and `family` its broad class; both are closed enums, so clients branch on them and show `message`, which says what failed and what to do next.",
+ "properties": {
+ "code": {
+ "description": "The specific error, one of a closed set of Port OS codes. Every REST error body, MCP tool error, batch item error and discovery item error uses this enum; each code belongs to an `ErrorFamily` that decides its HTTP status. Provider-specific codes are never codes: they travel in `details.providerCode`. New failure kinds are added here, never as free strings.",
+ "enum": [
+ "BAD_REQUEST",
+ "UNAUTHORIZED",
+ "FORBIDDEN",
+ "INSUFFICIENT_SCOPE",
+ "NOT_FOUND",
+ "CONFLICT",
+ "UNPROCESSABLE_ENTITY",
+ "UNSUPPORTED_OPERATION",
+ "TOO_MANY_REQUESTS",
+ "SERVICE_UNAVAILABLE",
+ "NOT_IMPLEMENTED",
+ "INTERNAL",
+ "CHECKSUM_MISMATCH",
+ "FILE_TOO_LARGE",
+ "STORAGE_UNAVAILABLE",
+ "INSUFFICIENT_PERMISSIONS",
+ "INVALID_FILE_TYPE",
+ "QUOTA_EXCEEDED",
+ "CONCURRENT_MODIFICATION",
+ "ENDPOINT_UNREACHABLE",
+ "BRIDGE_UNREACHABLE",
+ "CLOUD_CONTROL_DISABLED",
+ "ENDPOINT_BUSY",
+ "ENDPOINT_LOW_POWER",
+ "AUTHORIZATION_CREDENTIAL_INVALID",
+ "AUTHORIZATION_CREDENTIAL_EXPIRED",
+ "INVALID_DIRECTIVE",
+ "INVALID_VALUE",
+ "VALUE_OUT_OF_RANGE",
+ "NOT_SUPPORTED_IN_CURRENT_MODE",
+ "RATE_LIMIT_EXCEEDED",
+ "PROVIDER_SERVICE_UNAVAILABLE",
+ "PROVIDER_TIMEOUT",
+ "PROVIDER_INTERNAL_ERROR",
+ "INVALID_PROVIDER_RESPONSE",
+ "OUTCOME_UNKNOWN",
+ "PRECONDITION_FAILED",
+ "AUTH_LINK_NOT_READY",
+ "AUTH_LINK_NOT_DISCONNECTABLE",
+ "PRECONDITION_REQUIRED",
+ "IDEMPOTENCY_KEY_REQUIRED",
+ "IDEMPOTENCY_KEY_REUSED",
+ "IDEMPOTENCY_KEY_IN_FLIGHT",
+ "IDEMPOTENCY_KEY_INVALID",
+ "GROUP_MERGED",
+ "MULTI_ROOM_UNSUPPORTED",
+ "MAP_NOT_ACTIVE",
+ "TARGET_UNSUPPORTED",
+ "TARGET_AMBIGUOUS",
+ "TARGET_GROUP_NOT_FOUND",
+ "TARGET_GROUP_DISABLED",
+ "DUPLICATE_TARGET_GROUP",
+ "MESSAGE_UNSUPPORTED",
+ "MESSAGE_AMBIGUOUS",
+ "ENDPOINT_DISABLED",
+ "ENDPOINT_ROUTE_CHANGED",
+ "ENDPOINT_HAS_DEPENDENCIES",
+ "ENDPOINT_EVENT_SUBSCRIPTIONS_ACTIVE",
+ "ENDPOINT_COMMITTED_CLEANUP_PENDING",
+ "DEEP_QUERY_FAILED",
+ "PROVIDER_NO_STATE",
+ "EVENT_MANAGEMENT_DISABLED",
+ "SUBSCRIPTION_IDENTITY_IMMUTABLE",
+ "UNSUPPORTED_MEDIA_TYPE",
+ "EVENT_PAYLOAD_TOO_LARGE",
+ "REQUEST_BODY_TOO_LARGE",
+ "EVENT_IDENTITY_CONFLICT",
+ "EVENT_INGRESS_QUOTA_EXCEEDED",
+ "EVENT_RECEIPT_EXPIRED",
+ "EVENT_STORAGE_UNAVAILABLE",
+ "EVENT_DEAD_LETTER_NOT_FOUND",
+ "EVENT_REDRIVE_CONFLICT",
+ "EVENT_REDRIVE_EXPIRED",
+ "RECEIPT_CONTEXT_EXPIRED",
+ "EVENT_MAINTENANCE_INCOMPLETE",
+ "UNKNOWN_INTERFACE",
+ "INVALID_CONFIGURATION",
+ "INVALID_PLUGIN_MANIFEST",
+ "INVALID_ATTRIBUTE",
+ "INVALID_PROVIDER_MESSAGE",
+ "UNDECLARED_CAPABILITY",
+ "PLUGIN_ROUTE_ID_CONFLICT",
+ "UNRESOLVED_REFERENCE",
+ "INVALID_RELATIONSHIP",
+ "RELATIONSHIP_CYCLE",
+ "MULTIPLE_PARENTS",
+ "FLOW_VALIDATION_FAILED",
+ "PROVIDER_SYNC_UNSUPPORTED"
+ ],
+ "type": "string"
+ },
+ "details": {
+ "description": "Optional typed context for an error. Fields are additive and only populated when the error can safely expose that context to API clients.\n",
+ "properties": {
+ "actual": {
+ "description": "String representation of the submitted value when the plugin can safely report it.",
+ "type": "string"
+ },
+ "correlationId": {
+ "description": "Provider or plugin correlation ID useful for support.",
+ "type": "string"
+ },
+ "correlationToken": {
+ "description": "Token that correlates an outcome-unknown dispatch with its eventual result.",
+ "type": "string"
+ },
+ "currentMode": {
+ "description": "Current endpoint mode when `code` is `NOT_SUPPORTED_IN_CURRENT_MODE`.",
+ "type": "string"
+ },
+ "directive": {
+ "description": "Message namespace and name or provider directive that failed.",
+ "type": "string"
+ },
+ "discoveryEndpointId": {
+ "description": "Port OS provider endpoint (type ENDPOINT_PLUGIN) of the connection to send `discover-routes` to when `code` is `TARGET_UNSUPPORTED` because the route must be rediscovered.",
+ "type": "string"
+ },
+ "endpointId": {
+ "description": "Port OS endpoint ID involved in the failed dispatch.",
+ "type": "string"
+ },
+ "fieldErrors": {
+ "description": "The request fields that were rejected, when the error is about the request's content.",
+ "items": {
+ "description": "One rejected request field of an error.",
+ "properties": {
+ "field": {
+ "description": "Name or JSON path of the rejected field.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Why the field was rejected and what an accepted value looks like.",
+ "type": "string"
+ }
+ },
+ "required": [
+ "field",
+ "reason"
+ ],
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "maximum": {
+ "description": "Maximum accepted value when `code` is `VALUE_OUT_OF_RANGE`.",
+ "type": "number"
+ },
+ "minimum": {
+ "description": "Minimum accepted value when `code` is `VALUE_OUT_OF_RANGE`.",
+ "type": "number"
+ },
+ "parameter": {
+ "description": "Request parameter or capability value that caused the failure.",
+ "type": "string"
+ },
+ "pluginId": {
+ "description": "Port OS plugin ID that reported the failure.",
+ "type": "string"
+ },
+ "pluginRouteId": {
+ "description": "Plugin-owned route identifier involved in the failed dispatch.",
+ "type": "string"
+ },
+ "provider": {
+ "description": "Third-party provider or bridge name that reported the failure.",
+ "type": "string"
+ },
+ "providerCode": {
+ "description": "The third-party provider's own error code, for support. It is opaque and provider-specific; branch on `code` and `family` instead.",
+ "type": "string"
+ },
+ "retryAfterSeconds": {
+ "description": "Suggested retry delay for rate-limit or provider-unavailable failures.",
+ "minimum": 0,
+ "type": "integer"
+ }
+ },
+ "type": "object"
+ },
+ "errors": {
+ "description": "Every rejected item when a request that is validated item by item and applied atomically fails, such as a discovery `SynchronizationRequest` whose routes, group routes or relationships are rejected. Omitted for single-item failures.\n",
+ "items": {
+ "description": "One rejected discovery item of a `SynchronizationRequest`, keyed by the plugin-owned identity of the rejected item: `pluginRouteId` for a route or group route, or `relationshipExternalId` for a relationship. Exactly one of the two is set. It shares the `code`, `family`, `status` and `message` fields of `BatchItemError`; discovery items are keyed by plugin-owned identity because they carry no `requestId`. A request with any rejected item is rejected as a whole and lists every rejected item.\n",
+ "properties": {
+ "code": {
+ "description": "The specific error, one of a closed set of Port OS codes. Every REST error body, MCP tool error, batch item error and discovery item error uses this enum; each code belongs to an `ErrorFamily` that decides its HTTP status. Provider-specific codes are never codes: they travel in `details.providerCode`. New failure kinds are added here, never as free strings.",
+ "enum": [
+ "BAD_REQUEST",
+ "UNAUTHORIZED",
+ "FORBIDDEN",
+ "INSUFFICIENT_SCOPE",
+ "NOT_FOUND",
+ "CONFLICT",
+ "UNPROCESSABLE_ENTITY",
+ "UNSUPPORTED_OPERATION",
+ "TOO_MANY_REQUESTS",
+ "SERVICE_UNAVAILABLE",
+ "NOT_IMPLEMENTED",
+ "INTERNAL",
+ "CHECKSUM_MISMATCH",
+ "FILE_TOO_LARGE",
+ "STORAGE_UNAVAILABLE",
+ "INSUFFICIENT_PERMISSIONS",
+ "INVALID_FILE_TYPE",
+ "QUOTA_EXCEEDED",
+ "CONCURRENT_MODIFICATION",
+ "ENDPOINT_UNREACHABLE",
+ "BRIDGE_UNREACHABLE",
+ "CLOUD_CONTROL_DISABLED",
+ "ENDPOINT_BUSY",
+ "ENDPOINT_LOW_POWER",
+ "AUTHORIZATION_CREDENTIAL_INVALID",
+ "AUTHORIZATION_CREDENTIAL_EXPIRED",
+ "INVALID_DIRECTIVE",
+ "INVALID_VALUE",
+ "VALUE_OUT_OF_RANGE",
+ "NOT_SUPPORTED_IN_CURRENT_MODE",
+ "RATE_LIMIT_EXCEEDED",
+ "PROVIDER_SERVICE_UNAVAILABLE",
+ "PROVIDER_TIMEOUT",
+ "PROVIDER_INTERNAL_ERROR",
+ "INVALID_PROVIDER_RESPONSE",
+ "OUTCOME_UNKNOWN",
+ "PRECONDITION_FAILED",
+ "AUTH_LINK_NOT_READY",
+ "AUTH_LINK_NOT_DISCONNECTABLE",
+ "PRECONDITION_REQUIRED",
+ "IDEMPOTENCY_KEY_REQUIRED",
+ "IDEMPOTENCY_KEY_REUSED",
+ "IDEMPOTENCY_KEY_IN_FLIGHT",
+ "IDEMPOTENCY_KEY_INVALID",
+ "GROUP_MERGED",
+ "MULTI_ROOM_UNSUPPORTED",
+ "MAP_NOT_ACTIVE",
+ "TARGET_UNSUPPORTED",
+ "TARGET_AMBIGUOUS",
+ "TARGET_GROUP_NOT_FOUND",
+ "TARGET_GROUP_DISABLED",
+ "DUPLICATE_TARGET_GROUP",
+ "MESSAGE_UNSUPPORTED",
+ "MESSAGE_AMBIGUOUS",
+ "ENDPOINT_DISABLED",
+ "ENDPOINT_ROUTE_CHANGED",
+ "ENDPOINT_HAS_DEPENDENCIES",
+ "ENDPOINT_EVENT_SUBSCRIPTIONS_ACTIVE",
+ "ENDPOINT_COMMITTED_CLEANUP_PENDING",
+ "DEEP_QUERY_FAILED",
+ "PROVIDER_NO_STATE",
+ "EVENT_MANAGEMENT_DISABLED",
+ "SUBSCRIPTION_IDENTITY_IMMUTABLE",
+ "UNSUPPORTED_MEDIA_TYPE",
+ "EVENT_PAYLOAD_TOO_LARGE",
+ "REQUEST_BODY_TOO_LARGE",
+ "EVENT_IDENTITY_CONFLICT",
+ "EVENT_INGRESS_QUOTA_EXCEEDED",
+ "EVENT_RECEIPT_EXPIRED",
+ "EVENT_STORAGE_UNAVAILABLE",
+ "EVENT_DEAD_LETTER_NOT_FOUND",
+ "EVENT_REDRIVE_CONFLICT",
+ "EVENT_REDRIVE_EXPIRED",
+ "RECEIPT_CONTEXT_EXPIRED",
+ "EVENT_MAINTENANCE_INCOMPLETE",
+ "UNKNOWN_INTERFACE",
+ "INVALID_CONFIGURATION",
+ "INVALID_PLUGIN_MANIFEST",
+ "INVALID_ATTRIBUTE",
+ "INVALID_PROVIDER_MESSAGE",
+ "UNDECLARED_CAPABILITY",
+ "PLUGIN_ROUTE_ID_CONFLICT",
+ "UNRESOLVED_REFERENCE",
+ "INVALID_RELATIONSHIP",
+ "RELATIONSHIP_CYCLE",
+ "MULTIPLE_PARENTS",
+ "FLOW_VALIDATION_FAILED",
+ "PROVIDER_SYNC_UNSUPPORTED"
+ ],
+ "type": "string"
+ },
+ "family": {
+ "description": "The broad class of an error. The family decides the HTTP status of a REST error, so clients can handle every code of a family alike.",
+ "enum": [
+ "NOT_FOUND",
+ "BAD_REQUEST",
+ "UNAUTHORIZED",
+ "FORBIDDEN",
+ "CONFLICT",
+ "GONE",
+ "PRECONDITION_FAILED",
+ "PRECONDITION_REQUIRED",
+ "PAYLOAD_TOO_LARGE",
+ "UNSUPPORTED_MEDIA_TYPE",
+ "UNPROCESSABLE_ENTITY",
+ "LOCKED",
+ "TOO_MANY_REQUESTS",
+ "BAD_GATEWAY",
+ "SERVICE_UNAVAILABLE",
+ "GATEWAY_TIMEOUT",
+ "NOT_IMPLEMENTED",
+ "INTERNAL_SERVER_ERROR",
+ "REQUEST_INVALID",
+ "AUTHENTICATION",
+ "PERMISSION",
+ "ENDPOINT_NOT_FOUND",
+ "ENDPOINT_STATE_CONFLICT",
+ "ENDPOINT_UNAVAILABLE",
+ "RATE_LIMIT",
+ "PROVIDER_BAD_RESPONSE",
+ "PROVIDER_UNAVAILABLE",
+ "PROVIDER_TIMEOUT"
+ ],
+ "type": "string"
+ },
+ "interface": {
+ "description": "Canonical capability interface name the failure applies to, when the failure is interface-specific.",
+ "type": "string"
+ },
+ "message": {
+ "description": "Plain-language description of the failure and the suggested fix.",
+ "type": "string"
+ },
+ "pluginRouteId": {
+ "description": "Plugin-owned identifier of the rejected route or group route. Set unless the item is a relationship.",
+ "type": "string"
+ },
+ "relationshipExternalId": {
+ "description": "Plugin-owned `externalId` of the rejected relationship. Set only for relationship items.",
+ "type": "string"
+ },
+ "status": {
+ "description": "HTTP-equivalent status code of the item failure.",
+ "maximum": 599,
+ "minimum": 400,
+ "type": "integer"
+ },
+ "version": {
+ "description": "Declared capability interface version the failure applies to, when the failure is interface-specific.",
+ "type": "string"
+ }
+ },
+ "required": [
+ "code",
+ "family",
+ "status",
+ "message"
+ ],
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "family": {
+ "description": "The broad class of an error. The family decides the HTTP status of a REST error, so clients can handle every code of a family alike.",
+ "enum": [
+ "NOT_FOUND",
+ "BAD_REQUEST",
+ "UNAUTHORIZED",
+ "FORBIDDEN",
+ "CONFLICT",
+ "GONE",
+ "PRECONDITION_FAILED",
+ "PRECONDITION_REQUIRED",
+ "PAYLOAD_TOO_LARGE",
+ "UNSUPPORTED_MEDIA_TYPE",
+ "UNPROCESSABLE_ENTITY",
+ "LOCKED",
+ "TOO_MANY_REQUESTS",
+ "BAD_GATEWAY",
+ "SERVICE_UNAVAILABLE",
+ "GATEWAY_TIMEOUT",
+ "NOT_IMPLEMENTED",
+ "INTERNAL_SERVER_ERROR",
+ "REQUEST_INVALID",
+ "AUTHENTICATION",
+ "PERMISSION",
+ "ENDPOINT_NOT_FOUND",
+ "ENDPOINT_STATE_CONFLICT",
+ "ENDPOINT_UNAVAILABLE",
+ "RATE_LIMIT",
+ "PROVIDER_BAD_RESPONSE",
+ "PROVIDER_UNAVAILABLE",
+ "PROVIDER_TIMEOUT"
+ ],
+ "type": "string"
+ },
+ "message": {
+ "description": "Plain-language description of the failure and the suggested next action.",
+ "type": "string"
+ }
+ },
+ "required": [
+ "family",
+ "code",
+ "message"
+ ],
+ "type": "object"
+ },
+ "freshness": {
+ "description": "Whether the value is current enough to present as the device's present state.\n\n`FRESH`: the provider reported a sample within the last 30 seconds, or a\nforced refresh (`forceDeviceAttributeQuery=true` or `forceDeviceQuery`) read the\nprovider during this request and the provider reported no sample time.\n\n`STALE`: the value is older than 30 seconds, came from stored state, or is a\nprovider's own last known value. A forced refresh cannot make a provider's old\nsample newer: when the provider (for example a thermostat reached through a\nvoice-assistant account) answers with the sample it already holds, the value\nkeeps its original `sampledAt` and is `STALE`. Report the value together with\n`sampledAt`, never as the present reading.\n",
+ "enum": [
+ "FRESH",
+ "STALE"
+ ],
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "retrievability": {
+ "description": "Whether the serving route supports retrieving this attribute.",
+ "enum": [
+ "RETRIEVABLE",
+ "NOT_RETRIEVABLE"
+ ],
+ "type": "string"
+ },
+ "sampledAt": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "value": {
+ "additionalProperties": true,
+ "type": "object"
+ }
+ },
+ "required": [
+ "name",
+ "retrievability",
+ "autoUpdateFrequency"
+ ],
+ "type": "object"
+ }
+ ]
+ },
+ "type": "array"
+ },
+ "configuration": {
+ "type": "object"
+ },
+ "messages": {
+ "items": {
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "id",
+ "name"
+ ],
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "name": {
+ "type": "string"
+ },
+ "outboundMessages": {
+ "description": "Declared outbound message types, including results and events. Not every command returns a correlated result. These IDs cannot be sent as commands.",
+ "items": {
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "id",
+ "name"
+ ],
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "version": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "name",
+ "version",
+ "messages",
+ "attributes"
+ ],
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "name": {
+ "type": "string"
+ },
+ "providerId": {
+ "type": "string"
+ },
+ "providerName": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "id",
+ "providerId",
+ "providerName",
+ "interfaces"
+ ],
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "serialNumber": {
+ "properties": {
+ "type": {
+ "type": "string"
+ },
+ "value": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "type",
+ "value"
+ ],
+ "type": "object"
+ },
+ "type": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "id",
+ "etag",
+ "name",
+ "type",
+ "enablement",
+ "interfaces"
+ ],
+ "type": "object"
+ },
+ "type": "array"
+ }
+ },
+ "required": [
+ "results"
+ ],
+ "type": "object"
+ },
+ {
+ "additionalProperties": false,
+ "description": "The one Port OS error shape, returned by every REST error response and every MCP tool error. `code` names the specific failure and `family` its broad class; both are closed enums, so clients branch on them and show `message`, which says what failed and what to do next.",
+ "properties": {
+ "code": {
+ "description": "The specific error, one of a closed set of Port OS codes. Every REST error body, MCP tool error, batch item error and discovery item error uses this enum; each code belongs to an `ErrorFamily` that decides its HTTP status. Provider-specific codes are never codes: they travel in `details.providerCode`. New failure kinds are added here, never as free strings.",
+ "enum": [
+ "BAD_REQUEST",
+ "UNAUTHORIZED",
+ "FORBIDDEN",
+ "INSUFFICIENT_SCOPE",
+ "NOT_FOUND",
+ "CONFLICT",
+ "UNPROCESSABLE_ENTITY",
+ "UNSUPPORTED_OPERATION",
+ "TOO_MANY_REQUESTS",
+ "SERVICE_UNAVAILABLE",
+ "NOT_IMPLEMENTED",
+ "INTERNAL",
+ "CHECKSUM_MISMATCH",
+ "FILE_TOO_LARGE",
+ "STORAGE_UNAVAILABLE",
+ "INSUFFICIENT_PERMISSIONS",
+ "INVALID_FILE_TYPE",
+ "QUOTA_EXCEEDED",
+ "CONCURRENT_MODIFICATION",
+ "ENDPOINT_UNREACHABLE",
+ "BRIDGE_UNREACHABLE",
+ "CLOUD_CONTROL_DISABLED",
+ "ENDPOINT_BUSY",
+ "ENDPOINT_LOW_POWER",
+ "AUTHORIZATION_CREDENTIAL_INVALID",
+ "AUTHORIZATION_CREDENTIAL_EXPIRED",
+ "INVALID_DIRECTIVE",
+ "INVALID_VALUE",
+ "VALUE_OUT_OF_RANGE",
+ "NOT_SUPPORTED_IN_CURRENT_MODE",
+ "RATE_LIMIT_EXCEEDED",
+ "PROVIDER_SERVICE_UNAVAILABLE",
+ "PROVIDER_TIMEOUT",
+ "PROVIDER_INTERNAL_ERROR",
+ "INVALID_PROVIDER_RESPONSE",
+ "OUTCOME_UNKNOWN",
+ "PRECONDITION_FAILED",
+ "AUTH_LINK_NOT_READY",
+ "AUTH_LINK_NOT_DISCONNECTABLE",
+ "PRECONDITION_REQUIRED",
+ "IDEMPOTENCY_KEY_REQUIRED",
+ "IDEMPOTENCY_KEY_REUSED",
+ "IDEMPOTENCY_KEY_IN_FLIGHT",
+ "IDEMPOTENCY_KEY_INVALID",
+ "GROUP_MERGED",
+ "MULTI_ROOM_UNSUPPORTED",
+ "MAP_NOT_ACTIVE",
+ "TARGET_UNSUPPORTED",
+ "TARGET_AMBIGUOUS",
+ "TARGET_GROUP_NOT_FOUND",
+ "TARGET_GROUP_DISABLED",
+ "DUPLICATE_TARGET_GROUP",
+ "MESSAGE_UNSUPPORTED",
+ "MESSAGE_AMBIGUOUS",
+ "ENDPOINT_DISABLED",
+ "ENDPOINT_ROUTE_CHANGED",
+ "ENDPOINT_HAS_DEPENDENCIES",
+ "ENDPOINT_EVENT_SUBSCRIPTIONS_ACTIVE",
+ "ENDPOINT_COMMITTED_CLEANUP_PENDING",
+ "DEEP_QUERY_FAILED",
+ "PROVIDER_NO_STATE",
+ "EVENT_MANAGEMENT_DISABLED",
+ "SUBSCRIPTION_IDENTITY_IMMUTABLE",
+ "UNSUPPORTED_MEDIA_TYPE",
+ "EVENT_PAYLOAD_TOO_LARGE",
+ "REQUEST_BODY_TOO_LARGE",
+ "EVENT_IDENTITY_CONFLICT",
+ "EVENT_INGRESS_QUOTA_EXCEEDED",
+ "EVENT_RECEIPT_EXPIRED",
+ "EVENT_STORAGE_UNAVAILABLE",
+ "EVENT_DEAD_LETTER_NOT_FOUND",
+ "EVENT_REDRIVE_CONFLICT",
+ "EVENT_REDRIVE_EXPIRED",
+ "RECEIPT_CONTEXT_EXPIRED",
+ "EVENT_MAINTENANCE_INCOMPLETE",
+ "UNKNOWN_INTERFACE",
+ "INVALID_CONFIGURATION",
+ "INVALID_PLUGIN_MANIFEST",
+ "INVALID_ATTRIBUTE",
+ "INVALID_PROVIDER_MESSAGE",
+ "UNDECLARED_CAPABILITY",
+ "PLUGIN_ROUTE_ID_CONFLICT",
+ "UNRESOLVED_REFERENCE",
+ "INVALID_RELATIONSHIP",
+ "RELATIONSHIP_CYCLE",
+ "MULTIPLE_PARENTS",
+ "FLOW_VALIDATION_FAILED",
+ "PROVIDER_SYNC_UNSUPPORTED"
+ ],
+ "type": "string"
+ },
+ "details": {
+ "description": "Optional typed context for an error. Fields are additive and only populated when the error can safely expose that context to API clients.\n",
+ "properties": {
+ "actual": {
+ "description": "String representation of the submitted value when the plugin can safely report it.",
+ "type": "string"
+ },
+ "correlationId": {
+ "description": "Provider or plugin correlation ID useful for support.",
+ "type": "string"
+ },
+ "correlationToken": {
+ "description": "Token that correlates an outcome-unknown dispatch with its eventual result.",
+ "type": "string"
+ },
+ "currentMode": {
+ "description": "Current endpoint mode when `code` is `NOT_SUPPORTED_IN_CURRENT_MODE`.",
+ "type": "string"
+ },
+ "directive": {
+ "description": "Message namespace and name or provider directive that failed.",
+ "type": "string"
+ },
+ "discoveryEndpointId": {
+ "description": "Port OS provider endpoint (type ENDPOINT_PLUGIN) of the connection to send `discover-routes` to when `code` is `TARGET_UNSUPPORTED` because the route must be rediscovered.",
+ "type": "string"
+ },
+ "endpointId": {
+ "description": "Port OS endpoint ID involved in the failed dispatch.",
+ "type": "string"
+ },
+ "fieldErrors": {
+ "description": "The request fields that were rejected, when the error is about the request's content.",
+ "items": {
+ "description": "One rejected request field of an error.",
+ "properties": {
+ "field": {
+ "description": "Name or JSON path of the rejected field.",
+ "type": "string"
+ },
+ "reason": {
+ "description": "Why the field was rejected and what an accepted value looks like.",
+ "type": "string"
+ }
+ },
+ "required": [
+ "field",
+ "reason"
+ ],
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "maximum": {
+ "description": "Maximum accepted value when `code` is `VALUE_OUT_OF_RANGE`.",
+ "type": "number"
+ },
+ "minimum": {
+ "description": "Minimum accepted value when `code` is `VALUE_OUT_OF_RANGE`.",
+ "type": "number"
+ },
+ "parameter": {
+ "description": "Request parameter or capability value that caused the failure.",
+ "type": "string"
+ },
+ "pluginId": {
+ "description": "Port OS plugin ID that reported the failure.",
+ "type": "string"
+ },
+ "pluginRouteId": {
+ "description": "Plugin-owned route identifier involved in the failed dispatch.",
+ "type": "string"
+ },
+ "provider": {
+ "description": "Third-party provider or bridge name that reported the failure.",
+ "type": "string"
+ },
+ "providerCode": {
+ "description": "The third-party provider's own error code, for support. It is opaque and provider-specific; branch on `code` and `family` instead.",
+ "type": "string"
+ },
+ "retryAfterSeconds": {
+ "description": "Suggested retry delay for rate-limit or provider-unavailable failures.",
+ "minimum": 0,
+ "type": "integer"
+ }
+ },
+ "type": "object"
+ },
+ "errors": {
+ "description": "Every rejected item when a request that is validated item by item and applied atomically fails, such as a discovery `SynchronizationRequest` whose routes, group routes or relationships are rejected. Omitted for single-item failures.\n",
+ "items": {
+ "description": "One rejected discovery item of a `SynchronizationRequest`, keyed by the plugin-owned identity of the rejected item: `pluginRouteId` for a route or group route, or `relationshipExternalId` for a relationship. Exactly one of the two is set. It shares the `code`, `family`, `status` and `message` fields of `BatchItemError`; discovery items are keyed by plugin-owned identity because they carry no `requestId`. A request with any rejected item is rejected as a whole and lists every rejected item.\n",
+ "properties": {
+ "code": {
+ "description": "The specific error, one of a closed set of Port OS codes. Every REST error body, MCP tool error, batch item error and discovery item error uses this enum; each code belongs to an `ErrorFamily` that decides its HTTP status. Provider-specific codes are never codes: they travel in `details.providerCode`. New failure kinds are added here, never as free strings.",
+ "enum": [
+ "BAD_REQUEST",
+ "UNAUTHORIZED",
+ "FORBIDDEN",
+ "INSUFFICIENT_SCOPE",
+ "NOT_FOUND",
+ "CONFLICT",
+ "UNPROCESSABLE_ENTITY",
+ "UNSUPPORTED_OPERATION",
+ "TOO_MANY_REQUESTS",
+ "SERVICE_UNAVAILABLE",
+ "NOT_IMPLEMENTED",
+ "INTERNAL",
+ "CHECKSUM_MISMATCH",
+ "FILE_TOO_LARGE",
+ "STORAGE_UNAVAILABLE",
+ "INSUFFICIENT_PERMISSIONS",
+ "INVALID_FILE_TYPE",
+ "QUOTA_EXCEEDED",
+ "CONCURRENT_MODIFICATION",
+ "ENDPOINT_UNREACHABLE",
+ "BRIDGE_UNREACHABLE",
+ "CLOUD_CONTROL_DISABLED",
+ "ENDPOINT_BUSY",
+ "ENDPOINT_LOW_POWER",
+ "AUTHORIZATION_CREDENTIAL_INVALID",
+ "AUTHORIZATION_CREDENTIAL_EXPIRED",
+ "INVALID_DIRECTIVE",
+ "INVALID_VALUE",
+ "VALUE_OUT_OF_RANGE",
+ "NOT_SUPPORTED_IN_CURRENT_MODE",
+ "RATE_LIMIT_EXCEEDED",
+ "PROVIDER_SERVICE_UNAVAILABLE",
+ "PROVIDER_TIMEOUT",
+ "PROVIDER_INTERNAL_ERROR",
+ "INVALID_PROVIDER_RESPONSE",
+ "OUTCOME_UNKNOWN",
+ "PRECONDITION_FAILED",
+ "AUTH_LINK_NOT_READY",
+ "AUTH_LINK_NOT_DISCONNECTABLE",
+ "PRECONDITION_REQUIRED",
+ "IDEMPOTENCY_KEY_REQUIRED",
+ "IDEMPOTENCY_KEY_REUSED",
+ "IDEMPOTENCY_KEY_IN_FLIGHT",
+ "IDEMPOTENCY_KEY_INVALID",
+ "GROUP_MERGED",
+ "MULTI_ROOM_UNSUPPORTED",
+ "MAP_NOT_ACTIVE",
+ "TARGET_UNSUPPORTED",
+ "TARGET_AMBIGUOUS",
+ "TARGET_GROUP_NOT_FOUND",
+ "TARGET_GROUP_DISABLED",
+ "DUPLICATE_TARGET_GROUP",
+ "MESSAGE_UNSUPPORTED",
+ "MESSAGE_AMBIGUOUS",
+ "ENDPOINT_DISABLED",
+ "ENDPOINT_ROUTE_CHANGED",
+ "ENDPOINT_HAS_DEPENDENCIES",
+ "ENDPOINT_EVENT_SUBSCRIPTIONS_ACTIVE",
+ "ENDPOINT_COMMITTED_CLEANUP_PENDING",
+ "DEEP_QUERY_FAILED",
+ "PROVIDER_NO_STATE",
+ "EVENT_MANAGEMENT_DISABLED",
+ "SUBSCRIPTION_IDENTITY_IMMUTABLE",
+ "UNSUPPORTED_MEDIA_TYPE",
+ "EVENT_PAYLOAD_TOO_LARGE",
+ "REQUEST_BODY_TOO_LARGE",
+ "EVENT_IDENTITY_CONFLICT",
+ "EVENT_INGRESS_QUOTA_EXCEEDED",
+ "EVENT_RECEIPT_EXPIRED",
+ "EVENT_STORAGE_UNAVAILABLE",
+ "EVENT_DEAD_LETTER_NOT_FOUND",
+ "EVENT_REDRIVE_CONFLICT",
+ "EVENT_REDRIVE_EXPIRED",
+ "RECEIPT_CONTEXT_EXPIRED",
+ "EVENT_MAINTENANCE_INCOMPLETE",
+ "UNKNOWN_INTERFACE",
+ "INVALID_CONFIGURATION",
+ "INVALID_PLUGIN_MANIFEST",
+ "INVALID_ATTRIBUTE",
+ "INVALID_PROVIDER_MESSAGE",
+ "UNDECLARED_CAPABILITY",
+ "PLUGIN_ROUTE_ID_CONFLICT",
+ "UNRESOLVED_REFERENCE",
+ "INVALID_RELATIONSHIP",
+ "RELATIONSHIP_CYCLE",
+ "MULTIPLE_PARENTS",
+ "FLOW_VALIDATION_FAILED",
+ "PROVIDER_SYNC_UNSUPPORTED"
+ ],
+ "type": "string"
+ },
+ "family": {
+ "description": "The broad class of an error. The family decides the HTTP status of a REST error, so clients can handle every code of a family alike.",
+ "enum": [
+ "NOT_FOUND",
+ "BAD_REQUEST",
+ "UNAUTHORIZED",
+ "FORBIDDEN",
+ "CONFLICT",
+ "GONE",
+ "PRECONDITION_FAILED",
+ "PRECONDITION_REQUIRED",
+ "PAYLOAD_TOO_LARGE",
+ "UNSUPPORTED_MEDIA_TYPE",
+ "UNPROCESSABLE_ENTITY",
+ "LOCKED",
+ "TOO_MANY_REQUESTS",
+ "BAD_GATEWAY",
+ "SERVICE_UNAVAILABLE",
+ "GATEWAY_TIMEOUT",
+ "NOT_IMPLEMENTED",
+ "INTERNAL_SERVER_ERROR",
+ "REQUEST_INVALID",
+ "AUTHENTICATION",
+ "PERMISSION",
+ "ENDPOINT_NOT_FOUND",
+ "ENDPOINT_STATE_CONFLICT",
+ "ENDPOINT_UNAVAILABLE",
+ "RATE_LIMIT",
+ "PROVIDER_BAD_RESPONSE",
+ "PROVIDER_UNAVAILABLE",
+ "PROVIDER_TIMEOUT"
+ ],
+ "type": "string"
+ },
+ "interface": {
+ "description": "Canonical capability interface name the failure applies to, when the failure is interface-specific.",
+ "type": "string"
+ },
+ "message": {
+ "description": "Plain-language description of the failure and the suggested fix.",
+ "type": "string"
+ },
+ "pluginRouteId": {
+ "description": "Plugin-owned identifier of the rejected route or group route. Set unless the item is a relationship.",
+ "type": "string"
+ },
+ "relationshipExternalId": {
+ "description": "Plugin-owned `externalId` of the rejected relationship. Set only for relationship items.",
+ "type": "string"
+ },
+ "status": {
+ "description": "HTTP-equivalent status code of the item failure.",
+ "maximum": 599,
+ "minimum": 400,
+ "type": "integer"
+ },
+ "version": {
+ "description": "Declared capability interface version the failure applies to, when the failure is interface-specific.",
+ "type": "string"
+ }
+ },
+ "required": [
+ "code",
+ "family",
+ "status",
+ "message"
+ ],
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "family": {
+ "description": "The broad class of an error. The family decides the HTTP status of a REST error, so clients can handle every code of a family alike.",
+ "enum": [
+ "NOT_FOUND",
+ "BAD_REQUEST",
+ "UNAUTHORIZED",
+ "FORBIDDEN",
+ "CONFLICT",
+ "GONE",
+ "PRECONDITION_FAILED",
+ "PRECONDITION_REQUIRED",
+ "PAYLOAD_TOO_LARGE",
+ "UNSUPPORTED_MEDIA_TYPE",
+ "UNPROCESSABLE_ENTITY",
+ "LOCKED",
+ "TOO_MANY_REQUESTS",
+ "BAD_GATEWAY",
+ "SERVICE_UNAVAILABLE",
+ "GATEWAY_TIMEOUT",
+ "NOT_IMPLEMENTED",
+ "INTERNAL_SERVER_ERROR",
+ "REQUEST_INVALID",
+ "AUTHENTICATION",
+ "PERMISSION",
+ "ENDPOINT_NOT_FOUND",
+ "ENDPOINT_STATE_CONFLICT",
+ "ENDPOINT_UNAVAILABLE",
+ "RATE_LIMIT",
+ "PROVIDER_BAD_RESPONSE",
+ "PROVIDER_UNAVAILABLE",
+ "PROVIDER_TIMEOUT"
+ ],
+ "type": "string"
+ },
+ "message": {
+ "description": "Plain-language description of the failure and the suggested next action.",
+ "type": "string"
+ }
+ },
+ "required": [
+ "family",
+ "code",
+ "message"
+ ],
+ "type": "object"
+ }
+]