MisarMisar Docs
MisarMailMisar.BlogMisarReachMisarPostMisar.DevMisarSEOMisar PlatformMisar SSO
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
  }
}