# External integrations: update to Gladys 5.3, JS SDK 0.16 and the store

**URL:** <https://community.gladysassistant.com/t/integrations-externes-mettre-a-jour-vers-gladys-5-3-le-sdk-js-0-16-et-le-store/11410>\
**Category:** Développement\
**Created:** [October 25, 2026, 2:24pm UTC](https://community.gladysassistant.com/t/integrations-externes-mettre-a-jour-vers-gladys-5-3-le-sdk-js-0-16-et-le-store/11410 "2026-10-25T14:24:09Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![pierre-gilles](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/pierre-gilles/32/5886_2.png) [@pierre-gilles](https://community.gladysassistant.com/u/pierre-gilles)\
**Post date:** [October 25, 2026, 2:24pm UTC](https://community.gladysassistant.com/t/integrations-externes-mettre-a-jour-vers-gladys-5-3-le-sdk-js-0-16-et-le-store/11410/1 "2026-10-25T14:24:09Z")

</div>

Hello everyone!

A lot has changed in recent weeks regarding external integrations: new version of the JavaScript SDK ( **`@gladysassistant/integration-sdk` v0.16.0** ), new fields in the manifest, new validation rules in the store… This post gathers **everything you need to do to update your integration** , and what you can do additionally if you wish.

Good news: **there is no mandatory breaking change**. An integration published today remains indexed. But a few points deserve a check, and the new features are worth a look 🙂

* * *

## ✅ The Quick Checklist

- Upgrade the SDK to `^0.16.0` (Node.js ≥ 20)
- Check your `poll_frequency`: **in milliseconds** , and only among the allowed values
- Use `publishChangedStates` if you publish many states (limit of 300 states/minute)
- Add `categories` (and optionally `keywords` / `countries`) to the manifest
- Check that `gladys_version` covers all the fields you declare
- Have `docs/en.md` **and** `docs/fr.md` (300 characters minimum each)
- Check the cover: JPEG or PNG, **800×534 px exactly** , 150 Ko maximum
- Run the local validator: `npx github:GladysAssistant/integration-store`
- Publish: increment `version` + `docker_image`, pushing the image **before** the manifest

The details of each point are below.

* * *

## 1. Updating the SDK

```bash
npm install @gladysassistant/integration-sdk@^0.16.0

```

The SDK requires **Node.js ≥ 20**. Make sure to check the base image of your `Dockerfile`.

What has changed since v0.11:

| Version | Main New Features |
| --- | --- |
| **0.12** | Sync with Gladys 4.86: electric/gas network sensors, PTZ cameras, `wakeOnLan()`, `account_link` config field |
| **0.13** | Six new weather phenomena in the pivot format, sirens, battery recharge, scan result format |
| **0.14** | Scene triggers and actions, dashboard widgets, `getHouses()`, network carbon and smoke sensors |
| **0.15** | `DEVICE_POLL_FREQUENCIES`, **Fake Gladys for your tests** , `parseMdnsTxt()`, `publishChangedStates()`, `calendar` type, energy contracts, forms in widget buttons, house selector, `publishEnergyConsumption()` |
| **0.16** | Music players, `ai` and `tts` types, `should_poll` becomes optional |

The full changelog is on [GitHub](https://github.com/GladysAssistant/integration-sdk-js/blob/main/CHANGELOG.md).

* * *

## 2. Points to Check in Your Code

### ⏱ `poll_frequency`: in milliseconds, and only certain values

This is the most common pitfall. `poll_frequency` is expressed in **milliseconds** , and only these values are accepted: 1 s, 2 s, 10 s, 15 s, 30 s or 1 min. Any other value (`300` thought in seconds, `300000` for 5 minutes…) makes `publishDiscoveredDevices` fail with a **400 error**.

Use the constants exported by the SDK:

```js
import { DEVICE_POLL_FREQUENCIES } from '@gladysassistant/integration-sdk';

await gladys.publishDiscoveredDevices([
  {
    name: 'Weather Station',
    external_id: ids.device,
    should_poll: true,
    poll_frequency: DEVICE_POLL_FREQUENCIES.EVERY_MINUTES, // 60000 ms
    features: [/* … */],
  },
]);

```

A few clarifications:

- **One minute is the slowest pace.** To go slower (cloud API with quota, user setting in minutes), keep `EVERY_MINUTES` and ignore unnecessary polls in `onPoll`, or use your own timer.
- **Since Gladys 5.3, `poll_frequency` is enough** : the core activates `should_poll` on its own. If your `gladys_version` accepts older versions, **keep `should_poll: true`**. If you set `should_poll`, it must be a boolean.
- These two fields are read **when the device is created** : modifying them later does not update an already created device.

### 📉 300 states per minute limit: `publishChangedStates`

The host API limits `POST /state` to **300 states per minute and per integration**. If you query many devices, only publish what has changed:

```js
// replaces publishStates: only modified values go to Gladys
await gladys.publishChangedStates(states);

// and we still return an unchanged value every 30 minutes
await gladys.publishChangedStates(states, { heartbeat: 30 * 60 * 1000 });

```

The SDK splits batches of more than 100 states, returns what Gladys refused, and forgets the values of a device when the user creates, modifies, or deletes it.

### 🏷 Use constants, not hardcoded strings

`DEVICE_FEATURE_CATEGORIES`, `DEVICE_FEATURE_TYPES` and `DEVICE_FEATURE_UNITS` are a copy of `server/utils/constants.js` in Gladys, and they are kept up to date with each version. If you manually copied strings, now is the time to switch to constants: you avoid typos and have autocompletion.

### 🌦 Weather integrations: `night` is deprecated

The `night` condition is still accepted but it is **deprecated**. A rainy night is written `weather: 'rain', is_day: false`. Also think about the new conditions of the pivot format and the `type` field of alerts (`WEATHER_ALERT_TYPES`).

### 🎬 Scene triggers and actions: keys are final

If you declare `scene_triggers` / `scene_actions`, a published **key must never be renamed**. And adding a `required` field without `default` to an existing action breaks the scenes that use it.

* * *

## 3. Updating the Manifest

### The golden rule: `gladys_version` must cover what you declare

Old versions of Gladys **reject fields they don’t know**. The store therefore checks that the minimum of your `gladys_version` covers each declared field, otherwise **the integration is rejected**. This way, the user simply sees «&nbsp;requires Gladys ≥ X&nbsp;» in the catalog, instead of an installation that fails without explanation.

| You declare… | Minimum `gladys_version` |
| --- | --- |
| `categories` | `>=4.86.0` |
| `type: "provider"`, `widgets`, `scene_triggers`, `scene_actions` | `>=5.1.0` |
| `type: "calendar"`, `account_schema`, `energy_contracts`, a field with `source: "houses"` | `>=5.2.0` |
| `type: "ai"`, `type: "tts"`, `music`, `keywords`, `countries` | `>=5.3.0` |

⚠ Conversely, **do not increase `gladys_version` without reason** : your integration would be hidden from users who have not yet updated Gladys.

### 🗂 `categories`: your place in the catalog

Between 1 and 3 categories among: `climate`, `lighting`, `energy`, `security`, `multimedia`, `appliances`, `environment`, `protocols`, `network`, `notifications`, `assistants`, `services`, `transport`, `vehicles`, `servers`, `leisure`.

The last four (`transport`, `vehicles`, `servers`, `leisure`) have just been added. Without `categories`, your integration remains visible in «&nbsp;All&nbsp;» and in the search, but does not appear in any section. For already published integrations, the store applies in the meantime a fallback mapping ([`data/category-fallback.json`](https://github.com/GladysAssistant/integration-store/blob/main/data/category-fallback.json)). Declaring your own categories is the best way to be well placed. An unknown category is simply ignored, with a warning.

### 🔎 `keywords` and `countries` (Gladys ≥ 5.3)

```json
{
  "gladys_version": ">=5.3.0",
  "categories": ["energy"],
  "keywords": ["linky", "enedis", "téléinfo"],
  "countries": ["FR"]
}

```

- **`keywords`** : 1 to 10 terms of 2 to 30 characters, never displayed, used **only by search** (brands, models, synonyms, cities or networks served…).
- **`countries`** : 1 to 20 ISO country codes in uppercase. **Do not include this if your integration works everywhere** (this is the default behavior). If you declare it, instances located in another country will no longer see the integration in the catalog sections (it remains findable via search). Think about this for a regional integration: national weather service, transport network, energy provider, ISP…

Do not forget: declaring `keywords` or `countries` **requires `gladys_version` ≥ 5.3.0**.

* * *

## 4. Documentation and cover

- **Mandatory documentation** : `docs/en.md` **and** `docs/fr.md` at the root of the repository, **300 characters minimum** each, following the sections of the template (Presentation / Prerequisites / Configuration / Troubleshooting). If one is missing, the integration is **rejected**. The files are hosted by the store and displayed in the installation and configuration screens of Gladys.
- **New** : `docs/de.md` and `docs/es.md` are **optional**. If they are present (300 characters minimum), they are displayed to German and Spanish users.
- **Cover** : JPEG or PNG, **exactly 800×534 px** , **150 Ko maximum** , direct `https` URL (without redirection). The simplest: a `raw.githubusercontent.com` URL to a file in your repository. An invalid cover does not block indexing, but you will have a default image in the catalog.

* * *

## 5. Validate locally before publishing

No need to wait for hourly indexing to discover a rejection! At the root of your repository:

```bash
npx github:GladysAssistant/integration-store

```

The validator performs **exactly the same checks as the store robot** (schema, `gladys_version` rules, categories, documentation, existence of Docker images, cover) and displays **all problems at once**. Exit code `0` = the integration would be indexed, `1` = it would be rejected.

### In the CI of your pull requests

In a PR that increments the version, the Docker image is generally not yet published: add `--skip-image-check` to skip only this check.

```yaml
- uses: actions/setup-node@v4
  with:
    node-version: 24
- run: npx github:GladysAssistant/integration-store --skip-image-check

```

Run it **without** the option once the images are published, for example in the last step of your release workflow.

* * *

## 6. Publish the new version

1. Increment **`version`** (strict semver) **and**  **`docker_image`** (with an explicit tag) in the manifest.
2. **Publish the Docker image before** the manifest that references it arrives on the default branch: the store checks that the image exists and is downloadable without authentication. If the image is missing, the integration is removed from the catalog until the next indexing.
3. Push. At the next indexing (every hour), Gladys will display “update available” to your users.

Your integration does not appear? Look at the public **`rejected.json`** file of the store: each rejection is listed there with its reason (`error` = not indexed, `warning` = indexed with a degradation, for example the default cover).

* * *

## 7. Test your integration with the fake Gladys

The SDK now provides an **in-memory Gladys** for your unit tests: it’s a real `GladysIntegration`, connected to a fake Gladys instead of the network.

```js
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { createFakeGladys } from '@gladysassistant/integration-sdk/testing';
import { registerHandlers } from '../src/app.js';

test('publishes the temperature on poll', async () => {
  const gladys = createFakeGladys({ config: { api_key: 'key' } });
  registerHandlers(gladys);
  await gladys.connect();

  const [device] = gladys.fake.discoveredDevices;
  assert.deepEqual(await gladys.fake.poll(device), { success: true });
  assert.equal(gladys.fake.lastState(`${device.external_id}:temperature`), 21.5);
});

```

It applies the same checks as the host API (prefix of `external_id`, known categories/types/units, `poll_frequency`…) and responds with the **same 400 errors**. You therefore see the errors in your tests rather than with your users.

* * *

## 8. To go further (optional)

If you want to enrich your integration, here is everything that is now possible:

| Feature | Manifest | SDK | Gladys |
| --- | --- | --- | --- |
| Dashboard widgets | `widgets` | `onWidgetGet`, `onWidgetAction`, `requestWidgetRefresh` | ≥ 5.1 |
| Scene triggers / actions | `scene_triggers`, `scene_actions` | `publishSceneEvent`, `onSceneAction` | ≥ 5.1 |
| “Capabilities only” integration | `type: "provider"` | — | ≥ 5.1 |
| Calendar provider | `type: "calendar"`, `account_schema` | `publishCalendars`, `publishCalendarEvents`… | ≥ 5.2 |
| Energy contracts and calendars | `energy_contracts` | `publishEnergyCalendar`, `onEnergyPrice`… | ≥ 5.2 |
| Dated consumption (readings received later) | — | `publishEnergyConsumption` | ≥ 5.2 |
| House selection in a form | `source: "houses"` | — | ≥ 5.2 |
| AI provider (compatible with OpenAI) | `type: "ai"` | `onAiChat` | ≥ 5.3 |
| Text-to-speech | `type: "tts"` | `onTtsSynthesize` | ≥ 5.3 |
| Music players (navigation, search, queue) | `music` | `publishNowPlaying`, `onMusicBrowse`, `onMusicPlay`… | ≥ 5.3 |
| Wake-on-LAN | `network_wake: true` | `wakeOnLan` | ≥ 4.86 |
| Connection to an account without redirection (QR code…) | `account_link` field | `onOAuthAuthorizeUrl` | ≥ 4.86 |

Everything is documented in the [SDK README](https://github.com/GladysAssistant/integration-sdk-js#readme), and all the manifest rules are in the [store README](https://github.com/GladysAssistant/integration-store#the-manifest).

* * *

If you are stuck on a migration or if a validation rule seems strange to you, reply in this topic or open an issue on [integration-sdk-js](https://github.com/GladysAssistant/integration-sdk-js/issues) / [integration-store](https://github.com/GladysAssistant/integration-store/issues).

Thanks to everyone who develops integrations, the catalog is growing very quickly! 🙏

---

<div class="post-metadata">

**Author:** ![mutmut](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/mutmut/32/14064_2.png) [@mutmut](https://community.gladysassistant.com/u/mutmut)\
**Post date:** [November 11, 2026, 5:52pm UTC](https://community.gladysassistant.com/t/integrations-externes-mettre-a-jour-vers-gladys-5-3-le-sdk-js-0-16-et-le-store/11410/2 "2026-11-11T17:52:52Z")

</div>

> [@pierre-gilles](#):
>
> ### 🔎 `keywords` and `countries` (Gladys ≥ 5.3)
> 
> ```json
> {
> "gladys_version": ">=5.3.0",
> "categories": ["energy"],
> "keywords": ["linky", "enedis", "téléinfo"],
> "countries": ["FR"]
> }
> 
> ```
> 
> - **`keywords`** : 1 to 10 terms of 2 to 30 characters, never displayed, used **only by search** (brands, models, synonyms, cities or networks served…).
> - **`countries`** : 1 to 20 ISO country codes in uppercase. **Do not put it if your integration works everywhere** (this is the default behavior). If you declare it, instances located in another country will no longer see the integration in the catalog sections (it remains findable via search). Think about it for a regional integration: national weather service, transport network, energy supplier, ISP…
> 
> Don’t forget: declaring `keywords` or `countries` **requires `gladys_version` ≥ 5.3.0**.

I see in Gladys’ external integrations that some countries are not mentioned and we see a lot of integrations “external” to France (if I take my case as a French speaker).  
In the manifest, we should find the “countries”, no problem. For those who have put it, it works.  
There is also in the GladysAssistant/integration-store repo a file that manages the country language: `data/country-fallback.json`

If I have to make PRs for some integrations that don’t have the country, what would be the best rule: make a global PR on `country-fallback.json` or a PR per integration?

For now, I’ve made a PR for an integration, but I want to be sure about the next steps.

---

<div class="post-metadata">

**Author:** ![pierre-gilles](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/pierre-gilles/32/5886_2.png) [@pierre-gilles](https://community.gladysassistant.com/u/pierre-gilles)\
**Post date:** [November 13, 2026, 8:08am UTC](https://community.gladysassistant.com/t/integrations-externes-mettre-a-jour-vers-gladys-5-3-le-sdk-js-0-16-et-le-store/11410/3 "2026-11-13T08:08:55Z")

</div>

Hello @mutmut, thanks for taking care of this 🙏

The best approach is for **each integration to declare its own `countries` in its manifest** : the author knows best where their integration works. The data/country-fallback.json file is just a temporary solution, filled once in the October catalog to avoid waiting for everyone, and it is meant to disappear. So yes, a PR per integration, as you started doing 👍

A few rules to ensure these PRs go smoothly:

1. **`countries` enforces `gladys_version >= 5.3.0` in the same PR.** Without this, the store rejects the integration, and it disappears from the catalog at the next indexing. Run the validator before proposing the PR: `npx github:GladysAssistant/integration-store`
2. **Include all countries where the integration is useful** , not just France, as a forgotten country hides the integration from its users. For example, Pathé is also in Belgium, Switzerland, and the Netherlands.
3. **Only add `countries` to truly regional integrations** : national weather, transportation, energy or water providers, ISPs, open data… A hardware brand sold worldwide should not have this.
4. **Start with integrations missing from the fallback** , i.e., those published since late October. These are the ones currently displayed everywhere. Those already in the file are already correctly filtered, so the PR is still welcome but not urgent.
5. In the description, include a link to this topic and explain the consequence for the author (Gladys 5.3 minimum), so they can decide knowingly.

---

<div class="post-metadata">

**Author:** ![mutmut](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/mutmut/32/14064_2.png) [@mutmut](https://community.gladysassistant.com/u/mutmut)\
**Post date:** [November 13, 2026, 9:08am UTC](https://community.gladysassistant.com/t/integrations-externes-mettre-a-jour-vers-gladys-5-3-le-sdk-js-0-16-et-le-store/11410/4 "2026-11-13T09:08:22Z")

</div>

Thanks for your feedback!  
I’ve already opened the PRs with Claude on about a hundred integrations he found without countries and your points are well listed in them.  
I already have @lmilcent and @guim31 who have merged the PRs, I’m waiting for the others to make a final PR on the fallback so that it is (almost) clean.
