npm package: @gravity-rail/sdk
Description: Gravity Rail TypeScript SDK — API client for workspace management
Latest version: 0.2.0

# @gravity-rail/sdk

TypeScript SDK for [Gravity Rail](https://gravityrail.com) — the AI-native operating system for organizations that communicate with people at scale.

Build AI assistants that handle voice calls, SMS, web chat, email, Discord, and Slack — all backed by configurable workflows, structured data collection, and real-time streaming. One SDK, every channel.

## Installation

```sh
npm install @gravity-rail/sdk
# or
yarn add @gravity-rail/sdk
# or
pnpm add @gravity-rail/sdk
```

Zod schemas are available as an optional peer dependency:

```sh
npm install zod  # optional, for runtime validation
```

## Quick Start

```typescript
import { GravityRailClient } from '@gravity-rail/sdk';

const client = new GravityRailClient(
  process.env.GRAVITY_RAIL_API_KEY,
  'https://api.gravityrail.com'
);

// List all workflows in a workspace
const workflows = await client.getWorkflows(workspaceId);

// Get active chats across every channel
const chats = await client.getChats(workspaceId);

// Create a new member
const member = await client.createWorkspaceMember(workspaceId, {
  first_name: 'Jane',
  last_name: 'Doe',
  email: 'jane@example.com',
  role_id: roleId,
});
```

## Authentication

### API Key

Scoped API keys are the simplest way to authenticate. Create one from workspace settings or via the SDK:

```typescript
const client = new GravityRailClient(
  'your-api-key',
  'https://api.gravityrail.com'
);
```

Keys can be scoped to specific permissions (read-only, workspace-limited, time-expiring) using the [granular scope system](#scopes--permissions).

### OAuth2 with PKCE

For browser-based applications:

```typescript
const client = new GravityRailClient(undefined, 'https://api.gravityrail.com');

// Handle step-up authentication when the API requires it
client.setEnhancedAuthHandler(async (authInfo) => {
  // Redirect to login or show auth modal
});
```

### Member Identity Switching

Act on behalf of a specific workspace member:

```typescript
client.setActingMember(memberUuid);
// All subsequent requests use this member's identity
const myChats = await client.getChats(workspaceId);
client.setActingMember(undefined); // reset
```

## Core Concepts

Every Gravity Rail workspace is a self-contained environment with isolated data, workflows, and configuration. The SDK organizes its 500+ methods by domain:

| Domain | What it covers |
|---|---|
| **Workflows** | Multi-step conversational processes with branching logic, task assignment, and templates |
| **Assistants** | AI personas with configurable models, voices, and a two-tier supervisor system |
| **Agents** | Autonomous AI workspace members with their own identity, config, and multi-channel presence |
| **Chats** | Conversations across all channels — labels, filters, summaries, message history, and export |
| **Members** | Contacts and team — roles, labels, filters, custom fields, import/export, anonymous resolution |
| **Data Types** | Schema-driven forms (14 field types) with computed fields and conversational collection |
| **Events** | Trigger-based automation with [CEL expressions](https://github.com/google/cel-spec) |
| **Calendars** | Scheduling, availability, event types, Google Calendar sync, and iCal feeds |
| **Files** | Folder hierarchy with semantic search, role-based sharing, and public access |
| **Sites** | Customer-facing portals with custom domains, page builder, and web crawling |
| **Communications** | Phone numbers, SMS, email inboxes, and notification rules |
| **Toolkits** | Custom tools, MCP server integrations, and AI model configuration |
| **Operator Groups** | Live human routing with presence tracking and configurable strategies |
| **Qualifications** | Skills evaluation with expression-based and rubric-based scoring |
| **Billing** | API keys, subscriptions, and usage reports (AI, voice, SMS, storage) |
| **Integrations** | Discord, Slack, Monday.com, FHIR, and OAuth app connections |

## Usage Examples

### Workflows & Assistants

```typescript
// Create a multi-step workflow
const workflow = await client.createWorkflow(workspaceId, {
  name: 'Customer Onboarding',
  description: 'Guide new customers through setup',
});

// Create an AI assistant
const assistant = await client.createAssistant(workspaceId, {
  name: 'Onboarding Guide',
  model: 'claude-sonnet-4-20250514',
  bio: 'A friendly assistant that helps new customers get started.',
});

// Add a supervisor for quality assurance
const supervisor = await client.createSupervisor(workspaceId, {
  name: 'QA Reviewer',
  model: 'claude-sonnet-4-20250514',
  instructions: 'Review assistant responses for accuracy and tone.',
});

// Build from templates
const templates = await client.getWorkflowTemplates(workspaceId);
await client.createWorkflowFromTemplate(workspaceId, {
  template_id: templates[0].id,
});
```

### Chat Operations

```typescript
// Get conversations across all channels
const chats = await client.getChats(workspaceId);

// Full message history with tool calls
const messages = await client.getChatMessages(workspaceId, chatId);
const toolCalls = await client.getChatToolCallMessages(workspaceId, chatId);

// Trigger an AI response
await client.sendAssistantMessage(workspaceId, chatId);

// Direct messaging between members
const dm = await client.findOrCreateDMChat(workspaceId, { member_id: targetMemberId });
await client.sendChatMessage(workspaceId, dm.id, { content: 'Hey!' });

// Export for analysis
const exported = await client.exportChat(workspaceId, chatId);

// Organize with labels and filters
await client.createChatLabel(workspaceId, { name: 'VIP', color: '#FFD700' });
await client.createChatFilter(workspaceId, { name: 'Unresolved', conditions: { needs_response: true } });
```

### Structured Data Collection

```typescript
// Define a schema — AI assistants collect this conversationally
const dataType = await client.createDataType(workspaceId, {
  name: 'Contact Form',
  slug: 'contact-form',
  is_collection: true,
  fields: [
    { name: 'Full Name', field_type: 'text', required: true },
    { name: 'Email', field_type: 'email', required: true },
    { name: 'Priority', field_type: 'dropdown', options: ['Low', 'Medium', 'High'] },
    { name: 'Score', field_type: 'formula', formula: 'Priority == "High" ? 100 : 50' },
  ],
});

// Or create records programmatically
const record = await client.createDataRecord(workspaceId, dataType.id, {
  field_values: { 'Full Name': 'Alice Chen', 'Email': 'alice@example.com', 'Priority': 'High' },
});

// Query and upsert
const records = await client.getDataRecords(workspaceId, dataType.id);
await client.upsertDataRecord(workspaceId, dataType.id, {
  match_field: 'Email',
  field_values: { 'Email': 'alice@example.com', 'Priority': 'Medium' },
});
```

### Communication Channels

```typescript
// Phone — initiate an outbound AI voice call
const numbers = await client.getPhoneNumbers(workspaceId);
await client.initiateCall(workspaceId, {
  phone_number_id: numbers[0].id,
  to_number: '+15551234567',
  workflow_id: workflowId,
});

// Email — manage inboxes and threads
const inboxes = await client.getInboxes(workspaceId);
const threads = await client.getInboxThreads(workspaceId, inboxes[0].id);
const emails = await client.getThreadEmails(workspaceId, inboxes[0].id, threadId);

// Notifications
await client.createNotificationRule(workspaceId, {
  name: 'New chat alert',
  event_type: 'chat.created',
  channel: 'email',
});
```

### Toolkits & MCP Servers

```typescript
// Connect an MCP server for custom AI tool capabilities
const server = await client.createMcpServer(workspaceId, {
  name: 'Internal Tools',
  url: 'https://tools.example.com/mcp',
});
await client.testMcpServerConnection(workspaceId, server.id);

// Discover tools, resources, and prompts
const tools = await client.getMcpServerTools(workspaceId, server.id);
const resources = await client.getMcpServerResources(workspaceId, server.id);

// Or build custom tools directly
await client.createCustomTool(workspaceId, toolkitId, {
  name: 'lookup_order',
  description: 'Look up an order by ID',
  input_schema: {
    type: 'object',
    properties: { order_id: { type: 'string' } },
    required: ['order_id'],
  },
});
```

### Calendar & Scheduling

```typescript
const calendar = await client.createCalendar(workspaceId, { name: 'Appointments' });

// Check availability and book
const slots = await client.getAvailableSlots(workspaceId, calendar.id, {
  start_date: '2025-03-01',
  end_date: '2025-03-07',
  duration_minutes: 30,
});

await client.createCalendarEvent(workspaceId, calendar.id, {
  title: 'Consultation',
  start_time: slots[0].start,
  end_time: slots[0].end,
  attendees: [{ member_id: memberId }],
});

// Sync with Google Calendar
await client.linkCalendarToGoogle(workspaceId, calendar.id, {
  google_calendar_id: 'primary',
});
```

### Event Automation

```typescript
// Trigger-based automation with CEL conditions
await client.createEventRule(workspaceId, {
  name: 'VIP Follow-up',
  trigger: 'task.exited',
  condition: '"vip" in member.labels',
  actions: [{
    type: 'send_ai_message',
    delay_minutes: 60,
    config: { message: 'Thank you for your time today.' },
  }],
});

// Scheduled events (CRON)
const event = await client.createEvent(workspaceId, {
  name: 'Daily Check-in',
  schedule: '0 9 * * *',
  target_filter: { labels: ['active'] },
});

// Trigger manually
await client.runEvent(workspaceId, event.id);
```

### Operator Groups & Live Handoff

```typescript
// Route conversations to live human operators
const group = await client.createOperatorGroup(workspaceId, {
  name: 'Support Team',
  routing_strategy: 'round_robin',
  timeout_seconds: 30, // falls back to AI if no one accepts
});

await client.addGroupMember(workspaceId, group.id, { member_id: agentMemberId });
const operators = await client.getLiveOperators(workspaceId);
```

### Sites & Portals

```typescript
// Build customer-facing portals with AI chat built in
const site = await client.createSite(workspaceId, {
  name: 'Help Center',
  slug: 'help',
  domain: 'help.example.com',
});

await client.createPage(workspaceId, site.id, {
  title: 'Getting Started',
  slug: 'getting-started',
  content: '# Welcome\nHere is how to get started...',
});

// Import existing documentation automatically
await client.crawlSite(workspaceId, site.id, { url: 'https://docs.example.com' });
```

### Workspace Management

```typescript
// Export/import full workspace configuration
const config = await client.exportWorkspace(workspaceId);
const preview = await client.previewWorkspaceImport(targetId, config);
await client.importWorkspace(targetId, config);

// White-label: provision client workspaces
const clientWs = await client.createClientWorkspace(workspaceId, {
  name: 'Acme Corp',
  product_id: productId,
});
await client.provisionClientWorkspace(workspaceId, clientWs.id);
```

## Type System

Full TypeScript types for every API entity:

```typescript
import type {
  Workspace, Member, Chat, Task, Workflow, Assistant,
  DataType, DataRecord, EventRule, Calendar, Site,
  PhoneNumber, Inbox, OperatorGroup, Qualification,
  Subscription, ApiKey, Agent, MemberRole,
} from '@gravity-rail/sdk';
```

### Zod Schemas

Runtime validation schemas via a separate import (requires `zod`):

```typescript
import { taskSchema, memberSchema, workflowSchema } from '@gravity-rail/sdk/schemas';

const task = taskSchema.parse(apiResponse);

const result = memberSchema.safeParse(formData);
if (!result.success) {
  console.error(result.error.flatten());
}
```

## Scopes & Permissions

The SDK includes the complete scope system for building OAuth apps and managing API key permissions:

```typescript
import { SCOPES, ScopeCategory, ScopeManager, SCOPE_PRESETS } from '@gravity-rail/sdk';

// Browse available scopes by category
const chatScopes = Object.values(SCOPES).filter(
  (s) => s.category === ScopeCategory.CHATS
);
```

22 scope categories covering every domain: workspace, members, chats, DMs, assistants, workflows, assignments, automations, data types, records, files, sites, agents, calendars, inboxes, phones, webhooks, apps, labels, analytics, operator, and org.

## Error Handling

```typescript
import { GravityRailClient, ApiError } from '@gravity-rail/sdk';

try {
  const task = await client.getTask(workspaceId, taskId);
} catch (error) {
  if (error instanceof ApiError) {
    console.error(`${error.status}: ${error.message}`);
    // 403 → check API key scopes
    // 404 → verify workspace and entity IDs
    // 429 → rate limited, back off
  }
}
```

## Compliance

Gravity Rail is built for HIPAA compliance. The SDK enforces:

- **Data isolation** — every workspace has a dedicated database schema
- **Scoped access** — API keys enforce granular permissions at the scope level
- **Feature flags** — workspaces can enable `HIPAA_COMPLIANCE` for stricter data handling
- **Audit trails** — all operations are logged for compliance reporting

## Related

- [`@gravity-rail/cli`](https://www.npmjs.com/package/@gravity-rail/cli) — Command-line interface for interactive workspace management
- [Developer Docs](https://developer.gravityrail.com) — Full API reference and guides

## License

MIT