---
title: JavaScript SDK
description: Official JavaScript/TypeScript SDK for TraceRTM API integration
keywords: [javascript, typescript, sdk, api, client, npm, yarn, pnpm]
audience: developer
difficulty: intermediate
---

import { Callout } from 'fumadocs-ui/components/callout';
import { Steps, Step } from 'fumadocs-ui/components/steps';
import { Tabs, Tab } from 'fumadocs-ui/components/tabs';

# JavaScript SDK

The official JavaScript/TypeScript SDK for TraceRTM provides a modern, type-safe interface to the REST API. Built with full TypeScript support, async/await patterns, and comprehensive error handling.

## Installation

<Tabs items={['npm', 'yarn', 'pnpm']}>
  <Tab value="npm">
    ```bash
    npm install @tracertm/sdk
    ```
  </Tab>

  <Tab value="yarn">
    ```bash
    yarn add @tracertm/sdk
    ```
  </Tab>

  <Tab value="pnpm">
    ```bash
    pnpm add @tracertm/sdk
    ```
  </Tab>
</Tabs>

**Requirements**:
- Node.js 16+ or modern browser
- TypeScript 4.5+ (for TypeScript projects)

## Quick Start

<Steps>
  <Step>
    ### Initialize client

    ```typescript
    import { TraceRTMClient } from '@tracertm/sdk';

    // Using API key
    const client = new TraceRTMClient({
      apiKey: 'your-api-key-here'
    });

    // Or using environment variable
    const client = new TraceRTMClient({
      apiKey: process.env.TRACERTM_API_KEY
    });

    // With custom base URL (self-hosted)
    const client = new TraceRTMClient({
      apiKey: 'your-api-key',
      baseUrl: 'https://tracertm.yourcompany.com/api/v1'
    });
    ```

    <Callout type="tip">
    Store your API key in environment variables, never in code!
    </Callout>
  </Step>

  <Step>
    ### Create a project

    ```typescript
    const project = await client.projects.create({
      name: 'My Project',
      key: 'MYPROJ',
      description: 'Requirements tracking for my project'
    });

    console.log(`Created project: ${project.id}`);
    // Output: Created project: proj-abc123
    ```
  </Step>

  <Step>
    ### Create items

    ```typescript
    // Business requirement
    const br = await client.items.create({
      project_id: project.id,
      type: 'BR',
      title: 'Increase user engagement',
      description: 'Platform shall increase DAU by 20%',
      priority: 'MUST'
    });

    // Functional requirement
    const fr = await client.items.create({
      project_id: project.id,
      type: 'FR',
      title: 'Recommendation engine',
      description: 'System shall provide personalized recommendations',
      priority: 'MUST',
      custom_fields: {
        component: 'Engine',
        sprint: 5
      }
    });

    console.log(`Created: ${br.id}, ${fr.id}`);
    ```
  </Step>

  <Step>
    ### Create traceability link

    ```typescript
    const link = await client.links.create({
      source_id: fr.id,
      target_id: br.id,
      link_type: 'satisfies'
    });

    console.log(`Linked ${fr.id} -> ${br.id}`);
    ```
  </Step>

  <Step>
    ### Query traceability graph

    ```typescript
    // Get descendants (what depends on this item)
    const descendants = await client.graph.getDescendants(br.id, 3);

    console.log(`Impact: ${descendants.nodes.length} items`);

    // Get ancestors (what this item depends on)
    const ancestors = await client.graph.getAncestors(fr.id, 2);

    console.log(`Dependencies: ${ancestors.nodes.length} items`);
    ```
  </Step>
</Steps>

## TypeScript Support

The SDK is written in TypeScript and provides full type definitions out of the box.

### Type-safe API calls

```typescript
import type { Project, Item, Link } from '@tracertm/sdk';

// Compiler ensures correct types
const project: Project = await client.projects.create({
  name: 'My Project',
  key: 'PROJ',
  // TypeScript will error if required fields are missing
});

// Auto-complete and type checking
const items: Item[] = await client.items.list({
  project_id: project.id,
  type: 'FR', // Type-checked against valid item types
});

// Typed responses
const link: Link = await client.links.create({
  source_id: items[0].id,
  target_id: items[1].id,
  link_type: 'satisfies'
});
```

### Custom types

```typescript
import type { CreateItemInput, UpdateItemInput } from '@tracertm/sdk';

// Type your functions
async function createRequirement(
  data: CreateItemInput
): Promise<Item> {
  return client.items.create(data);
}

// Use partial types for updates
async function updateRequirement(
  id: string,
  updates: UpdateItemInput
): Promise<Item> {
  return client.items.update(id, updates);
}
```

## Client Initialization

### Basic configuration

```typescript
import { TraceRTMClient } from '@tracertm/sdk';

const client = new TraceRTMClient({
  apiKey: 'your-api-key',
  baseUrl: 'https://api.tracertm.io/v1',
  timeout: 30000, // 30 seconds
});
```

### Advanced configuration

```typescript
const client = new TraceRTMClient({
  apiKey: process.env.TRACERTM_API_KEY,
  baseUrl: process.env.TRACERTM_API_URL,

  // Request timeout (milliseconds)
  timeout: 30000,

  // Automatic retry on failure
  retry: {
    enabled: true,
    maxRetries: 3,
    retryDelay: 1000, // ms
    retryOnStatus: [408, 429, 500, 502, 503, 504]
  },

  // Custom headers
  headers: {
    'X-Custom-Header': 'value'
  },

  // Request/response interceptors
  interceptors: {
    request: (config) => {
      console.log('Request:', config.url);
      return config;
    },
    response: (response) => {
      console.log('Response:', response.status);
      return response;
    }
  }
});
```

### Browser configuration

```typescript
// For browser environments
const client = new TraceRTMClient({
  apiKey: localStorage.getItem('tracertm_api_key'),

  // Handle auth token from storage
  onRequest: (config) => {
    const token = localStorage.getItem('auth_token');
    if (token) {
      config.headers['Authorization'] = `Bearer ${token}`;
    }
    return config;
  },

  // Handle auth errors
  onError: (error) => {
    if (error.status === 401) {
      localStorage.removeItem('auth_token');
      window.location.href = '/login';
    }
    throw error;
  }
});
```

## Working with Projects

### List projects

```typescript
// List all projects
const projects = await client.projects.list();

for (const project of projects) {
  console.log(`${project.key}: ${project.name}`);
}

// With pagination
const projects = await client.projects.list({
  skip: 0,
  limit: 50
});

console.log(`Loaded ${projects.length} projects`);
```

### Get project by ID

```typescript
const project = await client.projects.get('proj-abc123');

console.log(`Project: ${project.name}`);
console.log(`Created: ${project.created_at}`);
console.log(`Items: ${project.item_count}`);
```

### Create project

```typescript
const project = await client.projects.create({
  name: 'My Project',
  key: 'MYPROJ',
  description: 'Project description',
  settings: {
    require_approval: true,
    enable_baselines: true
  },
  metadata: {
    owner: 'team@example.com',
    tags: ['critical', 'v2.0']
  }
});
```

### Update project

```typescript
const updated = await client.projects.update('proj-abc123', {
  description: 'Updated description',
  settings: {
    require_approval: true,
    min_test_coverage: 0.90
  }
});

console.log('Project updated:', updated.name);
```

### Delete project

```typescript
await client.projects.delete('proj-abc123');
```

<Callout type="warn">
Project deletion is **permanent** and deletes all items, links, and baselines!
</Callout>

## Working with Items

### Create item

```typescript
const item = await client.items.create({
  project_id: 'proj-abc123',
  type: 'FR', // FR, BR, NFR, TC, etc.
  title: 'User authentication',
  description: 'System shall authenticate users via email/password',
  priority: 'MUST', // MUST, SHOULD, COULD, WONT
  status: 'draft',

  // Custom fields
  custom_fields: {
    component: 'Auth',
    complexity: 'M',
    story_points: 5,
    sprint: 6
  },

  // Metadata
  metadata: {
    assignee: 'dev@example.com',
    labels: ['security', 'auth']
  }
});

console.log('Created item:', item.id);
```

### List items

```typescript
// All items in a project
const items = await client.items.list({
  project_id: 'proj-abc123'
});

// Filter by type
const requirements = await client.items.list({
  project_id: 'proj-abc123',
  type: 'FR'
});

// Filter by status
const approved = await client.items.list({
  project_id: 'proj-abc123',
  status: 'approved'
});

// Pagination
const page2 = await client.items.list({
  project_id: 'proj-abc123',
  skip: 50,
  limit: 50
});
```

### Get item by ID

```typescript
const item = await client.items.get('item-fr-123');

console.log(`${item.type}-${item.id}: ${item.title}`);
console.log(`Status: ${item.status}`);
console.log(`Priority: ${item.priority}`);
```

### Update item

```typescript
const updated = await client.items.update('item-fr-123', {
  status: 'approved',
  priority: 'MUST',
  custom_fields: {
    sprint: 7,
    complexity: 'H'
  }
});

console.log('Item updated');
```

### Delete item

```typescript
await client.items.delete('item-fr-123');
```

## Working with Links

### Create link

```typescript
const link = await client.links.create({
  source_id: 'item-fr-1',
  target_id: 'item-br-1',
  link_type: 'satisfies', // satisfies, verifies, depends_on, etc.
  rationale: 'FR implements business requirement',
  metadata: {
    strength: 'strong',
    reviewed: true
  }
});

console.log('Link created:', link.id);
```

### List links

```typescript
// All links for an item (both directions)
const links = await client.links.list({
  item_id: 'item-fr-1'
});

// Outgoing links only
const outgoing = await client.links.list({
  source_id: 'item-fr-1'
});

// Incoming links only
const incoming = await client.links.list({
  target_id: 'item-fr-1'
});

// Filter by link type
const satisfiesLinks = await client.links.list({
  source_id: 'item-fr-1',
  link_type: 'satisfies'
});
```

### Update link

```typescript
const updated = await client.links.update('link-abc123', {
  rationale: 'Updated rationale',
  metadata: {
    strength: 'weak'
  }
});
```

### Delete link

```typescript
await client.links.delete('link-abc123');
```

## Bulk Operations

### Bulk create items

```typescript
const items = await client.items.bulkCreate([
  {
    project_id: 'proj-123',
    type: 'FR',
    title: 'Requirement 1',
    priority: 'MUST'
  },
  {
    project_id: 'proj-123',
    type: 'FR',
    title: 'Requirement 2',
    priority: 'SHOULD'
  },
  {
    project_id: 'proj-123',
    type: 'TC',
    title: 'Test Case 1',
    priority: 'MUST'
  }
]);

console.log(`Created ${items.length} items`);
```

### Bulk update items

```typescript
const updated = await client.items.bulkUpdate({
  ids: ['item-1', 'item-2', 'item-3'],
  updates: {
    status: 'approved',
    custom_fields: {
      sprint: 5
    }
  }
});

console.log(`Updated ${updated.length} items`);
```

### Bulk delete items

```typescript
await client.items.bulkDelete(['item-1', 'item-2', 'item-3']);
```

### Bulk create links

```typescript
const links = await client.links.bulkCreate([
  {
    source_id: 'item-fr-1',
    target_id: 'item-br-1',
    link_type: 'satisfies'
  },
  {
    source_id: 'item-fr-2',
    target_id: 'item-br-1',
    link_type: 'satisfies'
  },
  {
    source_id: 'item-tc-1',
    target_id: 'item-fr-1',
    link_type: 'verifies'
  }
]);

console.log(`Created ${links.length} links`);
```

## Search and Queries

### Full-text search

```typescript
const results = await client.search.search({
  query: 'authentication login OAuth',
  project_id: 'proj-abc123',
  types: ['FR', 'BR'],
  limit: 20
});

console.log(`Found ${results.total} results`);

for (const result of results.items) {
  console.log(`${result.id}: ${result.title} (score: ${result.score})`);
}
```

### Search with filters

```typescript
const results = await client.search.search({
  query: 'user management',
  project_id: 'proj-abc123',

  // Filters
  filters: {
    type: ['FR', 'NFR'],
    status: ['approved', 'implemented'],
    priority: ['MUST', 'SHOULD'],
    custom_fields: {
      component: 'Auth'
    }
  },

  // Pagination
  skip: 0,
  limit: 50,

  // Sorting
  sort: {
    field: 'created_at',
    order: 'desc'
  }
});
```

### Autocomplete suggestions

```typescript
const suggestions = await client.search.suggest({
  query: 'auth',
  limit: 10
});

console.log('Suggestions:', suggestions);
// ['authentication', 'authorization', 'auth token', ...]
```

## Graph Operations

### Get ancestors (dependencies)

```typescript
// Get what this item depends on
const ancestors = await client.graph.getAncestors('item-fr-1', 3);

console.log(`Dependencies: ${ancestors.nodes.length} items`);

for (const node of ancestors.nodes) {
  console.log(`  ${node.type} ${node.id}: ${node.title}`);
}

for (const edge of ancestors.edges) {
  console.log(`  ${edge.source} -> ${edge.target} (${edge.link_type})`);
}
```

### Get descendants (impact)

```typescript
// Get what depends on this item
const descendants = await client.graph.getDescendants('item-br-1', 3);

console.log(`Impact: ${descendants.nodes.length} items`);
```

### Find path between items

```typescript
// Shortest path
const path = await client.graph.findPath('item-fr-1', 'item-tc-1');

console.log('Path:', path.map(item => item.id).join(' -> '));

// All paths
const allPaths = await client.graph.findAllPaths('item-br-1', 'item-tc-1');

console.log(`Found ${allPaths.length} paths`);
```

### Get full graph

```typescript
const graph = await client.graph.getFullGraph('proj-abc123');

console.log(`Graph: ${graph.nodes.length} nodes, ${graph.edges.length} edges`);
```

### Detect cycles

```typescript
const cycles = await client.graph.detectCycles('proj-abc123');

if (cycles.length > 0) {
  console.log(`Warning: Found ${cycles.length} cycles`);
  for (const cycle of cycles) {
    console.log(`  Cycle: ${cycle.join(' -> ')}`);
  }
} else {
  console.log('No cycles detected');
}
```

### Impact analysis

```typescript
const impact = await client.graph.getImpactAnalysis('item-br-1', 5);

console.log(`Changing this item affects ${impact.affected_count} items:`);
console.log(`  Direct: ${impact.direct_count}`);
console.log(`  Indirect: ${impact.indirect_count}`);

for (const item of impact.affected_items) {
  console.log(`  ${item.type} ${item.id}: ${item.title} (depth: ${item.depth})`);
}
```

### Dependency analysis

```typescript
const deps = await client.graph.getDependencyAnalysis('item-fr-1', 3);

console.log(`This item depends on ${deps.dependency_count} items`);

for (const item of deps.dependencies) {
  console.log(`  ${item.type} ${item.id}: ${item.title}`);
}
```

### Find orphaned items

```typescript
const orphans = await client.graph.getOrphanItems('proj-abc123');

console.log(`Found ${orphans.length} orphaned items (no links)`);

for (const item of orphans) {
  console.log(`  ${item.type} ${item.id}: ${item.title}`);
}
```

## Async/Await Patterns

### Sequential operations

```typescript
// Operations that depend on each other
async function createProjectWithItems() {
  // Create project first
  const project = await client.projects.create({
    name: 'My Project',
    key: 'PROJ'
  });

  // Then create items
  const br = await client.items.create({
    project_id: project.id,
    type: 'BR',
    title: 'Business Requirement'
  });

  const fr = await client.items.create({
    project_id: project.id,
    type: 'FR',
    title: 'Functional Requirement'
  });

  // Finally create link
  const link = await client.links.create({
    source_id: fr.id,
    target_id: br.id,
    link_type: 'satisfies'
  });

  return { project, br, fr, link };
}
```

### Parallel operations

```typescript
// Operations that can run concurrently
async function createMultipleItems(projectId: string) {
  // Create all items in parallel
  const [br, fr1, fr2, tc1, tc2] = await Promise.all([
    client.items.create({
      project_id: projectId,
      type: 'BR',
      title: 'Business Requirement'
    }),
    client.items.create({
      project_id: projectId,
      type: 'FR',
      title: 'Functional Requirement 1'
    }),
    client.items.create({
      project_id: projectId,
      type: 'FR',
      title: 'Functional Requirement 2'
    }),
    client.items.create({
      project_id: projectId,
      type: 'TC',
      title: 'Test Case 1'
    }),
    client.items.create({
      project_id: projectId,
      type: 'TC',
      title: 'Test Case 2'
    })
  ]);

  return { br, fr1, fr2, tc1, tc2 };
}
```

### Mixed sequential and parallel

```typescript
async function setupProject() {
  // Step 1: Create project (must be first)
  const project = await client.projects.create({
    name: 'My Project',
    key: 'PROJ'
  });

  // Step 2: Create items in parallel
  const [br1, br2, fr1, fr2] = await Promise.all([
    client.items.create({ project_id: project.id, type: 'BR', title: 'BR 1' }),
    client.items.create({ project_id: project.id, type: 'BR', title: 'BR 2' }),
    client.items.create({ project_id: project.id, type: 'FR', title: 'FR 1' }),
    client.items.create({ project_id: project.id, type: 'FR', title: 'FR 2' })
  ]);

  // Step 3: Create links in parallel (after items exist)
  const links = await Promise.all([
    client.links.create({ source_id: fr1.id, target_id: br1.id, link_type: 'satisfies' }),
    client.links.create({ source_id: fr2.id, target_id: br2.id, link_type: 'satisfies' })
  ]);

  return { project, items: [br1, br2, fr1, fr2], links };
}
```

### Error handling with async/await

```typescript
async function safeOperation() {
  try {
    const project = await client.projects.create({
      name: 'My Project',
      key: 'PROJ'
    });

    const item = await client.items.create({
      project_id: project.id,
      type: 'FR',
      title: 'Requirement'
    });

    return { project, item };
  } catch (error) {
    if (error instanceof ApiError) {
      console.error(`API Error ${error.status}: ${error.message}`);
      console.error('Details:', error.data);
    } else {
      console.error('Unexpected error:', error);
    }
    throw error;
  }
}
```

## Error Handling

### Error types

```typescript
import {
  ApiError,
  AuthenticationError,
  NotFoundError,
  ValidationError,
  RateLimitError,
  NetworkError
} from '@tracertm/sdk';

try {
  const item = await client.items.create({
    project_id: 'proj-123',
    type: 'INVALID_TYPE',
    title: 'Test'
  });
} catch (error) {
  if (error instanceof ValidationError) {
    console.error('Validation failed:', error.message);
    console.error('Field errors:', error.errors);
    // error.errors = { type: ['Invalid type: INVALID_TYPE'] }
  } else if (error instanceof NotFoundError) {
    console.error('Resource not found:', error.resourceType, error.resourceId);
  } else if (error instanceof AuthenticationError) {
    console.error('Authentication failed - check API key');
  } else if (error instanceof RateLimitError) {
    console.error(`Rate limited. Retry after ${error.retryAfter}s`);
    await new Promise(resolve => setTimeout(resolve, error.retryAfter * 1000));
    // Retry request
  } else if (error instanceof NetworkError) {
    console.error('Network error - check connection');
  } else {
    console.error('Unexpected error:', error);
  }
}
```

### Handling specific status codes

```typescript
try {
  const item = await client.items.get('item-123');
} catch (error) {
  if (error instanceof ApiError) {
    switch (error.status) {
      case 400:
        console.error('Bad request:', error.data);
        break;
      case 401:
        console.error('Unauthorized - invalid API key');
        break;
      case 403:
        console.error('Forbidden - insufficient permissions');
        break;
      case 404:
        console.error('Item not found');
        break;
      case 429:
        console.error('Rate limited');
        break;
      case 500:
        console.error('Server error');
        break;
      default:
        console.error('Error:', error.message);
    }
  }
}
```

### Retry logic

```typescript
async function retryOperation<T>(
  operation: () => Promise<T>,
  maxRetries = 3,
  delayMs = 1000
): Promise<T> {
  let lastError: Error;

  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await operation();
    } catch (error) {
      lastError = error as Error;

      // Don't retry on client errors (4xx)
      if (error instanceof ApiError && error.status >= 400 && error.status < 500) {
        throw error;
      }

      if (attempt < maxRetries) {
        console.log(`Attempt ${attempt} failed, retrying in ${delayMs}ms...`);
        await new Promise(resolve => setTimeout(resolve, delayMs));
        delayMs *= 2; // Exponential backoff
      }
    }
  }

  throw lastError!;
}

// Usage
const item = await retryOperation(() =>
  client.items.get('item-123')
);
```

## Configuration Options

### Complete configuration reference

```typescript
import { TraceRTMClient, type ClientConfig } from '@tracertm/sdk';

const config: ClientConfig = {
  // Required
  apiKey: 'your-api-key',

  // Optional
  baseUrl: 'https://api.tracertm.io/v1',

  // Timeout (milliseconds)
  timeout: 30000,

  // Retry configuration
  retry: {
    enabled: true,
    maxRetries: 3,
    retryDelay: 1000,
    retryOnStatus: [408, 429, 500, 502, 503, 504],
    exponentialBackoff: true
  },

  // Custom headers
  headers: {
    'User-Agent': 'MyApp/1.0.0',
    'X-Custom-Header': 'value'
  },

  // Request interceptor
  onRequest: (config) => {
    console.log('Making request:', config.method, config.url);
    return config;
  },

  // Response interceptor
  onResponse: (response) => {
    console.log('Received response:', response.status);
    return response;
  },

  // Error interceptor
  onError: (error) => {
    console.error('Request failed:', error.message);
    throw error;
  },

  // Logging
  logger: {
    debug: (msg) => console.debug(msg),
    info: (msg) => console.info(msg),
    warn: (msg) => console.warn(msg),
    error: (msg) => console.error(msg)
  }
};

const client = new TraceRTMClient(config);
```

## Complete Workflow Example

```typescript
import { TraceRTMClient } from '@tracertm/sdk';

async function setupTraceabilityProject() {
  // Initialize client
  const client = new TraceRTMClient({
    apiKey: process.env.TRACERTM_API_KEY!
  });

  try {
    // 1. Create project
    console.log('Creating project...');
    const project = await client.projects.create({
      name: 'Mobile App',
      key: 'MOBILE',
      description: 'Mobile app requirements tracking'
    });
    console.log(`✓ Project created: ${project.id}`);

    // 2. Create business requirements
    console.log('\nCreating business requirements...');
    const [br1, br2] = await Promise.all([
      client.items.create({
        project_id: project.id,
        type: 'BR',
        title: 'User Authentication',
        description: 'Users shall be able to authenticate securely',
        priority: 'MUST'
      }),
      client.items.create({
        project_id: project.id,
        type: 'BR',
        title: 'Data Synchronization',
        description: 'App shall sync data across devices',
        priority: 'MUST'
      })
    ]);
    console.log(`✓ Created 2 business requirements`);

    // 3. Create functional requirements
    console.log('\nCreating functional requirements...');
    const [fr1, fr2, fr3] = await Promise.all([
      client.items.create({
        project_id: project.id,
        type: 'FR',
        title: 'Email/Password Login',
        description: 'System shall support email/password authentication',
        priority: 'MUST',
        custom_fields: { component: 'Auth', sprint: 1 }
      }),
      client.items.create({
        project_id: project.id,
        type: 'FR',
        title: 'OAuth Social Login',
        description: 'System shall support OAuth via Google/Facebook',
        priority: 'SHOULD',
        custom_fields: { component: 'Auth', sprint: 1 }
      }),
      client.items.create({
        project_id: project.id,
        type: 'FR',
        title: 'Real-time Sync Engine',
        description: 'System shall sync data in real-time',
        priority: 'MUST',
        custom_fields: { component: 'Sync', sprint: 2 }
      })
    ]);
    console.log(`✓ Created 3 functional requirements`);

    // 4. Create test cases
    console.log('\nCreating test cases...');
    const [tc1, tc2, tc3] = await Promise.all([
      client.items.create({
        project_id: project.id,
        type: 'TC',
        title: 'Test Email Login',
        description: 'Verify email/password login works',
        priority: 'MUST'
      }),
      client.items.create({
        project_id: project.id,
        type: 'TC',
        title: 'Test OAuth Login',
        description: 'Verify OAuth login works',
        priority: 'SHOULD'
      }),
      client.items.create({
        project_id: project.id,
        type: 'TC',
        title: 'Test Data Sync',
        description: 'Verify data syncs correctly',
        priority: 'MUST'
      })
    ]);
    console.log(`✓ Created 3 test cases`);

    // 5. Create traceability links
    console.log('\nCreating traceability links...');
    await Promise.all([
      // FR -> BR links (satisfies)
      client.links.create({
        source_id: fr1.id,
        target_id: br1.id,
        link_type: 'satisfies'
      }),
      client.links.create({
        source_id: fr2.id,
        target_id: br1.id,
        link_type: 'satisfies'
      }),
      client.links.create({
        source_id: fr3.id,
        target_id: br2.id,
        link_type: 'satisfies'
      }),

      // TC -> FR links (verifies)
      client.links.create({
        source_id: tc1.id,
        target_id: fr1.id,
        link_type: 'verifies'
      }),
      client.links.create({
        source_id: tc2.id,
        target_id: fr2.id,
        link_type: 'verifies'
      }),
      client.links.create({
        source_id: tc3.id,
        target_id: fr3.id,
        link_type: 'verifies'
      })
    ]);
    console.log(`✓ Created 6 traceability links`);

    // 6. Verify traceability
    console.log('\nVerifying traceability...');

    // Check impact of BR1
    const impact = await client.graph.getImpactAnalysis(br1.id, 5);
    console.log(`\nBR1 impacts ${impact.affected_count} items:`);
    for (const item of impact.affected_items) {
      console.log(`  - ${item.type} ${item.title} (depth: ${item.depth})`);
    }

    // Check dependencies of TC1
    const deps = await client.graph.getDependencyAnalysis(tc1.id, 5);
    console.log(`\nTC1 depends on ${deps.dependency_count} items:`);
    for (const item of deps.dependencies) {
      console.log(`  - ${item.type} ${item.title}`);
    }

    // Find path from BR to TC
    const path = await client.graph.findPath(br1.id, tc1.id);
    console.log(`\nPath from BR1 to TC1:`);
    console.log(`  ${path.map(item => `${item.type} ${item.title}`).join(' -> ')}`);

    // 7. Check for issues
    console.log('\nChecking for issues...');

    const cycles = await client.graph.detectCycles(project.id);
    console.log(`Cycles detected: ${cycles.length}`);

    const orphans = await client.graph.getOrphanItems(project.id);
    console.log(`Orphaned items: ${orphans.length}`);

    // 8. Summary
    console.log('\n' + '='.repeat(50));
    console.log('✓ Project setup complete!');
    console.log(`  Project: ${project.name} (${project.key})`);
    console.log(`  Business Requirements: 2`);
    console.log(`  Functional Requirements: 3`);
    console.log(`  Test Cases: 3`);
    console.log(`  Traceability Links: 6`);
    console.log('='.repeat(50));

    return project;

  } catch (error) {
    console.error('\n❌ Error:', error);
    throw error;
  }
}

// Run the workflow
setupTraceabilityProject()
  .then(() => console.log('\nDone!'))
  .catch((error) => {
    console.error('Failed:', error);
    process.exit(1);
  });
```

## Next Steps

- [API Reference](/docs/api/rest-api) - Complete REST API documentation
- [JavaScript SDK Examples](/docs/sdk/javascript/examples) - More code examples
- [Type Definitions](/docs/sdk/javascript/types) - TypeScript type reference
- [Error Handling](/docs/sdk/javascript/errors) - Exception reference

<Callout type="info">
**Questions?** Check [GitHub Issues](https://github.com/tracertm/js-sdk/issues) or join [Discord #sdk-help](https://discord.gg/tracertm)
</Callout>
