# 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 (
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