{"record":{"id":"f970ad687c348deb","repo":"home-assistant/core","slug":"unauthorized","errorCode":null,"errorMessage":"Unauthorized","messagePattern":"Unauthorized","errorType":"http","errorClass":"Unauthorized","httpStatus":401,"severity":"error","filePath":"homeassistant/components/api/__init__.py","lineNumber":249,"sourceCode":"        )\n        if len(body) > MIN_COMPRESSED_RESPONSE_SIZE:\n            response.enable_compression()\n        return response\n\n\nclass APIEntityStateView(HomeAssistantView):\n    \"\"\"View to handle EntityState requests.\"\"\"\n\n    url = \"/api/states/{entity_id}\"\n    name = \"api:entity-state\"\n\n    @ha.callback\n    def get(self, request: web.Request, entity_id: str) -> web.Response:\n        \"\"\"Retrieve state of entity.\"\"\"\n        user: User = request[KEY_HASS_USER]\n        hass = request.app[KEY_HASS]\n        if not user.permissions.check_entity(entity_id, POLICY_READ):\n            raise Unauthorized(entity_id=entity_id)\n\n        if state := hass.states.get(entity_id):\n            return web.Response(\n                body=state.as_dict_json,\n                content_type=CONTENT_TYPE_JSON,\n            )\n        return self.json_message(\"Entity not found.\", HTTPStatus.NOT_FOUND)\n\n    async def post(self, request: web.Request, entity_id: str) -> web.Response:\n        \"\"\"Update state of entity.\"\"\"\n        user: User = request[KEY_HASS_USER]\n        if not user.is_admin:\n            raise Unauthorized(entity_id=entity_id)\n        hass = request.app[KEY_HASS]\n\n        body = await request.text()\n\n        try:","sourceCodeStart":231,"sourceCodeEnd":267,"githubUrl":"https://github.com/home-assistant/core/blob/58a3fdb3ea0538617f0a07efcfba6294de64fd59/homeassistant/components/api/__init__.py#L231-L267","documentation":"Unauthorized (HTTP 401) raised by GET /api/states/{entity_id} when the authenticated user lacks read permission for that specific entity. The API supports non-admin users with per-entity permission policies; the check user.permissions.check_entity(entity_id, POLICY_READ) fails, so the request never reaches the state lookup.","triggerScenarios":"Calling GET /api/states/light.kitchen with a token whose user is not admin and whose entity permissions do not include read (or an explicit deny) for light.kitchen; typical with long-lived access tokens created for restricted users, or with a user whose permissions were edited after the token was issued.","commonSituations":"Restricted HA user used by external tooling (Grafana, scripts, custom apps) with entity permission lists that omit newly created entities; permission policy set to entity-list instead of all; token created before permissions were narrowed.","solutions":["Use a token belonging to an admin user, or a user with read policy for the entity","Update the user's entity permissions in HA (Settings > People) to include the entity or use 'Allow all' read policy","Prefer the WebSocket API with proper permission scoping for third-party integrations"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"# Before first use, verify the token's user and permissions via the WebSocket API\n# await ws.send_json({\"id\": 1, \"type\": \"auth/current_user\"}) and inspect permissions","typeGuard":null,"tryCatchPattern":"try:\n    resp = session.get(url, headers={\"Authorization\": f\"Bearer {token}\"}, timeout=5)\n    if resp.status_code == 401:\n        # token lacks read permission for the entity: fix user policy or use admin token\n        ...","preventionTips":["Use admin or correctly-scoped tokens for API clients","Re-check entity permission lists after adding new entities","Prefer the WebSocket API for third-party tooling"],"tags":["home-assistant","api","auth","permissions","rest"],"backgroundTag":null,"analyzedSha":"58a3fdb3ea0538617f0a07efcfba6294de64fd59","analyzedAt":"2026-08-14T20:54:38.818Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}