# API Reference Reference material for `@monad-inc/embed/connect`: the `createConnectorFrame` options, theming tokens, the request thunk, catalog reads, connector icons, the security model, and the backend route contract. ## What the package gives you Everything ships in `@monad-inc/embed`, a public npm package with TypeScript types and no runtime dependencies. Import from the `/connect` subpath. **The iframe mount:** - `createConnectorFrame(options)` — returns a `ConnectorFrame` handle with `.destroy()`. **Pipeline lifecycle helpers** (each takes a `request` thunk): - `buildDevNullPipeline({ request, org, inputId, inputName })` - `findIntegrationPipeline({ request, org, inputId })` - `setIntegrationEnabled({ request, org, pipelineId, enabled })` — plus `enableIntegration` / `disableIntegration` - `deleteIntegration({ request, org, pipelineId?, inputId?, outputId?, cleanup })` **Constants and types:** `CLEANUP_FULL`, `CLEANUP_KEEP_OUTPUT`, `CLEANUP_PIPELINE_ONLY`, and the types `Appearance`, `ComponentKind`, `ConnectorFrame`, `ConnectorFrameOptions`, `BuiltPipeline`, `CleanupPolicy`, `ResolvedIntegration`, `MonadRequest`, and the protocol messages. See [Connector Lifecycle](/sdks/embed/lifecycle) for how the helpers and constants fit together. ## `createConnectorFrame` options | Option | Type | Required | Default | Description | | --- | --- | --- | --- | --- | | `container` | `HTMLElement \| string` | Yes | — | Element (or CSS selector) the iframe is appended to. | | `sessionToken` | `string` | Yes | — | Short-lived token from `POST /v3/sessions` (your backend mints this). | | `organizationId` | `string` | Yes | — | Monad team org id the session is scoped to. Same value you passed to `/v3/sessions`. | | `kind` | `'input' \| 'output'` | Yes | — | Which catalog the connector belongs to. | | `typeId` | `string` | Yes | — | Connector type slug, e.g. `'aws-cloudtrail'`, `'okta-systemlog'`. | | `existingId` | `string` | No | — | Pass to edit an existing connector. Omit to create a new one. | | `displayName` | `string` | No | the connector type's name | Title shown in the iframe header. | | `name` | `string` | No | type name + unique suffix | Name for the created connector. On edit, omit to keep the existing name. | | `description` | `string` | No | the connector type's description | Description for the created connector. On edit, omit to keep the existing description. | | `isNameEditable` | `boolean` | No | `false` | Show an editable name input in the iframe (prefilled with `name` if provided, else the type name). A non-empty name is required when shown. | | `isDescriptionEditable` | `boolean` | No | `false` | Show an editable description input in the iframe (prefilled with `description` if provided). | | `appearance` | `Appearance` | No | Monad defaults | Theming tokens (see below). | | `synthetic` | `boolean` | No | `false` | Exposes Monad's internal synthetic-data toggle. Keep off in production. | | `frameOrigin` | `string` | No | `https://app.monad.com/embed` | Override only for non-prod testing. | | `apiBase` | `string` | No | `https://app.monad.com/api` | Override only for non-prod testing. | | `onSave` | `(c: { id, name? }) => void` | No | — | Fired when the user saves successfully. | | `onCancel` | `() => void` | No | — | Fired when the user cancels. | | `onError` | `(message: string) => void` | No | — | Fired on a save / test / load failure. | The call returns a handle: ```ts const frame = createConnectorFrame({ /* ... */ }); frame.destroy(); // remove the iframe + listeners ``` ## Theming with `appearance` Six tokens, applied as CSS custom properties inside the iframe: ```ts createConnectorFrame({ /* ... */ appearance: { colorPrimary: '#2f4bff', // primary buttons, focus rings colorText: '#0e1726', // body text + derived muted/faint shades colorBackground: '#ffffff', colorBorder: '#e3e7ee', fontFamily: "'Inter', system-ui, sans-serif", borderRadius: '10px', }, }); ``` The iframe is cross-origin, so your stylesheets can't bleed in — by design. These six tokens are the main theming channel. `appearance` applies once at mount, so changing a token means a `destroy()` and remount (see [Best Practices](/sdks/embed/best-practices#session-and-theming-performance)). For cases the tokens can't cover, `stylesheets` replaces Monad's CSS wholesale. ## The `MonadRequest` thunk `MonadRequest` is the seam between the lifecycle helpers and your authentication. You build a function with your API key already closed over and hand it to the helpers; they call it when they need the Monad API, and never see the key. Build it once, on your backend: ```ts import type { MonadRequest } from '@monad-inc/embed/connect'; interface MonadConfig { apiKey: string; apiBase: string; } export function monadRequest(cfg: MonadConfig): MonadRequest { return async (path, init) => { const r = await fetch(`${cfg.apiBase}${path}`, { ...init, headers: { 'Content-Type': 'application/json', Authorization: `ApiKey ${cfg.apiKey}`, // key stays server-side ...(init?.headers ?? {}), }, }); if (!r.ok) throw new Error(`${r.status} ${path}: ${(await r.text()).slice(0, 300)}`); const text = await r.text(); return text ? JSON.parse(text) : undefined; }; } ``` Retries, logging, or a proxy all live inside this function, out of the SDK's way. ## Rendering your own catalog The type list and a tenant's configured connectors are plain Monad API reads behind your backend: - **Available types (global):** `GET /v1/{kind}s`, each with `type_id` and `name`. You rarely surface all 300+; keep a server-side allow-list of the `type_id`s you support. - **A tenant's configured connectors (team-scoped):** `GET /v1/{org}/{kind}s`, wrapped as `{ inputs: [...] }` or `{ outputs: [...] }`. The configured list is paginated; pass `?limit=&offset=`. ```ts const req = monadRequest(cfg); const types = await req(`/v1/${kind}s`); // [{ type_id, name }, ...] const page = await req(`/v1/${org}/${kind}s?limit=1000&offset=0`); const configured = page[`${kind}s`]; // unwrap { inputs: [...] } ``` :::warning Field-name mismatch Configured rows carry the type slug as `type`, not `type_id`. Normalize it so the rest of your app sees one field. ::: ## Connector icons Connector icons are static SVGs at a public, no-auth, CORS-enabled endpoint keyed by the same `typeId` you pass to `createConnectorFrame`: ```text GET https://app.monad.com/external/icons/raw/{typeId}.svg ``` Render it in an `` and fall back to your own placeholder on a `404`: ```tsx function ConnectorIcon({ typeId, label }: { typeId: string; label: string }) { const [failed, setFailed] = useState(false); if (failed) return ; return ( {label} setFailed(true)} // fires on 404 / unmapped typeId /> ); } ``` Notes: - **Responses are immutable per `typeId`** and carry a 7-day `Cache-Control`, so the browser and any CDN cache them automatically — no need to bust the URL. - **The icon is the vendor's, not the connector's.** Many `typeId`s share one logo (every AWS service resolves to the AWS icon). If you need to tell two connectors of the same vendor apart, use the display name alongside the logo. - **Always handle `404`** — new or custom connectors may not have a dedicated logo yet. The full endpoint reference, including the JSON mapping-lookup companion endpoint, is in [`docs/connector-icons.md`](https://github.com/monad-inc/embed/blob/main/docs/connector-icons.md) in the `@monad-inc/embed` repo. ## Security model - **Cross-origin iframe.** The form runs on `app.monad.com`, not on your domain. The browser's same-origin policy means your JavaScript cannot read the iframe's DOM or any value the user types. - **Session tokens are short-lived.** Default 30 min, scoped to a single team. Compromise of a session token is bounded; compromise of the long-lived API key is not — keep it on your backend. - **`postMessage` with strict origin checks.** Every message between your page and the iframe is validated against the expected origin in both directions. - **`SameSite=Lax` cookies.** Any cookies you set on your own domain do not travel into the Monad iframe. - **No host JavaScript in the iframe.** You cannot inject script or CSS; the only customization channel is the six `appearance` tokens (and `stylesheets`). ## Appendix A — backend route contract The endpoints your backend exposes to your frontend. Paths are your choice; the shapes and the Monad call behind each are what matter. | Method and path | Body / query | Monad call behind it | Returns | | --- | --- | --- | --- | | `GET /api/monad/config` | (none) | static | `{ frameOrigin, apiBase }` | | `POST /api/session` | `{ tenantId }` | `POST /v3/sessions` | `{ session_token, expires_at, organizationId }` | | `GET /api/catalog` | `?kind=input\|output` | `GET /v1/{kind}s` | `CatalogType[]` | | `GET /api/connectors` | `?kind=&tenantId=` | `GET /v1/{org}/{kind}s` | `ConfiguredConnector[]` | | `POST /api/build-pipeline` | `{ tenantId, inputId, inputName }` | `buildDevNullPipeline` or `POST /v2/{org}/pipelines/` | `BuiltPipeline` | | `POST /api/integration-action` | `{ tenantId, action, inputId }` | `findIntegrationPipeline`, then `setIntegrationEnabled` or `deleteIntegration` | status or result | Add `POST /api/team` (`{ name }` → `POST /v3/{yourOrgId}/organizations`, returns `{ id }`) if you provision teams programmatically. ## Appendix B — what you import vs. what you build | Concern | Ships in `@monad-inc/embed` | You write | | --- | --- | --- | | Mount the iframe | `createConnectorFrame` | the container and chrome | | Authenticated requests | `MonadRequest` type | the thunk (`monadRequest`) | | Session mint | (none) | `POST /v3/sessions` endpoint | | Catalog reads | (none) | `GET /v1/...` wrappers | | Zero-setup pipeline | `buildDevNullPipeline` | (none) | | Real input-to-output pipeline | (none) | `POST /v2/{org}/pipelines/` | | Status, pause, resume | `findIntegrationPipeline`, `setIntegrationEnabled` | thin route wrappers | | Delete and cleanup | `deleteIntegration`, `CLEANUP_*` | resolve-then-act route | | Tenant-to-team mapping | (none) | your server-side record | ## Related - [`@monad-inc/embed` on npm](https://www.npmjs.com/package/@monad-inc/embed) - [`monad-inc/embed` on GitHub](https://github.com/monad-inc/embed) — the SDK source, `USAGE.md`, and the connector-icons guide. ## Support For additional support contact support@monad.com