For design software vendors
Implement ODIO in your tool
A practical guide for AV, CAD, and schematic software vendors — EasySchematic, XTEN-AV, AVCAD, D-Tools, Visio, Stardraw, and the like — to consume OpenDeviceIO so your users import accurate device data instead of re-keying PDF spec sheets. You can pull data from the free, read-only public API or read .odio files directly with the SDK.
Are you a manufacturer?
Brands can publish authoritative, manufacturer-verified files for their own products. Approved reps upload .odio files through the web UI or an authenticated POST /api/v1/devices token. Request access on the Contribute page →
What ODIO is
ODIO (OpenDeviceIO) is an open, machine-readable format describing a hardware device's externally observable I/O, power, physical, and compliance characteristics. The heart of the format is the port, and each port separates three concerns — the connector → link → signals model:
- Connector — the physical jack only:
rj45,xlr-3-f,hdmi-type-a,phoenix. Pole count lives here. - Link — the physical pipe that connector provides: 1 GbE with 802.3at PoE, USB with a 60 W PD budget, single-mode fiber. Stated once per port.
- Signals — one or more concurrent logical flows, each in its domain:
video,audio,control,network,data,power. One HDMI port carries video + audio; one RJ45 can carry Dante + AES67 + general LAN.
A document's kind is one of device, bundle (a kit / assembly — a part number that contains devices, sub-assemblies, and cables), or cable (a first-class cable with typed ends). See the whitepaper for the full data model.
Consuming ODIO
There are two ways to get ODIO data into your tool:
1. The TypeScript SDK
Install the SDK and read .odio files (whether you fetched them, bundled them, or accepted them as an import):
shellnpm install @opendeviceio/sdk
The SDK gives you:
validateDocument(doc)/validateBundle/validateCable— schema validation; returns{ valid, errors }.parseDocument(doc)/parse— validate and return a typed value, throwing on failure.flattenBundle(bundle)— expand a kit into its constituent devices plus cable / accessory line items (the bill of materials). Use this when a bundle should render as several device blocks with cable accessories between them.- Accessors such as
inputPorts,outputPorts,portsByConnector,signalsByDomain,totalMaxWatts,poeBudget, andrackUnitsfor derived facts.
2. The public REST API
If you would rather not bundle the SDK, fetch JSON straight from the public API. It is free, read-only, and CORS-enabled, so you can call it from a browser plugin or a backend. Validate the response with the SDK if you want strong typing; the data already validated before it entered the registry.
Mapping recipe: ODIO ports → your port model
ODIO models a port as one connector that can carry several concurrent signals. Most schematic and CAD tools model the opposite: one signal per port. This mismatch is the single most important thing to get right.
The key lesson
If your tool models one signal per port (most do), collapse each multi-signal connector down to ONE port and pick a primary signal by domain priority:
video > audio > control > network > data > power
Keep the signals you did not promote as notes on that port, so nothing is silently dropped. An HDMI port (video + audio) becomes one port whose primary domain is video, with “also carries audio” recorded as a note.
This is exactly what the reference EasySchematic adapter does: it emits one ES port per ODIO connector, choosing the primary signal by that priority order. The collapse keeps the drawn back panel faithful (one jack = one port) while preserving the richer multi-signal truth as annotations.
For bundles, run flattenBundle first: each contained device becomes its own device block, and the cables / accessories become cable accessories or line items between them. Do not try to draw a bundle as a single device.
Reference implementation: copy the adapter
Rather than write the mapping from scratch, start from the reference adapter package @opendeviceio/adapters — it contains the EasySchematic exporter, which implements the connector-to-port collapse and primary-signal selection described above. Copy its approach (and, if your stack is TypeScript, much of its code) and adjust the output shape to your tool's own port / device model.
Code snippets
Fetch a device from the public API:
typescript// Fetch a single ODIO document from the free, read-only public API. // ids contain slashes, e.g. "lightware/ucx-4x2-hc60d". async function fetchDevice(id: string) { const res = await fetch(`https://opendeviceio.org/api/v1/devices/${id}`); if (res.status === 404) return null; // unknown id if (!res.ok) throw new Error(`ODIO API ${res.status}`); return res.json(); // the full ODIO document } // Search / list (paged): returns { data, total, limit, offset }. async function searchDevices(q: string) { const url = new URL("https://opendeviceio.org/api/v1/devices"); url.searchParams.set("q", q); url.searchParams.set("limit", "50"); const res = await fetch(url); return res.json(); }
Validate it with the SDK before trusting it:
typescriptimport { parseDocument, validateDocument } from "@opendeviceio/sdk"; const doc = await fetchDevice("lightware/ucx-4x2-hc60d"); // Validate before trusting it. validateDocument detects the kind from $schema. const result = validateDocument(doc); if (!result.valid) { console.error(result.errors); throw new Error("Document failed ODIO validation"); } // Or parse-and-throw, returning a typed value: const device = parseDocument(doc); // OdioDevice | Bundle | Cable
The primary-signal collapse — one ODIO port to one tool port — the same logic the EasySchematic adapter uses:
typescriptimport type { OdioDevice, Port, Signal } from "@opendeviceio/sdk"; // Most schematic/CAD tools model ONE signal per port. ODIO ports can carry // several concurrent signals (one HDMI port = video + audio; one RJ45 = // Dante + AES67 + LAN). To map an ODIO device into a one-signal-per-port // tool, collapse each connector to a single port and pick a PRIMARY signal // by domain priority, keeping the rest as notes. const DOMAIN_PRIORITY = [ "video", "audio", "control", "network", "data", "power" ] as const; function primarySignal(port: Port): Signal | undefined { const signals = port.signals ?? []; if (signals.length <= 1) return signals[0]; // Lower index in DOMAIN_PRIORITY wins; unknown domains sort last. return [...signals].sort((a, b) => { const ia = DOMAIN_PRIORITY.indexOf(a.domain as never); const ib = DOMAIN_PRIORITY.indexOf(b.domain as never); return (ia < 0 ? 99 : ia) - (ib < 0 ? 99 : ib); })[0]; } interface ToolPort { id: string; label: string; direction: "input" | "output" | string; connector: string; primaryDomain?: string; notes: string[]; // the signals we did NOT promote, for the human } function toToolPort(port: Port): ToolPort { const primary = primarySignal(port); const others = (port.signals ?? []).filter((s) => s !== primary); return { id: port.id, label: port.label ?? port.id, direction: port.direction, connector: port.connector, primaryDomain: primary?.domain, notes: others.map( (s) => `also carries ${s.domain} (${s.transport ?? "n/a"})` ) }; } // One ODIO port -> exactly one tool port. This is what the reference // EasySchematic adapter does (one ES port per connector). function deviceToToolPorts(device: OdioDevice): ToolPort[] { return (device.ports ?? []).map(toToolPort); }
The public API
Two endpoints, both CORS-enabled and free to use without a key. Full parameter and response documentation is on the API reference page.
GET /api/v1/devices— list / search the registry (paged).GET /api/v1/devices/{id}— fetch the full ODIO document by id (ids contain slashes).
Schemas & licensing
The canonical JSON Schemas are hosted with permissive CORS at https://opendeviceio.org/schema/v0.1/*.schema.json — device, bundle, and cable. Every document references its schema via $schema, so $ref resolution works from any validator.
The registry data is free and read-only. The schema and SDK are Apache-2.0; the spec and docs are CC BY 4.0. You are free to ship an ODIO importer in a commercial product.