NDI adapters is the part of the API you use when a managed source in Callaba should reappear as an NDI device that another system can consume immediately. In production, that usually means taking a stable SRT, RTMP, or conference feed and handing it off to an NDI-based workflow without rebuilding the whole pipeline.
The important user question here is not how the backend is implemented. It is whether the team can expose the right program, camera, or speaker feed back into an NDI environment with a predictable device name and a controlled start or stop workflow.
Read this module as a bridge into NDI operations. If one side of your setup already lives inside Callaba but another switcher, graphics system, or room workflow expects NDI, this is where that handoff becomes repeatable.
If your team starts or stops adapters from an operator position, the create, start, and stop examples below also include ready-to-adapt vMix Script tabs.
The useful presets here are source-to-NDI bridges. The output side stays intentionally stable: a named NDI device. What changes is the source family feeding that output.
{
"restream_name": "Camera 1 to Cloud NDI via SRT",
"input": {
"input_type": "INPUT_TYPE_SRT_SOFTWARE",
"application": "IO_APPLICATION_CALLABA_CLOUD_INGRESS_API",
"input_module_id": "66015d2997300f9385d32c00",
"input_stream_url": "",
"input_stream_listen_port": {},
"input_settings": {},
"input_stream_id": "",
"entity_name": "Camera 1 to Cloud NDI via SRT",
"module_name": "MODULE_RESTREAM"
},
"output": {
"output_type": "OUTPUT_TYPE_NDI_DEVICE",
"application": "IO_APPLICATION_CALLABA_CLOUD_INGRESS_API",
"output_stream_url": "",
"output_stream_listen_port": {},
"output_settings": {
"ndi_device_name": "Cloud NDI Camera 1",
"timestamp_offset": 0,
"av_stream_control_mode": "AV_STREAM_CONTROL_VIDEO_AUDIO"
},
"output_stream_key": "",
"entity_name": "Camera 1 to Cloud NDI via SRT",
"module_name": "MODULE_RESTREAM"
},
"module_name": "MODULE_NDI_ADAPTERS",
"active": true
}
{
"restream_name": "RTMP stage feed to Cloud NDI",
"input": {
"input_type": "INPUT_TYPE_RTMP_SOFTWARE",
"application": "IO_APPLICATION_CALLABA_CLOUD_INGRESS_API",
"input_module_id": "66015d2997300f9385d32c10",
"input_stream_url": "",
"input_stream_listen_port": {},
"input_settings": {},
"input_stream_id": "",
"entity_name": "RTMP stage feed to Cloud NDI",
"module_name": "MODULE_RESTREAM"
},
"output": {
"output_type": "OUTPUT_TYPE_NDI_DEVICE",
"application": "IO_APPLICATION_CALLABA_CLOUD_INGRESS_API",
"output_stream_url": "",
"output_stream_listen_port": {},
"output_settings": {
"ndi_device_name": "Cloud NDI Stage Feed",
"timestamp_offset": 0,
"av_stream_control_mode": "AV_STREAM_CONTROL_VIDEO_AUDIO"
},
"output_stream_key": "",
"entity_name": "RTMP stage feed to Cloud NDI",
"module_name": "MODULE_RESTREAM"
},
"module_name": "MODULE_NDI_ADAPTERS",
"active": true
}
{
"restream_name": "Speaker feed to Cloud NDI",
"input": {
"input_type": "INPUT_TYPE_MODULE_CONFERENCES_PARTICIPANT",
"application": "IO_APPLICATION_CALLABA_CLOUD_INGRESS_API",
"input_module_id": "66015d2997300f9385d32c20",
"input_stream_url": "",
"input_stream_listen_port": {},
"input_settings": {},
"input_stream_id": "",
"entity_name": "Speaker feed to Cloud NDI",
"module_name": "MODULE_RESTREAM"
},
"output": {
"output_type": "OUTPUT_TYPE_NDI_DEVICE",
"application": "IO_APPLICATION_CALLABA_CLOUD_INGRESS_API",
"output_stream_url": "",
"output_stream_listen_port": {},
"output_settings": {
"ndi_device_name": "Cloud NDI Speaker",
"timestamp_offset": 0,
"av_stream_control_mode": "AV_STREAM_CONTROL_VIDEO_AUDIO"
},
"output_stream_key": "",
"entity_name": "Speaker feed to Cloud NDI",
"module_name": "MODULE_RESTREAM"
},
"module_name": "MODULE_NDI_ADAPTERS",
"active": true
}
Use an NDI adapter when the ingest side is already controlled in Callaba, but another room, switcher, or graphics system still expects an NDI device.
When an operator depends on a known NDI device name, the adapter layer makes that output predictable even if the upstream source is not native NDI.
An adapter only helps if the bridge is actually running. The runtime checks matter when the team wants to confirm that a named NDI output is truly alive and carrying the source as expected.
Use Create NDI adapter when one managed source should be exposed as a named NDI output device.
The UI presents this as an NDI tool, but the backend contract is a Restream creation call with module_name = MODULE_NDI_ADAPTERS and an output fixed to OUTPUT_TYPE_NDI_DEVICE.
That means the source choice matters more than the destination family here. The create form changes the wording of the selectors, but the saved object is still a restream pipeline underneath.
If this action is driven from an operator station, the examples below also include a ready-to-adapt vMix Script tab.
Use this preset when one managed SRT server should show up as a named Cloud NDI output.
This is the most direct operator-facing bridge from an existing SRT ingest boundary into an NDI device contract.
curl --request POST \--url http://localhost/api/restream/create \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{"restream_name": "Camera 1 to Cloud NDI via SRT","input": {"input_type": "INPUT_TYPE_SRT_SOFTWARE","application": "IO_APPLICATION_CALLABA_CLOUD_INGRESS_API","input_module_id": "66015d2997300f9385d32c00","input_stream_url": "","input_stream_listen_port": {},"input_settings": {},"input_stream_id": "","entity_name": "Camera 1 to Cloud NDI via SRT","module_name": "MODULE_RESTREAM"},"output": {"output_type": "OUTPUT_TYPE_NDI_DEVICE","application": "IO_APPLICATION_CALLABA_CLOUD_INGRESS_API","output_stream_url": "","output_stream_listen_port": {},"output_settings": {"ndi_device_name": "Cloud NDI Camera 1","timestamp_offset": 0,"av_stream_control_mode": "AV_STREAM_CONTROL_VIDEO_AUDIO"},"output_stream_key": "","entity_name": "Camera 1 to Cloud NDI via SRT","module_name": "MODULE_RESTREAM"},"module_name": "MODULE_NDI_ADAPTERS","active": true}'
This is useful for hardware or software sources that already terminate on RTMP inside the platform.
curl --request POST \--url http://localhost/api/restream/create \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{"restream_name": "GoPro RTMP to Cloud NDI","input": {"input_type": "INPUT_TYPE_RTMP_GOPRO","application": "IO_APPLICATION_CALLABA_CLOUD_INGRESS_API","input_module_id": "66015d2997300f9385d32c10","input_stream_url": "","input_stream_listen_port": {},"input_settings": {},"input_stream_id": "","entity_name": "GoPro RTMP to Cloud NDI","module_name": "MODULE_RESTREAM"},"output": {"output_type": "OUTPUT_TYPE_NDI_DEVICE","application": "IO_APPLICATION_CALLABA_CLOUD_INGRESS_API","output_stream_url": "","output_stream_listen_port": {},"output_settings": {"ndi_device_name": "Cloud NDI GoPro","timestamp_offset": 0,"av_stream_control_mode": "AV_STREAM_CONTROL_VIDEO_AUDIO"},"output_stream_key": "","entity_name": "GoPro RTMP to Cloud NDI","module_name": "MODULE_RESTREAM"},"module_name": "MODULE_NDI_ADAPTERS","active": true}'
Use this preset when one participant feed from a video call should be surfaced back into an NDI-aware production environment.
This is the conference-side variant of the same adapter pattern.
curl --request POST \--url http://localhost/api/restream/create \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{"restream_name": "Speaker feed to Cloud NDI","input": {"input_type": "INPUT_TYPE_MODULE_CONFERENCES_PARTICIPANT","application": "IO_APPLICATION_CALLABA_CLOUD_INGRESS_API","input_module_id": "66015d2997300f9385d32c20","input_stream_url": "","input_stream_listen_port": {},"input_settings": {},"input_stream_id": "","entity_name": "Speaker feed to Cloud NDI","module_name": "MODULE_RESTREAM"},"output": {"output_type": "OUTPUT_TYPE_NDI_DEVICE","application": "IO_APPLICATION_CALLABA_CLOUD_INGRESS_API","output_stream_url": "","output_stream_listen_port": {},"output_settings": {"ndi_device_name": "Cloud NDI Speaker","timestamp_offset": 0,"av_stream_control_mode": "AV_STREAM_CONTROL_VIDEO_AUDIO"},"output_stream_key": "","entity_name": "Speaker feed to Cloud NDI","module_name": "MODULE_RESTREAM"},"module_name": "MODULE_NDI_ADAPTERS","active": true}'
Dashboard label: Adapter name.
Human-facing name of the NDI adapter job.
Dashboard label: Source Input.
Real supported runtime families include managed SRT server inputs, managed RTMP server inputs, and conference-participant inputs.
Identifier of the selected source entity in the create form.
Dashboard label: Target Output.
This module pins the output side to OUTPUT_TYPE_NDI_DEVICE.
Dashboard label: NDI® Device Name.
Name of the Cloud NDI output device to create.
Dashboard label: Timestamp offset (ns).
Optional timestamp shift in nanoseconds.
Dashboard label: AV Stream Control.
Controls whether the adapter should publish audio, video, or both.
The UI saves this job as MODULE_NDI_ADAPTERS even though it uses the restream backend paths.
Dashboard label: Enable once created.
Controls whether the adapter should start active.
curl --request POST \--url http://localhost/api/restream/create \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{"restream_name": "Camera 1 to Cloud NDI via SRT","input": {"input_type": "INPUT_TYPE_SRT_SOFTWARE","application": "IO_APPLICATION_CALLABA_CLOUD_INGRESS_API","input_module_id": "66015d2997300f9385d32c00","input_stream_url": "","input_stream_listen_port": {},"input_settings": {},"input_stream_id": "","entity_name": "Camera 1 to Cloud NDI via SRT","module_name": "MODULE_RESTREAM"},"output": {"output_type": "OUTPUT_TYPE_NDI_DEVICE","application": "IO_APPLICATION_CALLABA_CLOUD_INGRESS_API","output_stream_url": "","output_stream_listen_port": {},"output_settings": {"ndi_device_name": "Cloud NDI Camera 1","timestamp_offset": 0,"av_stream_control_mode": "AV_STREAM_CONTROL_VIDEO_AUDIO"},"output_stream_key": "","entity_name": "Camera 1 to Cloud NDI via SRT","module_name": "MODULE_RESTREAM"},"module_name": "MODULE_NDI_ADAPTERS","active": true}'
Identifiers and the saved adapter name.
Saved source definition for the adapter.
Saved NDI output definition for the adapter.
Module marker, active state, and backend-managed timestamps.
The model exposes success: true for successful responses.
{"_id": "67f200000000000000000001","id": "67f200000000000000000001","restream_name": "Camera 1 to Cloud NDI via SRT","input": [{"_id": "67f200000000000000000010","id": "67f200000000000000000010","input_type": "INPUT_TYPE_SRT_SOFTWARE","input_module_id": "66015d2997300f9385d32c00","module_name": "MODULE_RESTREAM"}],"output": [{"_id": "67f200000000000000000020","id": "67f200000000000000000020","output_type": "OUTPUT_TYPE_NDI_DEVICE","output_settings": {"ndi_device_name": "Cloud NDI Camera 1","timestamp_offset": 0,"av_stream_control_mode": "AV_STREAM_CONTROL_VIDEO_AUDIO"},"module_name": "MODULE_RESTREAM"}],"module_name": "MODULE_NDI_ADAPTERS","active": true,"created": "2026-03-24T11:00:00.000Z","modified": "2026-03-24T11:00:00.000Z","success": true}
Use Get NDI adapters count for pagination and quick inventory checks of saved adapter jobs.
Under the hood this count is coming from the restream store with a module filter for MODULE_NDI_ADAPTERS.
NDI adapter list calls scope this to module_name: MODULE_NDI_ADAPTERS.
curl --request POST \--url http://localhost/api/restream/getCount \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{"filter": {"module_name": "MODULE_NDI_ADAPTERS"}}'
Total number of saved NDI adapter jobs visible to the authenticated user.
{"count": 1}
Use Get all NDI adapters for the operator-facing listing of saved bridge jobs.
The dashboard reads this through the regular restream listing path and filters by module_name = MODULE_NDI_ADAPTERS. That is why the object shape matches restream jobs rather than a separate adapter-only schema.
Optional page size for the adapter list.
Optional offset for paginated listing.
Optional sort descriptor. The store defaults to { created: 1 }.
Adapter listings filter to module_name: MODULE_NDI_ADAPTERS.
curl --request POST \--url http://localhost/api/restream/getAll \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{"limit": 10,"skip": 0,"sort": {"created": 1},"filter": {"module_name": "MODULE_NDI_ADAPTERS"}}'
The backend returns a bare array of restream objects filtered to NDI adapters.
[{"_id": "67f200000000000000000001","id": "67f200000000000000000001","restream_name": "Camera 1 to Cloud NDI via SRT","input": [{"_id": "67f200000000000000000010","id": "67f200000000000000000010","input_type": "INPUT_TYPE_SRT_SOFTWARE","input_module_id": "66015d2997300f9385d32c00","module_name": "MODULE_RESTREAM"}],"output": [{"_id": "67f200000000000000000020","id": "67f200000000000000000020","output_type": "OUTPUT_TYPE_NDI_DEVICE","output_settings": {"ndi_device_name": "Cloud NDI Camera 1","timestamp_offset": 0,"av_stream_control_mode": "AV_STREAM_CONTROL_VIDEO_AUDIO"},"module_name": "MODULE_RESTREAM"}],"module_name": "MODULE_NDI_ADAPTERS","active": true,"created": "2026-03-24T11:00:00.000Z","modified": "2026-03-24T11:00:00.000Z","success": true}]
Use Get NDI adapter by id when you need the fully populated adapter object for one bridge job.
This is the method that lets the UI refill the create/edit form with the saved source, NDI output settings, and active state.
Identifier of the adapter job you want to load.
curl --request POST \--url http://localhost/api/restream/getById \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{"id": "67f200000000000000000001"}'
The populated restream-backed adapter object.
{"_id": "67f200000000000000000001","id": "67f200000000000000000001","restream_name": "Camera 1 to Cloud NDI via SRT","input": [{"_id": "67f200000000000000000010","id": "67f200000000000000000010","input_type": "INPUT_TYPE_SRT_SOFTWARE","input_module_id": "66015d2997300f9385d32c00","module_name": "MODULE_RESTREAM"}],"output": [{"_id": "67f200000000000000000020","id": "67f200000000000000000020","output_type": "OUTPUT_TYPE_NDI_DEVICE","output_settings": {"ndi_device_name": "Cloud NDI Camera 1","timestamp_offset": 0,"av_stream_control_mode": "AV_STREAM_CONTROL_VIDEO_AUDIO"},"module_name": "MODULE_RESTREAM"}],"module_name": "MODULE_NDI_ADAPTERS","active": true,"created": "2026-03-24T11:00:00.000Z","modified": "2026-03-24T11:00:00.000Z","success": true}
Use Update NDI adapter when the bridge already exists and only the source mapping, NDI output settings, or active intent should change.
This stays on the same restream-backed contract as create and keeps the adapter under MODULE_NDI_ADAPTERS.
Identifier of the adapter job being updated.
The update contract mirrors create and stays on the restream-backed payload shape.
curl --request POST \--url http://localhost/api/restream/update \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{"restream_name": "Camera 1 to Cloud NDI updated","input": {"input_type": "INPUT_TYPE_SRT_SOFTWARE","application": "IO_APPLICATION_CALLABA_CLOUD_INGRESS_API","input_module_id": "66015d2997300f9385d32c00","input_stream_url": "","input_stream_listen_port": {},"input_settings": {},"input_stream_id": "","entity_name": "Camera 1 to Cloud NDI via SRT","module_name": "MODULE_RESTREAM"},"output": {"output_type": "OUTPUT_TYPE_NDI_DEVICE","application": "IO_APPLICATION_CALLABA_CLOUD_INGRESS_API","output_stream_url": "","output_stream_listen_port": {},"output_settings": {"ndi_device_name": "Cloud NDI Camera 1","timestamp_offset": 0,"av_stream_control_mode": "AV_STREAM_CONTROL_VIDEO_AUDIO"},"output_stream_key": "","entity_name": "Camera 1 to Cloud NDI via SRT","module_name": "MODULE_RESTREAM"},"module_name": "MODULE_NDI_ADAPTERS","active": false,"id": "67f200000000000000000001"}'
The backend returns the updated adapter object.
{"_id": "67f200000000000000000001","id": "67f200000000000000000001","restream_name": "Camera 1 to Cloud NDI updated","input": [{"_id": "67f200000000000000000010","id": "67f200000000000000000010","input_type": "INPUT_TYPE_SRT_SOFTWARE","input_module_id": "66015d2997300f9385d32c00","module_name": "MODULE_RESTREAM"}],"output": [{"_id": "67f200000000000000000020","id": "67f200000000000000000020","output_type": "OUTPUT_TYPE_NDI_DEVICE","output_settings": {"ndi_device_name": "Cloud NDI Camera 1","timestamp_offset": 0,"av_stream_control_mode": "AV_STREAM_CONTROL_VIDEO_AUDIO"},"module_name": "MODULE_RESTREAM"}],"module_name": "MODULE_NDI_ADAPTERS","active": false,"created": "2026-03-24T11:00:00.000Z","modified": "2026-03-24T11:15:00.000Z","success": true}
Use Start NDI adapter to bring the saved bridge process online.
This is a strong fit for button-driven operational workflows because the adapter may already be provisioned and only needs runtime activation.
Identifier of the adapter job to start.
curl --request POST \--url http://localhost/api/restream/start \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{"id": "67f200000000000000000001"}'
The backend marks the adapter as active and returns the updated object.
{"_id": "67f200000000000000000001","id": "67f200000000000000000001","restream_name": "Camera 1 to Cloud NDI via SRT","input": [{"_id": "67f200000000000000000010","id": "67f200000000000000000010","input_type": "INPUT_TYPE_SRT_SOFTWARE","input_module_id": "66015d2997300f9385d32c00","module_name": "MODULE_RESTREAM"}],"output": [{"_id": "67f200000000000000000020","id": "67f200000000000000000020","output_type": "OUTPUT_TYPE_NDI_DEVICE","output_settings": {"ndi_device_name": "Cloud NDI Camera 1","timestamp_offset": 0,"av_stream_control_mode": "AV_STREAM_CONTROL_VIDEO_AUDIO"},"module_name": "MODULE_RESTREAM"}],"module_name": "MODULE_NDI_ADAPTERS","active": true,"created": "2026-03-24T11:00:00.000Z","modified": "2026-03-24T11:20:00.000Z","success": true}
Use Stop NDI adapter to take the bridge offline without deleting its saved configuration.
Operationally this is the natural companion to start when the output device should disappear for the moment but the job should stay reusable.
Identifier of the adapter job to stop.
curl --request POST \--url http://localhost/api/restream/stop \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{"id": "67f200000000000000000001"}'
The backend marks the adapter as inactive and returns the updated object.
{"_id": "67f200000000000000000001","id": "67f200000000000000000001","restream_name": "Camera 1 to Cloud NDI via SRT","input": [{"_id": "67f200000000000000000010","id": "67f200000000000000000010","input_type": "INPUT_TYPE_SRT_SOFTWARE","input_module_id": "66015d2997300f9385d32c00","module_name": "MODULE_RESTREAM"}],"output": [{"_id": "67f200000000000000000020","id": "67f200000000000000000020","output_type": "OUTPUT_TYPE_NDI_DEVICE","output_settings": {"ndi_device_name": "Cloud NDI Camera 1","timestamp_offset": 0,"av_stream_control_mode": "AV_STREAM_CONTROL_VIDEO_AUDIO"},"module_name": "MODULE_RESTREAM"}],"module_name": "MODULE_NDI_ADAPTERS","active": false,"created": "2026-03-24T11:00:00.000Z","modified": "2026-03-24T11:25:00.000Z","success": true}
Use Remove NDI adapter to delete the saved bridge job.
Because this module is restream-backed, the remove behavior follows the restream lifecycle rather than a separate NDI-only storage layer.
Identifier of the adapter job to delete.
curl --request DELETE \--url http://localhost/api/restream/remove \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{"id": "67f200000000000000000001"}'
The docs use the previously loaded adapter object as the reference shape for a successful remove flow.
{"_id": "67f200000000000000000001","id": "67f200000000000000000001","restream_name": "Camera 1 to Cloud NDI via SRT","input": [{"_id": "67f200000000000000000010","id": "67f200000000000000000010","input_type": "INPUT_TYPE_SRT_SOFTWARE","input_module_id": "66015d2997300f9385d32c00","module_name": "MODULE_RESTREAM"}],"output": [{"_id": "67f200000000000000000020","id": "67f200000000000000000020","output_type": "OUTPUT_TYPE_NDI_DEVICE","output_settings": {"ndi_device_name": "Cloud NDI Camera 1","timestamp_offset": 0,"av_stream_control_mode": "AV_STREAM_CONTROL_VIDEO_AUDIO"},"module_name": "MODULE_RESTREAM"}],"module_name": "MODULE_NDI_ADAPTERS","active": true,"created": "2026-03-24T11:00:00.000Z","modified": "2026-03-24T11:00:00.000Z","success": true}
Use Get NDI adapter stat when the question is “is the bridge process alive and moving?” rather than “is the adapter saved?”
This reuses the same live process-stat path as the restream engine, which is why it is useful for operator checks before or during a show.
curl --request POST \--url http://localhost/api/restream/getStat \--header 'x-access-token: <your_api_token>' \--header 'Content-Type: application/json' \--data '{}'
Current process-stat rows used by the adapter listing and operational checks.
Current runtime bitrate values for the adapter process.
Current FFmpeg-style progress values for the running bridge.
[{"processData": {"id": "67f200000000000000000001","bitrate": "3200.5kbits/s","bitrate_kbits": 3200,"fps": "30","speed": "1.00x","progress": "continue"}}]