Skip to content

App Registration

Consumer apps (like Socialite, VideoMaker, etc.) register with Fabric as Apps — first-class citizens that get their own client credentials, white-label auth, and app-scoped tenancy.

Terminal window
cargo run -- setup \
--app-name "My App" \
--email "dev@myapp.com" \
--password "SecureP@ss1"

Output:

Fabric setup complete.
App: My App (my-app)
Admin: dev@myapp.com
Organization: My App (swift-fox-742)
Organization ID: 5fe20183-...
Add to your consumer app .env:
FABRIC_API_URL=http://localhost:3001
FABRIC_CLIENT_ID=foc_abc123...
FABRIC_CLIENT_SECRET=focs_xyz789...
FABRIC_WEBHOOK_SECRET=whsec_a1b2c3d4...
API Key (for direct access): fab_def456...
Terminal window
export FABRIC_API_URL=http://localhost:3001
export FABRIC_CLIENT_ID=foc_abc123...
export FABRIC_CLIENT_SECRET=focs_xyz789...
export FABRIC_WEBHOOK_SECRET=whsec_a1b2c3d4...
import { FabricClient } from "@fabric-platform/sdk";
const fabric = new FabricClient({
baseUrl: process.env.FABRIC_API_URL,
app: {
clientId: process.env.FABRIC_CLIENT_ID!,
clientSecret: process.env.FABRIC_CLIENT_SECRET!,
},
});

Users sign up and log in through your app’s own UI. Fabric is invisible to them.

// Your signup handler
app.post("/signup", async (req, res) => {
const { email, password } = req.body;
// Fabric creates the user + personal org scoped to your app
const auth = await fabric.auth.signup(email, password);
// Store the tokens in your session/cookies
res.cookie("access_token", auth.access_token);
res.json({ user: auth.user });
});
// Your login handler
app.post("/login", async (req, res) => {
const auth = await fabric.auth.login(req.body.email, req.body.password);
res.cookie("access_token", auth.access_token);
res.json({ user: auth.user });
});

Your server needs to submit workflows, manage resources, etc. for specific users. Use token exchange to get a user-scoped client.

// Get a user-scoped client via token exchange
const userFabric = await fabric.asUser(userId);
// Everything is now scoped to this user's org
await userFabric.workflows.runs.submit("video/ai_shorts", {
input: { topic: "AI trends" },
});
const orgs = await userFabric.organizations.list(); // Only this app's orgs

Token exchange happens internally — the SDK caches user tokens and auto-refreshes them.

Register a webhook to receive push notifications when workflows complete, fail, or reach other terminal states. Your app should self-register on startup using the webhook secret from fabric setup:

// On app startup — register webhook if not already present
const webhooks = await fabric.webhooks.list(orgId);
const exists = webhooks.items?.some(w => w.url.includes("/api/webhooks/fabric"));
if (!exists) {
const result = await fabric.webhooks.create(orgId, {
url: `${process.env.PUBLIC_URL}/api/webhooks/fabric`,
event_filter: ["workflow.run.completed", "workflow.run.failed"],
});
// result.secret is the signing secret (whsec_...) — returned once.
// For local dev, fabric setup already provided it as FABRIC_WEBHOOK_SECRET.
}

See the Webhooks Reference for signature verification, delivery semantics, and the full event catalog.

Each app’s data is completely isolated:

  • Orgs created through App A are invisible to App B
  • Same org slug is allowed across different apps
  • Users can have accounts in multiple apps (same Fabric identity, separate orgs)
  • Workflows, assets, artifacts are scoped through orgs — automatically isolated per app
// List your apps
const apps = await fabric.apps.list();
// Update settings
await fabric.apps.update(appId, {
auto_create_org: false,
allowed_origins: ["https://myapp.com"],
});
// Rotate client secret (one-time reveal)
const { client_secret } = await fabric.apps.rotateSecret(appId);
// View aggregate usage
const usage = await fabric.apps.usage(appId);
console.log(`${usage.total_runs} runs across ${usage.total_orgs} orgs`);

By default, every new user gets a personal org when they sign up through your app. This org is scoped to your app and the user is the owner.

Disable it if you want users to be invited to existing orgs instead:

await fabric.apps.update(appId, { auto_create_org: false });
Your App (e.g., Socialite)
|-- client_id + client_secret (for server-to-server)
|
|-- User: alice@example.com
| |-- Org: "Alice's Agency" (app-scoped)
| | |-- Team: "Marketing"
| | +-- Team: "Creative"
| +-- Org: "Client Corp" (invited)
|
+-- User: bob@example.com
+-- Org: "Bob's Studio" (app-scoped)

Fabric provides the entire identity + tenancy layer. Your app doesn’t need to implement auth, orgs, teams, invitations, or RBAC.