> ## Documentation Index
> Fetch the complete documentation index at: https://docs.engagefabric.com/llms.txt
> Use this file to discover all available pages before exploring further.

# JavaScript SDK

> Integrate EngageFabric with the JavaScript SDK. Install, initialize, track events, manage players, and query leaderboards from Node.js or browsers.

The EngageFabric JavaScript SDK provides a simple, type-safe way to integrate gamification into your applications.

## Installation

<Note>
  The EngageFabric SDK is currently available for enterprise customers and early access partners.
  Contact us at [support@engagefabric.com](mailto:support@engagefabric.com) to get access.
</Note>

Once you have access, install via npm:

<CodeGroup>
  ```bash npm theme={null}
  npm install @engagefabricsdk/sdk
  ```

  ```bash yarn theme={null}
  yarn add @engagefabricsdk/sdk
  ```

  ```bash pnpm theme={null}
  pnpm add @engagefabricsdk/sdk
  ```
</CodeGroup>

## Quick Start

```typescript theme={null}
import { EngageFabric } from '@engagefabricsdk/sdk';

// Initialize the client
const client = new EngageFabric({
  apiKey: 'your-api-key',
  projectId: 'your-project-id'
});

// Identify a player
const player = await client.players.identify({
  externalUserId: 'user-123',
  displayName: 'John Doe'
});

// Track an event
await client.events.track({
  playerId: player.id,
  name: 'lesson_completed',
  properties: {
    courseId: 'math-101',
    score: 95
  }
});
```

***

## Configuration

```typescript theme={null}
const client = new EngageFabric({
  // Required
  apiKey: 'your-api-key',
  projectId: 'your-project-id',

  // Optional
  baseUrl: 'https://api.engagefabric.com', // Custom API URL
  timeout: 30000, // Request timeout in ms
  retries: 3, // Number of retry attempts
  debug: false // Enable debug logging
});
```

***

## API Reference

### Players

```typescript theme={null}
// Identify/create a player
const player = await client.players.identify({
  externalUserId: 'user-123',
  displayName: 'John Doe',
  metadata: { email: 'john@example.com' }
});

// Get a player
const player = await client.players.get('player-id');

// Get player by external ID
const player = await client.players.getByExternalId('user-123');

// Update a player
const player = await client.players.update('player-id', {
  displayName: 'John Smith'
});

// Grant XP
await client.players.grantXP('player-id', { amount: 100 });

// Grant currency
await client.players.grantCurrency('player-id', {
  currencyId: 'coins',
  amount: 500
});

// Spend currency
await client.players.spendCurrency('player-id', {
  currencyId: 'coins',
  amount: 100
});
```

### Events

```typescript theme={null}
// Track a single event
await client.events.track({
  playerId: 'player-id',
  name: 'purchase_completed',
  properties: {
    itemId: 'sword-001',
    price: 100
  }
});

// Track with idempotency key
await client.events.track({
  playerId: 'player-id',
  name: 'purchase_completed',
  idempotencyKey: 'purchase-abc123',
  properties: { ... }
});
```

### Quests

```typescript theme={null}
// Get player's quests
const quests = await client.quests.getPlayerQuests('player-id');

// Get quest details
const quest = await client.quests.get('quest-id');

// Get quest progress
const progress = await client.quests.getProgress('player-id', 'quest-id');
```

### Adventures

```typescript theme={null}
// Get player's adventures
const adventures = await client.adventures.getPlayerAdventures('player-id');

// Get adventure details
const adventure = await client.adventures.get('adventure-id');
```

### Leaderboards

```typescript theme={null}
// Get top rankings
const rankings = await client.leaderboards.getRankings('leaderboard-id', {
  limit: 10
});

// Get player's rank
const rank = await client.leaderboards.getPlayerRank(
  'leaderboard-id',
  'player-id'
);

// Get rank with neighbors
const neighbors = await client.leaderboards.getRankWithNeighbors(
  'leaderboard-id',
  'player-id',
  { above: 2, below: 2 }
);
```

### Lobbies

```typescript theme={null}
// Create a lobby
const lobby = await client.lobbies.create({
  name: 'Game Room 1',
  maxPlayers: 4,
  metadata: { gameMode: 'deathmatch' }
});

// Join a lobby
await client.lobbies.join('lobby-id', 'player-id');

// Leave a lobby
await client.lobbies.leave('lobby-id', 'player-id');

// Set ready status
await client.lobbies.setReady('lobby-id', 'player-id', true);

// Start the lobby
await client.lobbies.start('lobby-id');
```

### Chat

```typescript theme={null}
// Send a message
await client.chat.sendMessage('channel-id', {
  playerId: 'player-id',
  content: 'Hello everyone!'
});

// Get messages
const messages = await client.chat.getMessages('channel-id', {
  limit: 50
});
```

***

## WebSocket Client

Connect for real-time updates:

```typescript theme={null}
// Connect to WebSocket
const socket = client.realtime.connect();

// Subscribe to player updates
client.realtime.subscribeToPlayer('player-id');

// Listen for events
client.realtime.on('xp_updated', (data) => {
  console.log(`New XP: ${data.xp}`);
});

client.realtime.on('level_up', (data) => {
  console.log(`Reached level ${data.newLevel}!`);
});

client.realtime.on('quest_completed', (data) => {
  console.log(`Quest completed: ${data.questName}`);
});

// Disconnect when done
client.realtime.disconnect();
```

***

## State Management

The SDK includes Zustand stores for state management:

```typescript theme={null}
import { usePlayerStore, useQuestStore } from '@engagefabricsdk/sdk';

// Access player state
const { player, loading, error } = usePlayerStore();

// Access quests
const { quests, fetchQuests } = useQuestStore();
```

***

## TypeScript Support

The SDK is fully typed:

```typescript theme={null}
import type {
  Player,
  Quest,
  Adventure,
  LeaderboardEntry,
  Lobby,
  ChatMessage
} from '@engagefabricsdk/sdk';

const player: Player = await client.players.get('id');
```

***

## Error Handling

```typescript theme={null}
import { EngageFabricError } from '@engagefabricsdk/sdk';

try {
  await client.players.get('invalid-id');
} catch (error) {
  if (error instanceof EngageFabricError) {
    console.log(error.code); // 'PLAYER_NOT_FOUND'
    console.log(error.message); // 'Player not found'
    console.log(error.requestId); // For support
  }
}
```

***

## Best Practices

<AccordionGroup>
  <Accordion title="Keep API key secure">
    Never expose your API key in client-side code. Use a backend proxy for browser apps.
  </Accordion>

  <Accordion title="Use idempotency keys">
    For important operations like purchases, always use idempotency keys to prevent duplicates.
  </Accordion>

  <Accordion title="Handle errors gracefully">
    Implement proper error handling and retry logic for transient failures.
  </Accordion>

  <Accordion title="Cache player data">
    Use the built-in Zustand stores to cache player data and reduce API calls.
  </Accordion>
</AccordionGroup>

***

## REST API Alternative

If you prefer direct HTTP calls over using the SDK, you can achieve the same operations via the REST API. This is useful for server-side integrations in any language.

<CodeGroup>
  ```bash cURL theme={null}
  # Identify a player
  curl -X POST "https://api.engagefabric.com/api/v1/players/identify" \
    -H "X-API-Key: ef_live_your-api-key" \
    -H "Content-Type: application/json" \
    -d '{
      "externalUserId": "user-123",
      "displayName": "John Doe"
    }'

  # Track an event
  curl -X POST "https://api.engagefabric.com/api/v1/events" \
    -H "X-API-Key: ef_live_your-api-key" \
    -H "Content-Type: application/json" \
    -d '{
      "playerId": "player-id",
      "name": "lesson_completed",
      "properties": {
        "courseId": "math-101",
        "score": 95
      }
    }'

  # Get leaderboard rankings
  curl -X GET "https://api.engagefabric.com/api/v1/leaderboards/weekly-xp/rankings?limit=10" \
    -H "X-API-Key: ef_live_your-api-key"
  ```

  ```python Python theme={null}
  import requests

  API_KEY = "ef_live_your-api-key"
  BASE_URL = "https://api.engagefabric.com/api/v1"
  HEADERS = {
      "X-API-Key": API_KEY,
      "Content-Type": "application/json"
  }

  # Identify a player
  player = requests.post(
      f"{BASE_URL}/players/identify",
      headers=HEADERS,
      json={
          "externalUserId": "user-123",
          "displayName": "John Doe"
      }
  ).json()

  # Track an event
  requests.post(
      f"{BASE_URL}/events",
      headers=HEADERS,
      json={
          "playerId": player["id"],
          "name": "lesson_completed",
          "properties": {
              "courseId": "math-101",
              "score": 95
          }
      }
  )

  # Get leaderboard rankings
  rankings = requests.get(
      f"{BASE_URL}/leaderboards/weekly-xp/rankings",
      headers=HEADERS,
      params={"limit": 10}
  ).json()
  ```
</CodeGroup>

For more language examples (Ruby, PHP) and the full REST API reference, see the [SDK Overview](/sdks/overview) and [API Reference](/api-reference).
