Skip to main content

SDK Reference

The @facilio/vibe-sdk is the browser-side library that handles auth and data access for Vibe apps.

Install#

Bundler (Vite / webpack / Next.js / esbuild / Astro / …)#

npm install @facilio/vibe-sdk
import { createVibe } from '@facilio/vibe-sdk';
const vibe = createVibe();   // serverURL defaults to window.location.origin

Because every deployed Vibe app is served from https://<linkName>.vibe.facilio.com, the SDK talks to the same origin and cookies flow automatically — no serverURL override needed.

Plain HTML (no bundler)#

Load from CDN — no npm install required:

<script src="https://unpkg.com/@facilio/vibe-sdk"></script><script>  const vibe = VibeSDK.createVibe();</script>

createVibe(options?)#

Create the SDK client.

const vibe = createVibe({ serverURL: window.location.origin });
OptionDefaultNotes
serverURLwindow.location.originOverride only if you're testing against a different host.

Returns a Vibe instance with the methods below.


Auth#

getCurrentUser()#

The single source of truth for "is the user signed in?".

const me = await vibe.getCurrentUser();

Returns (signed in):

{  "user": {    "uid": 1,    "email": "xyz@facilio.com",    "name": "xxxxx",    "username": "xyz"  },  "org": {    "orgId": 1  }}

Returns null when not signed in (the underlying /api/runtime/getCurrentUser returned 401).

Access fields under the nested shapeme.user.email, me.user.name, me.user.uid, me.user.username, me.org.orgId. There is no me.email at the top level.

isAuthenticated()#

Boolean check.

const ok = await vibe.isAuthenticated();

login()#

Redirect the browser to identity-service. Synchronous in effect — nothing after this line runs because the browser navigates away.

vibe.login();

Use this only when getCurrentUser() returned null. Do not wire it into the catch block of every action call — a 401 from executeAction is just an error.

logout()#

Sign out the current session.

vibe.logout();

Recommended bootstrap pattern#

Run on app mount. This is the canonical way to gate an app behind auth:

const me = await vibe.getCurrentUser();if (!me) {  vibe.login();   // browser navigates away; nothing below runs  return;}// ...render authenticated UI using me.user.email, me.org.orgId, etc.

Or, if you prefer an explicit "Log in" button:

const me = await vibe.getCurrentUser();if (!me) {  // render <button onClick={() => vibe.login()}>Log in</button>  return;}

Either pattern is fine — just never leave a null user case unhandled.


Data — executeAction#

The only sanctioned way to access Facilio data from a Vibe app.

const result = await vibe.executeAction(connectionSlug, actionSlug, payload);
ArgumentNotes
connectionSlugIdentifies which Facilio product/connector to talk to (e.g. facilio-cmms).
actionSlugIdentifies the specific operation (e.g. list-assets, create-workorder).
payloadJSON object with the action's inputs. Defaults to {} if the action takes none.

Returns the parsed JSON response. The shape is action-specific — the SDK does not normalize it. A typical action returns { response: { data: [...] } }, but always confirm by inspecting the action's schema in the MCP catalog.

Where do connectionSlug, actionSlug, and payload come from?#

Not from your imagination — from the Facilio MCP server:

https://mcp.facilio.com/mcp

This is the source of truth. It exposes every available connection, every action, the input schema (so you know exactly what payload keys to send), and the response shape. AI agents (Claude, GPT, any MCP-aware client) connect to it and discover the catalog at runtime.

Workflow when you need to call data:

  1. Query the MCP server to discover the right connectionSlug and actionSlug for what the user wants.
  2. Read the action's input schema; build the payload to match.
  3. Call vibe.executeAction(connectionSlug, actionSlug, payload).
  4. Read the action's response schema; parse the result accordingly.

Do not hardcode action lists from documentation — they evolve. Re-discover via MCP each time you add new functionality.

Reference call#

const result = await vibe.executeAction('facilio-cmms', 'list-assets');const { response } = result;const assets = response?.data ?? [];

With a payload#

const { response } = await vibe.executeAction(  'facilio-cmms',  'create-workorder',  {    subject: 'Replace HVAC filter',    siteId: 123,    dueDate: new Date('2026-07-01').getTime(),  // milliseconds since epoch  });

Raw HTTP — fetch(path, init?)#

Escape hatch for endpoints that aren't exposed as actions. A thin wrapper around fetch() that:

  • Attaches credentials: 'include' so the session cookie flows.
  • Redirects to login() automatically on 401.
const res = await vibe.fetch('/api/runtime/...');const json = await res.json();

Prefer executeAction whenever possible — it's the supported, schema-discoverable surface.


Error handling#

All SDK methods throw VibeError. The error has:

  • .message — human-readable string.
  • .status? — HTTP status if available.
try {  const result = await vibe.executeAction('facilio-cmms', 'list-assets');  // ...use result} catch (err) {  showError(err.message);   // do NOT call vibe.login() here  console.error('status:', err.status);}

A 401 from executeAction is not a signal to call vibe.login(). The login redirect belongs only on the getCurrentUser() path. If executeAction returns 401, surface the message — the session was likely revoked, and the next mount cycle will trigger the login flow through getCurrentUser().


Method index#

MethodPurpose
createVibe(options?)Create the SDK client.
getCurrentUser()Returns { user, org } or null. The single source of truth for "signed in?".
isAuthenticated()Boolean check.
login()Redirect to identity-service. Use only when getCurrentUser() returns null.
logout()Sign out the current session.
executeAction(connectionSlug, actionSlug, payload)The only sanctioned way to call Facilio data. Slugs come from the MCP catalog.
fetch(path, init?)Raw HTTP escape hatch with credentials: 'include' and auto-redirect on 401.

End-to-end example#

import { useEffect, useState } from 'react';import { createVibe } from '@facilio/vibe-sdk';
const vibe = createVibe();
export default function App() {  const [me, setMe] = useState(null);  const [assets, setAssets] = useState([]);  const [error, setError] = useState(null);
  useEffect(() => {    (async () => {      const user = await vibe.getCurrentUser();      if (!user) {        vibe.login();        return;      }      setMe(user);      try {        const { response } = await vibe.executeAction('facilio-cmms', 'list-assets');        setAssets(response?.data ?? []);      } catch (err) {        setError(err.message);      }    })();  }, []);
  if (error) return <p>{error}</p>;  if (!me) return <p>Loading…</p>;
  return (    <main>      <h1>Hello, {me.user.name}</h1>      <p>Org: {me.org.orgId}</p>      <button onClick={() => vibe.logout()}>Log out</button>      <h2>Assets ({assets.length})</h2>      <ul>        {assets.map(a => <li key={a.id}>{a.name}</li>)}      </ul>    </main>  );}

See Getting Started for the full project setup and Building with AI Agents for how to hand this off to an AI agent.