Skip to content
OAOpenAppPhysical Security as a Service
Login

Integrations

Integrations bind external systems (provider types) into an organization: devices, entities, and portal flows hang off an integration id. Almost everything requires X-Org — see Organization context & pagination. Shapes follow IntegrationResponse, CreateIntegrationRequest, UpdateIntegrationRequest, and related schemas in the API reference.

Related: per-entity automation lives under Entities (POST /entities/{id}/actions/{action_id}). GET /integrations/{id}/entities (list_integration_entities) lists entities owned by devices on that integration — same pagination/output rules as org GET /entities.

Some URLs under /integrations/... are tagged elsewhere in OpenAPI: .../building-users (Apartment Residents), .../lan-agent/... (LAN agent), .../zones (Zones — see Zones).

AreaRepresentative HTTPoperationIdNotes
CatalogGET / POST /integrationslist_integrations, create_integrationList requires output_options + pagination, optional provider_type, q.
Provider catalogGET /integrations/provider-types, GET .../definitionlist_integration_provider_types, get_integration_provider_definitionStatic discovery for dashboards and codegen.
Instance + lifecycleGET/PUT /integrations/{id}, DELETE .../purge, POST .../restoreget_integration, update_integration, hard_delete_integration, restore_integrationPurge is destructive removal per bundle rules.
Device metadata schemaGET .../device-metadata-schemaget_integration_device_metadata_schemaJsonForms/schema hints for device_metadata on devices under this integration.
DiscoveryGET .../discovered-devicesget_integration_discovered_devicesProvider-specific provisioning candidates.
Entities (integration scope)GET .../entitieslist_integration_entitiesRequires output_options + pagination; optional entity_type.
OpsGET .../ops, POST .../ops/{op_id}list_integration_ops, execute_integration_opProvider maintenance / sync jobs — JSON body often {}.
Access portalsGET/POST .../access-portals, GET /integrations/access-portals/{portal_id}, PUT/DELETE .../access-portals/{portal_id}list_integration_access_portals, create_integration_access_portal, get_access_portal_by_id, update_integration_access_portal, delete_integration_access_portalBuilding entry portals for virtual access flows.
Access invitesPUT/DELETE .../access-invites/{invite_link_id}, POST .../restoreupdate_integration_access_invite, delete_integration_access_invite, restore_integration_access_invite

Multipart POST /integrations/{id}/image may exist where deployments expose it — Python includes upload_image / upload_image_from_url (see Python — Resources).

CapabilityPythonRust (openapp_sdk)GoTypeScript (AsyncClient)
Surface aboveclient.integrations — matches methods on IntegrationsClientclient.integrations() — thin JSON helpers for the same pathsIntegrationsAPIServiceNot on façade

GET /integrations: Rust list() is a bare GET /integrations — OpenAPI requires output_options + pagination; use transport() + RequestSpec for parity (same story as Devices). integrations.entities(id) in Python/Rust is a bare GET .../entities — the bundle expects output_options + pagination; use Go or explicit RequestSpec for full wire fidelity.

401 / 403 on org or integration access.404 for unknown ids.400 / 422 on validation.426 can appear on LAN-agent compatibility routes (see LAN agent docs when shipped). See Errors & retries.

page = await client.integrations.list(org_id="org_123")

Wire parity for output_options / pagination may require raw requests — compare list_integrations in the bundle.

result = await client.integrations.run_op(integration_id, "some_op_id")

Provider catalog (GET .../provider-types, GET .../definition)

Section titled “Provider catalog (GET .../provider-types, GET .../definition)”

Use this before create_integration to pick a provider_type and load ProviderDefinition (capabilities, schema hooks) for dashboards or CLIs.

types = await client.integrations.provider_types()
definition = await client.integrations.provider_definition("virtual_demo")

OpenAPI marks X-Org as required on this route — the Go client models it explicitly. Python/Rust high-level helpers assume your gateway or interceptors supply org context when needed.

row = await client.integrations.get(integration_id)

If your stack requires an explicit org header for this path, wire X-Org through client configuration (see Python resources overview) or a RequestSpec interceptor — match what get_integration expects in the bundle.

Body CreateIntegrationRequestorg_id and provider_type are required; optional name, config, secrets, enabled (see schemas in the API reference).

created = await client.integrations.create(
org_id=org_id,
provider_type="virtual_demo",
name="Demo bridge",
)

OpenAPI requires X-Org on update_integration, restore_integration, and hard_delete_integration — the Go builder enforces it; Python/Rust high-level helpers omit the header on the wire, so use transport + RequestSpec when your gateway rejects the request.

updated = await client.integrations.update(
integration_id,
name="Renamed bridge",
enabled=False,
)
restored = await client.integrations.restore(integration_id)
await client.integrations.purge(integration_id)

Discovered devices (GET /integrations/{id}/discovered-devices)

Section titled “Discovered devices (GET /integrations/{id}/discovered-devices)”

Provider-specific provisioning candidates. X-Org is required; the Go return type is interface{} (the body shape varies by provider — decode into your own struct or map[string]any).

candidates = await client.integrations.discovered_devices(integration_id)

list_integration_access_portals returns ListIntegrationAccessPortalsResponse; create_integration_access_portal takes a CreateAccessPortalRequest (required name — accepts a string or LocalizedString map; optional device_external_id to bind the portal to a virtual_access_portal device) and returns CreateAccessPortalResponse (id, public_id, name). Both require X-Org.

portals = await client.integrations.list_access_portals(integration_id)
created = await client.integrations.create_access_portal(
integration_id,
name={"en": "Lobby"},
device_external_id="lobby-gate",
)
public_id = created["public_id"]

UpdateAccessPortalRequest has no required fields — set whichever of name (localized) or device_external_id you want to change (null unlinks). Both routes require X-Org.

updated = await client.integrations.update_access_portal(
integration_id,
portal_id,
name={"en": "Lobby (renamed)"},
)
await client.integrations.delete_access_portal(integration_id, portal_id)

UpdateAccessInviteRequest is fully optional — common fields are is_enabled, name, expires_in, valid_from / valid_to, max_uses, portal_ids, schedules (replaces all entries when set), and disabled_justification. delete_integration_access_invite is a hard delete; restore_integration_access_invite undoes a soft revoke. All three require X-Org.

edited = await client.integrations.update_access_invite(
integration_id,
invite_link_id,
is_enabled=False,
disabled_justification="lost token",
)
await client.integrations.delete_access_invite(integration_id, invite_link_id)
restored = await client.integrations.restore_access_invite(integration_id, invite_link_id)

Look up a portal by id (GET /integrations/access-portals/{portal_id})

Section titled “Look up a portal by id (GET /integrations/access-portals/{portal_id})”

Resolves the portal’s owning integration so dashboards can build deep links. The path is integration-less (uses portal_id only) but X-Org is still required on the wire (the Go builder enforces it).

portal = await client.integrations.get_access_portal(portal_id)
integration_id = portal["integration_id"]

Device metadata schema (GET /integrations/{id}/device-metadata-schema)

Section titled “Device metadata schema (GET /integrations/{id}/device-metadata-schema)”

Returns IntegrationDeviceMetadataSchemaResponse — provider JSON Schema dashboards use to render generic labels for device_metadata fields. Different from per-device get_device_metadata_definition (Devices). X-Org required.

schema = await client.integrations.device_metadata_schema(integration_id)

List integration entities (GET /integrations/{id}/entities)

Section titled “List integration entities (GET /integrations/{id}/entities)”

Returns PaginatedResponseEntityResponse. The Go builder requires XOrg, OutputOptions, and Pagination; optional EntityType filter. Python and Rust ship bare helpers — same pattern as list_entities where parity needs transport + RequestSpec.

rows = await client.integrations.entities(integration_id)