Skip to content

Manifest

A consumer manifest declares the Home Assistant capabilities the consumer wants.

type VarcoManifest = {
name: string;
icon?: string;
version: string;
read_entities?: string[];
subscriptions?: string[];
history?: string[];
camera_snapshots?: string[];
actions?: string[];
};

The canonical schema is snake_case. For compatibility with existing consumers, the Authority also accepts the camelCase aliases readEntities and cameraSnapshots on the wire, then normalizes the stored manifest to snake_case (custom_components/varco/manifest.py, validate_manifest). A manifest that sets both spellings of the same field (for example read_entities and readEntities) is rejected with the invalid_manifest error code; neither value is silently dropped. The Authority also requires a non-empty string name and rejects scope fields that are not arrays of non-empty strings.

{
"name": "Kitchen display",
"version": "0.1.0",
"read_entities": ["sensor.kitchen_temperature", "sensor.kitchen_humidity"],
"subscriptions": [],
"history": [],
"camera_snapshots": [],
"actions": []
}

Entities in read_entities are already subscribable: the Authority allows subscribe_states for the union of subscriptions and read_entities, so duplicating read entities into subscriptions is unnecessary.

sensor.temperature
sensor.*
*
light.turn_on@light.kitchen
light.*
light.*@light.kitchen
*@light.kitchen

Request the smallest manifest that supports the app. The Authority still enforces the stored grant on every request, even if the consumer code changes later.

@varco/client exports headless manifest builders for common entity/action presets. They expand ergonomic entity declarations into the Varco manifest fields and deduplicate repeated scopes.

import {
climateControl,
createManifest,
lightControl,
readEntity,
} from "@varco/client";
const manifest = createManifest({
name: "Room dashboard",
version: "0.1.0",
entities: [
readEntity("sensor.room_temperature", { subscribe: true }),
lightControl("light.kitchen", { brightness: true }),
climateControl("climate.living_room", {
temperature: true,
hvacMode: true,
presetMode: true,
}),
],
});

This produces read scopes for each entity, a subscription scope for sensor.room_temperature, default subscription scopes for control builders, plus action scopes such as:

light.turn_on@light.kitchen
light.turn_off@light.kitchen
climate.set_temperature@climate.living_room
climate.set_hvac_mode@climate.living_room
climate.set_preset_mode@climate.living_room

readEntity() and cameraEntity() do not request subscriptions by default. Pass { subscribe: true } when the app needs live updates. Control builders such as lightControl() and climateControl() subscribe by default, and accept { subscribe: false } to opt out.

Available first-batch builders:

  • readEntity(entityId)
  • cameraEntity(entityId)
  • lightControl(entityId, options)
  • switchControl(entityId, options)
  • climateControl(entityId, options)
  • coverControl(entityId, options)
  • fanControl(entityId, options)
  • lockControl(entityId, options)
  • mediaPlayerControl(entityId, options)
  • buttonControl(entityId, options)
  • sceneControl(entityId, options)
  • numberControl(entityId, options)
  • selectControl(entityId, options)