← API Version Chart

Server API 3.9 Release Notes

This version of the API shipped with Indigo 20261.0 - check the API Version Chart to see what version of the API is available in which Indigo versions.

  • Tags. Objects can now be labeled with tags, across all six types that have folders — devices, variables, triggers, schedules, action groups and control pages. A tag is server-wide: it lives in one library shared by every object type, and tags cut across the folder hierarchy rather than replacing it.
  • indigo.server.tags returns the entire tag library as a {name: record} map, so both "kitchen" in indigo.server.tags and indigo.server.tags["kitchen"] work. It includes tags no object currently carries, since a tag has to be in the library before it can be assigned.
  • A tag record carries three colors — {"color": "AABBCC", "text_color": "AABBCC", "border_color": "AABBCC"}. color is the one the user chose and the only one that is stored or settable; text_color and border_color are derived from it by the server and are read-only. Draw a tag's text and border with them rather than computing your own contrast — every Indigo interface derives them with one shared implementation, so using them is what makes a plugin's or a third-party client's tags match Indigo's. Attempting to set either through create_tag or update_tag is refused with an error saying the key is derived.
  • indigo.server.create_tag(tag, color), indigo.server.update_tag(tag, new_tag=None, new_color=None) and indigo.server.delete_tag(tag) maintain the library. update_tag requires at least one of new_tag / new_color; a rename carries the tag on every object that has it, and a recolor rewrites no object at all.
  • add_tag(obj, tag) and remove_tag(obj, tag) on indigo.device, indigo.variable, indigo.trigger, indigo.schedule, indigo.actionGroup and indigo.controlPage assign and unassign. Both are idempotent. add_tag raises if the tag isn't already in the library — the deliberate split is that create_tag mints a library entry while add_tag puts an existing one on an object, so a typo can't quietly create a near-duplicate.
  • Every taggable element gained a read-only tags property, a plain list of the names it carries. Note this is a different shape from indigo.server.tags, which maps every name in the library to its record.
  • Tag names are lowercase letters separated by single dashes (a-tag, some-other-tag), enforced everywhere a tag can be created. Colors are "AABBCC" — six hex digits, no separators, no leading # — in the IOM, the HTTP body and the WebSocket frame alike, so nothing in the stack converts between representations.
  • Plugins can subscribe to tag library changes. indigo.server.subscribeToTagChanges(), called once in startup(), delivers tag_created(tag), tag_updated(origTag, newTag) and tag_deleted(tag). Each tag arrives as a one-entry {name: record} map — the same shape indigo.server.tags returns for the whole library, so a callback argument can be handed straight to code written against the library. A recolor reaches a plugin only this way, since it rewrites no object.
  • Plugins can subscribe to folder changes, per object type: indigo.devices.folders.subscribeToChanges() and the same for variables, action groups, schedules, triggers and control pages. Delivers folder_created(folder), folder_updated(origFolder, newFolder) and folder_deleted(folder). This API was previously callable but never delivered anything — the server broadcast and the plugin host handler were both already in place, but nothing named the Python functions to dispatch to, so every folder change died in the plugin host as an unknown element type.
  • indigo.Folder gained a read-only parentType — one of "device", "variable", "actionGroup", "schedule", "trigger" or "controlPage", the same names the command namespaces use. There are six folder lists but one set of folder callbacks, so this is how a plugin subscribed to more than one list tells them apart.
  • Both subscriptions are opt-in and plugins-only; calling either from a script or the interactive shell raises ValueError. Neither filters by ownership the way deviceCreated() and friends do, because folders and tags have no owning plugin. Worked example: Example Folder and Tag Subscriptions in the SDK.
  • HTTP and WebSocket APIs: every object gained tags, a list of names, on both transports. HTTP additionally carries tagDetails beside it, resolving those names to their records on reads. GET /v2/api/indigo.tags returns the whole library. The object list endpoints accept ?tag= and ?folder= filters — repeating tag is AND, and ?folder=0 means "in no folder". Library commands are HTTP-only; per-object add_tag / remove_tag work on both transports.
  • A new v3 WebSocket API at /v3/api/ws/full-feed carries every object type you subscribe to over one connection instead of seven, along with each type's folder list and the tag library. It also delivers two kinds of change the v2 feeds structurally cannot: tag recolors and folder renames, neither of which rewrites an object. The seven v2 feeds are unchanged and fully supported.
  • GET /api/capabilities reports which API versions this server serves and where each lives. It is unauthenticated, and from 2026.1 on a 404 means the server predates this release.
  • An MCP server at /v3/api/mcp lets an AI chat client or coding agent control Indigo in plain language. It is deliberately control-only: it cannot create, edit or delete devices, triggers, schedules, action groups or control pages.
  • Indigo now requires macOS 10.15 Catalina or later, up from 10.13. For plugin developers this means your users' floor is now Catalina, and binary wheels vendored into Contents/Packages/ need only reach 10.15.