Integration Development
An integration is the unit of functionality in ApexOS. Each integration owns a domain — a short, unique, lowercase identifier made of characters and underscores — and packages everything needed to connect a device, service, or helper to the platform: setup code, a manifest, config flows, entity platforms, and translations.
Where integrations live
Built-in integrations are Python packages inside the core repository, under:
apexos/components/<domain>/
The domain must match the directory name; the manifest validator rejects any
mismatch. A typical integration directory looks like this (the sun integration is a
good minimal reference):
apexos/components/sun/
├── __init__.py # setup / unload entry points
├── manifest.json # metadata (see the manifest reference)
├── config_flow.py # UI-driven configuration
├── const.py # DOMAIN and other constants
├── entity.py # shared entity base for the integration
├── sensor.py # a platform (one file per entity platform)
├── binary_sensor.py
├── strings.json # translatable texts (source of truth)
├── icons.json
└── translations/ # per-language files: en.json, de.json, ...
Integrations installed by users outside the core tree are custom integrations and
live in a custom_components/ directory instead — see
Custom integrations.
The core object every integration works with is apex, an instance of ApexOS
(apexos.core.ApexOS) — see The apex object.
Scaffolding a new integration
The core repository ships a scaffold tool. Run it from the repository root (it
checks for requirements_all.txt and exits otherwise):
python3 -m script.scaffold integration
The first positional argument is a template name. Available templates:
| Template | Purpose |
|---|---|
integration | A new integration skeleton (also generates a config flow) |
config_flow | Config flow for a manually configured integration |
config_flow_discovery | Config flow for a discoverable integration |
config_flow_helper | Config flow for a helper integration |
config_flow_oauth2 | Config flow using OAuth2 |
backup | Backup platform |
device_action / device_condition / device_trigger | Device automation platforms |
reproduce_state | Reproduce-state support |
significant_change | Significant-change support |
Options:
--integration <domain>— target an existing integration instead of prompting.--develop— fill in all answers automatically (domaindevelop) and run the integration's tests at the end.
What the tool asks
For a new integration the scaffolder prompts for:
- domain — must be unique, cannot be changed, must match the directory name, and must contain no spaces or special characters.
- name — the human-readable integration name.
- GitHub handle — becomes the entry in
codeowners(an@is prepended if you omit it). - PyPI requirement — optional; versions must be pinned with
==. - iot_class — one of
assumed_state,calculated,cloud_polling,cloud_push,local_polling,local_push. - Whether the user must authenticate, whether the device is discoverable on
the local network, the integration type, and whether OAuth2 applies. These
answers pick the config-flow template that is generated alongside the integration
(helper →
config_flow_helper, OAuth2 →config_flow_oauth2, authentication or not discoverable →config_flow, otherwise →config_flow_discovery).
What it generates
The integration template produces __init__.py, const.py, a
quality_scale.yaml (all rules set to todo), and this manifest:
{
"domain": "NEW_DOMAIN",
"name": "NEW_NAME",
"codeowners": [],
"config_flow": false,
"dependencies": [],
"documentation": "https://www.apexinfosys.in/integrations/NEW_DOMAIN",
"homekit": {},
"iot_class": "IOT_CLASS",
"quality_scale": "bronze",
"requirements": [],
"ssdp": [],
"zeroconf": []
}
Note the documentation URL convention for built-in integrations:
https://www.apexinfosys.in/integrations/<domain> — this exact prefix is
enforced by the manifest validator.
What runs afterwards
After generating files the scaffolder automatically runs:
python -m script.apexfest --integration-path <dir> --skip-plugins quality_scale— the manifest/integration validator (quality scale is skipped because a fresh skeleton cannot pass it yet).python -m script.gen_requirements_all— regenerates the aggregated requirement files.python -m script.translations develop --integration <domain>— generates translation files fromstrings.json.
With --develop it additionally runs pytest against
tests/components/<domain>.