> For the complete documentation index, see [llms.txt](https://docs.opendatadiscovery.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.opendatadiscovery.org/integrations/integrations/integration-wizard.md).

# Integration Wizard

The Integration Wizard — the in-app UI under Management → Integrations that generates collector\_config.yaml snippets for the integrations the platform recognises.

The **Integration Wizard** is an in-app UI under [**Management → Integrations**](/features/management.md) that helps operators bootstrap a `collector_config.yaml` for the integrations the platform recognises. It is a **template generator**, not an installer: it does not deploy a collector, write to disk, or talk to any source system. It produces a parameterised YAML snippet that the operator copies into their own `collector_config.yaml`.

## What the wizard does

* Lists every integration the platform's classpath registers (one card per integration; sorted case-insensitively by id).
* For each integration, renders a multi-section wizard panel:
  * **Title and description** — taken from the integration's manifest (`IntegrationPreview` model: `id`, `name`, `description`).
  * **Content blocks** — ordered sections, each with a title, prose content, and zero-or-more code snippets. Use these to walk the operator through prerequisites, snippet selection, and post-deploy verification (whatever the manifest author put there).
  * **Code snippets** — parameterised templates with form fields. The operator fills in the inputs; the wizard interpolates them; the rendered output is shown ready to copy.

## What it does NOT do

* It does not deploy or launch a collector — that is operator-side work, see [Deployment Options](/configuration-and-deployment/deployment.md).
* It does not write `collector_config.yaml` for you — the file lives on the host running the collector; the wizard only feeds you a snippet.
* It does not validate the snippet against a target source — credentials, hosts, and ports are typed at face value.
* It is not the same surface as the [Integrations hub](/integrations/integrations.md) — the hub documents what each integration is, the wizard generates configuration for some of them.

## How operators use it

1. **Open** [Management → Integrations](/features/management.md) in the platform UI.
2. **Pick** an integration card (PostgreSQL, Snowflake, …).
3. **Read** the wizard's content blocks (prerequisites, instructions).
4. **Fill in** the form parameters the wizard prompts for (host, port, credentials, …). The wizard pre-fills any **static** parameter — see "Static parameters" below.
5. **Copy** the rendered YAML snippet into the `plugins:` list of your `collector_config.yaml`.
6. **Run** your collector with the updated config — see [Build and run ODD Collectors](/developer-guides/build-and-run/build-and-run-odd-collectors.md) or the [chart-based deployment options](/configuration-and-deployment/deployment.md).

## Static parameters

A code-snippet argument has an `isStatic` flag (and a `staticValue` field on the wire). When `isStatic = true`, the platform — not the operator — supplies the value. Today exactly one parameter is wired up this way: **`platform_url`**, read from `odd.platform-base-url` (`StaticArgumentMappingContext.java:11-19`). The Java field default is the placeholder string `http://your.odd.platform`, so on a fresh deployment without the key set explicitly the wizard will pre-fill `platform_url` with that placeholder — see [Configure ODD Platform → odd.platform-base-url](/configuration-and-deployment/odd-platform.md#odd-platform-base-url) for the full caveat about this default. Always set `odd.platform-base-url` to your real deployment URL in any non-local environment, **then** open the wizard so the snippets carry a working URL out of the box.

All other arguments default to `isStatic = false` and are entered by the operator.

## API surface

The wizard's two backing endpoints — `GET /api/integrations` (list) and `GET /api/integrations/{integration_id}` (full overview with content blocks and code snippets) — are documented at [API Reference → Integrations](/developer-guides/api-reference/integrations.md). Call them directly to script integration-snippet generation outside the in-app UI.

{% hint style="warning" %}
**The wizard endpoints carry no RBAC permission gate — any authenticated user reads the full integration registry, and under `auth.type=DISABLED` the registry is anonymously reachable.** Both `GET /api/integrations` and `GET /api/integrations/{integration_id}` fall through to the platform's default `.authenticated()` matcher; the platform's security wiring has no `SecurityRule` entry for `/api/integrations*`, and the controller methods carry no `@PreAuthorize`. The UI's placement under **Management → Integrations** suggests admin-only access (sibling tabs like Datasources, Collectors, and Owners gate their write actions on `*_CREATE` / `_UPDATE` / `_DELETE` permissions), but the wizard endpoints are not gated even at write — they are read-only by shape, and the read surface is the entire wizard registry including each integration's content blocks and the `platform_url` value rendered into them.

Operators expecting the wizard registry to be admin-only — including the values pre-filled into each integration's static parameters (today exactly one: `platform_url`) — discover the any-authenticated reach only through API enumeration. Under DISABLED, the registry is reachable by any anonymous network caller. This is consistent with the platform's broader read-collaborative authorization posture across the Management section (see [Management → Tab visibility versus mutate gates](/features/management.md#tab-visibility-versus-mutate-gates)).

**Mitigation today.** Apply a reverse-proxy authz filter on `/api/integrations*` if admin-only read of the wizard registry is a deployment requirement. Treat the `platform_url` static parameter as deployment-public — do not put sensitive information in the integration manifests' content blocks. The upstream platform-side fix is either to introduce an `INTEGRATION_READ` permission and gate the controller, or to add a `SecurityRule` entry that restricts the path to an existing permission — both are read-posture decisions that fit the broader ODD Platform authorization-model work.
{% endhint %}

## Integration registry

The wizard is data-driven. Every integration card is one YAML manifest packaged on the platform's classpath at `META-INF/wizard/*.yaml`. At startup `IntegrationRegistryFactory` scans `classpath*:META-INF/wizard/*.yaml` (Spring's `PathMatchingResourcePatternResolver`), parses each manifest into an `IntegrationOverviewDto`, and stores them in a case-insensitive `TreeMap` keyed by `id`. Adding a new integration to the wizard means dropping a new manifest into a JAR on the platform's classpath; the platform does not currently support hot-reload — a restart is required.

The exact manifest schema is the contract defined by `IntegrationOverviewDto` and its nested DTOs (`IntegrationPreviewDto`, `IntegrationContentBlockDto`, `IntegrationCodeSnippetDto`, `IntegrationCodeSnippetArgumentDto`, `IntegrationCodeSnippetArgumentTypeEnum`).

## Wizard vs `collector_config.yaml`

|                  | Integration Wizard                              | `collector_config.yaml`                                                                                     |
| ---------------- | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| Where it lives   | In the Platform UI (Management → Integrations)  | On the host running the collector                                                                           |
| What it produces | A YAML snippet for one plugin (one integration) | The full collector configuration: `platform_host_url`, `token`, `default_pulling_interval`, `plugins:` list |
| Who reads it     | The operator setting up an integration          | The collector process at startup                                                                            |
| Persistence      | None — the wizard re-renders each time          | The file you keep under source control                                                                      |

The wizard is a **starting point**, not a replacement. Operators still maintain `collector_config.yaml` themselves — combining wizard-generated snippets with hand-authored ones (multiple plugins of the same type, custom filters, secrets backend references, environment-variable overrides). For the full file shape see the [Integrations hub → Common configuration](/integrations/integrations.md#common-configuration-collectors) and the [collector build-and-run guide](/developer-guides/build-and-run/build-and-run-odd-collectors.md).

## Where to next

* [Integrations hub](/integrations/integrations.md) — what each integration is, paired with the wizard cards on the same in-app surface.
* [Build and run ODD Collectors](/developer-guides/build-and-run/build-and-run-odd-collectors.md) — fields the wizard does not surface (filters, secrets, `default_pulling_interval`, …).
* [Configure ODD Platform → `odd.platform-base-url`](/configuration-and-deployment/odd-platform.md#odd-platform-base-url) — set this before opening the wizard so static `platform_url` substitution carries a working URL.
* [Collector secrets backend](/configuration-and-deployment/collectors-secrets-backend.md) — keep wizard-generated credentials out of the YAML you commit.
