Workspaces
TypeScript SDK
Use @misar/workspace to call the Workspaces API from any Misar product server.
Installation
The SDK is a workspace package — no npm install needed inside the monorepo.
{
"dependencies": {
"@misar/workspace": "workspace:*"
}
}Never import @misar/workspace inside non-misar-io repos (MisarMail, MisarReach, etc.). Use the REST API directly from those products — the service key and base URL are sufficient.
Setup
import { createWorkspaceClient } from "@misar/workspace";
const workspaces = createWorkspaceClient({
baseUrl: "https://api.misar.io/io/workspaces",
serviceKey: process.env.WORKSPACE_SERVICE_KEY,
});Prop
Type
Types
import type {
Workspace,
WorkspaceMember,
WorkspaceRole,
WorkspaceMemberStatus,
AccessResult,
} from "@misar/workspace";
type WorkspaceRole = "owner" | "admin" | "member";
type WorkspaceMemberStatus = "active" | "invited" | "removed";
interface Workspace {
id: string;
name: string;
slug: string | null;
owner_id: string;
created_at: string;
updated_at: string;
}
interface WorkspaceMember {
id: string;
workspace_id: string;
user_id: string | null; // null for a pending invite
invited_email: string | null;
role: WorkspaceRole;
status: WorkspaceMemberStatus;
invited_by: string | null;
created_at: string;
}
interface AccessResult {
allowed: boolean;
role: WorkspaceRole | null;
}Methods
Every method takes the acting userId as its first argument — it is sent as the user_id query param on every request.
// List the workspaces a user owns or is an active member of
const list: Workspace[] = await workspaces.getWorkspaces(userId);
// Create a workspace (the user becomes owner)
const created: Workspace = await workspaces.createWorkspace(userId, "Acme Agency");
// Get one workspace + the user's role in it (member+)
const { workspace, role } = await workspaces.getWorkspace(userId, wsId);
// Rename a workspace (admin+)
const renamed: Workspace = await workspaces.updateWorkspace(userId, wsId, { name: "Acme Studios" });
// Delete a workspace (owner only)
await workspaces.deleteWorkspace(userId, wsId);
// List members (member+)
const { workspace: ws, members } = await workspaces.listMembers(userId, wsId);
// Invite / add a member by email (admin+); role defaults to "member"
const member: WorkspaceMember = await workspaces.inviteMember(userId, wsId, "teammate@example.com", "admin");
// Soft-remove a member by membership id (admin+; owner protected)
await workspaces.removeMember(userId, wsId, memberId);
// Gate access — the check products call before serving workspace data
const { allowed, role: accessRole } = await workspaces.checkAccess(userId, wsId);Signatures
Prop
Type
Error handling
Failed requests throw a WorkspaceError carrying the HTTP status and the API's error message.
import { WorkspaceError } from "@misar/workspace";
try {
await workspaces.deleteWorkspace(userId, wsId);
} catch (err) {
if (err instanceof WorkspaceError) {
console.error(err.status, err.message);
// err.status === 403 → caller is not the owner
}
}