Web component
<svx-integration-catalog> is a custom element. It works in any framework, or none.
Loading it
<script type="module" src="https://embed.work.studio/v1.js"></script>
<svx-integration-catalog
token="svx_st_…"
tenant-id="your-tenant-id"
scope-key="customer:acme"
></svx-integration-catalog>
The element renders a framed catalog and passes your credential to it over postMessage — the token never appears in a URL.
Attributes
Required
Customer
Appearance
Content
Changing height after load
height is read when the element mounts. Setting it later won't re-trigger sizing — set it in your markup.
Methods
const el = document.querySelector('svx-integration-catalog');
el.connect('GitHub'); // open the connect dialog for one app
el.openConnection(connectorId); // same, by connector id
el.openIntegration('slack-alerts');// open one integration's setup flow
el.showCatalog(); // return to the full catalog
el.refresh(); // reload catalog and connection status
el.setTheme({ primaryColor: '#111827' });
connect() accepts an app name or a connector id. If the app isn't one you offer, the element raises svx:connect:not-found rather than failing silently.
Events
Every event bubbles and carries a detail object.
automation:created carries template when the customer added one of your templates and changed: true when they edited an existing automation. recovered: true means the connection dropped while the automation was being built, and the element found it in the customer's list afterwards.
Customer feedback
The customer can rate each automation the Automate tab builds, and each Assistant reply, with a thumbs up or down. After a thumbs-down they can say what went wrong. svx:feedback:sent fires for each rating: surface is AUTOMATION or ASSISTANT_REPLY, rating is 1 or -1, and commented says whether they wrote something. The comment text itself is not in the event.
The ratings are stored for you. Read them under What your customers said in Designer's Embed settings.
el.addEventListener('svx:connection:completed', (e) => {
analytics.track('integration_connected', { app: e.detail.name });
});
Framework notes
import { useEffect, useRef } from 'react';
export function Catalog({ token, tenantId, scopeKey }) {
const ref = useRef(null);
useEffect(() => {
const el = ref.current;
const onConnected = (e) => console.log(e.detail);
el.addEventListener('svx:connection:completed', onConnected);
return () => el.removeEventListener('svx:connection:completed', onConnected);
}, []);
return (
<svx-integration-catalog
ref={ref}
token={token}
tenant-id={tenantId}
scope-key={scopeKey}
/>
);
}
<template>
<svx-integration-catalog
:token="token"
:tenant-id="tenantId"
:scope-key="scopeKey"
@svx:connection:completed="onConnected"
/>
</template>
<svx-integration-catalog id="catalog" token="…" tenant-id="…" scope-key="customer:acme">
</svx-integration-catalog>
<script>
document.getElementById('catalog')
.addEventListener('svx:connection:completed', (e) => console.log(e.detail));
</script>
In React, mark the tag as a custom element in your JSX types, or render it through a small wrapper as above.
Next steps
- Authentication — minting tokens and setting the origin allowlist
- SDK — building your own interface instead
Something not behaving as described? support@work.studio