SW Combine SDK
    Preparing search index...

    SW Combine SDK

    SW Combine SDK for Node.js

    Comprehensive TypeScript SDK for the Star Wars Combine API v2.0

    npm version TypeScript License: MIT API Docs

    FeaturesInstallationQuick StartDocumentationExamples

    • Full API Coverage - All 60+ endpoints across 11 resource categories
    • OAuth 2.0 Built-in - Complete OAuth flow with automatic token refresh
    • TypeScript First - Full type definitions with IntelliSense support
    • Type-Safe Scopes - 170+ OAuth scope constants with autocomplete
    • Automatic Retries - Exponential backoff for failed requests
    • Modern & Universal - ES Modules + CommonJS, Node.js 18+
    • Developer Tools - Helper scripts for OAuth and testing
    • Zero Dependencies (except axios)
    npm install swcombine-sdk
    # or
    yarn add swcombine-sdk
    # or
    pnpm add swcombine-sdk
    import { SWCombine } from 'swcombine-sdk';

    // Public mode (no auth)
    const publicClient = new SWCombine();

    // Token-only mode (use an existing token)
    const tokenClient = new SWCombine({
    token: process.env.SWC_ACCESS_TOKEN!,
    });

    // Full OAuth mode (required for OAuth flows and token refresh)
    const fullClient = new SWCombine({
    clientId: process.env.SWC_CLIENT_ID!,
    clientSecret: process.env.SWC_CLIENT_SECRET!,
    token: process.env.SWC_ACCESS_TOKEN, // Optional - string or OAuthToken object
    redirectUri: 'http://localhost:3000/callback',
    accessType: 'offline',
    });
    // Get public character information (no auth required)
    const character = await publicClient.character.getByHandle({
    handle: 'character-handle',
    });

    console.log(character.uid); // "1:12345"
    console.log(character.name); // "Character Name"
    // For authenticated endpoints, provide an access token
    const authenticatedClient = new SWCombine({
    token: process.env.SWC_ACCESS_TOKEN!,
    });

    // Get character details
    const character = await authenticatedClient.character.get({
    uid: '1:12345',
    });

    // Get character messages
    const messages = await authenticatedClient.character.messages.list({
    uid: '1:12345',
    mode: 'received',
    });

    // List returns metadata items (MessageListItem[])
    const firstMessageId = messages[0]?.attributes.uid;
    if (firstMessageId) {
    const fullMessage = await authenticatedClient.character.messages.get({
    uid: '1:12345',
    messageId: firstMessageId,
    });
    console.log(fullMessage.communication);
    }

    // Send a message
    // IMPORTANT: use receiver handle(s), not UID(s), for `receivers`
    await authenticatedClient.character.messages.create({
    uid: '1:12345',
    receivers: 'recipient_handle',
    communication: 'Test message',
    });

    // Get faction information
    const faction = await authenticatedClient.faction.get({
    uid: '20:123',
    });

    Use the included helper script to get an access token:

    # 1. Add your credentials to .env
    echo "SWC_CLIENT_ID=your_client_id" >> .env
    echo "SWC_CLIENT_SECRET=your_client_secret" >> .env

    # 2. Run the OAuth helper
    npm run get-token

    # 3. Visit http://localhost:3000 in your browser
    # 4. Authorize the app and copy the token to .env

    OAuth-only methods require full OAuth mode (clientId + clientSecret):

    • client.auth.getAuthorizationUrl(...)
    • client.auth.handleCallback(...)
    • client.auth.revokeToken(...)
    • client.refreshToken()
    import { SWCombine, CharacterScopes, MessageScopes } from 'swcombine-sdk';

    const client = new SWCombine({
    clientId: 'your-client-id',
    clientSecret: 'your-client-secret',
    redirectUri: 'http://localhost:3000/callback',
    accessType: 'offline', // Get refresh token
    });

    // 1. Generate authorization URL
    const authUrl = client.auth.getAuthorizationUrl({
    scopes: [
    CharacterScopes.READ,
    CharacterScopes.STATS,
    MessageScopes.READ,
    MessageScopes.SEND,
    ],
    state: 'random-csrf-token',
    });

    // 2. Redirect user to authUrl...

    // 3. Handle callback
    const result = await client.auth.handleCallback(req.query);

    if (result.success) {
    const token = result.token!;
    console.log('Access Token:', token.accessToken);
    console.log('Refresh Token:', token.refreshToken);
    }
    import {
    CharacterScopes,
    MessageScopes,
    Scopes,
    getAllScopes,
    getReadOnlyScopes,
    } from 'swcombine-sdk';

    // Use constants with autocomplete
    const scopes = [
    CharacterScopes.READ, // TypeScript suggests all scopes
    CharacterScopes.STATS,
    MessageScopes.SEND,
    Scopes.PersonalInventory.SHIPS.READ,
    ];

    // Or use helpers
    const readOnly = getReadOnlyScopes();
    const everything = getAllScopes();

    See OAuth Scopes Guide for all 170+ available scopes.

    The SDK provides access to all SW Combine API v2.0 resources through a fluent, type-safe interface:

    Resource Access Description
    client.api Utilities Hello world, permissions, rate limits, time conversion
    client.character Characters Profile, messages, skills, privileges, credits, credit log
    client.faction Factions Info, members, budgets, stockholders, credits, credit log
    client.galaxy Galaxy Systems, sectors, planets, stations, cities
    client.inventory Inventory Entity listing, management, tagging
    client.market Market Vendor listings
    client.news News GNS and Sim News feeds
    client.types Types Entity types, classes, and detailed type info
    client.events Events Personal, faction, inventory, and combat events
    client.location Location Entity location lookups
    client.datacard Datacards Datacard management and assignment

    Also includes a Timestamp utility for Combine Galactic Time (CGT) conversion and formatting.

    For complete method signatures, parameters, and examples, see the API Reference Documentation.

    The SW Combine API has a rate limit of 600 requests per hour. The SDK provides tools to monitor and handle rate limits:

    // Check current rate limit status after any API call
    const rateLimit = client.getRateLimitInfo();
    if (rateLimit) {
    console.log(`${rateLimit.remaining}/${rateLimit.limit} requests remaining`);
    console.log(`Resets at: ${rateLimit.resetTime}`);
    }

    // Set up a callback to monitor rate limits in real-time
    client.onRateLimitUpdate((info) => {
    if (info.remaining < 100) {
    console.warn(`Warning: Only ${info.remaining} API requests remaining!`);
    }
    });

    // Or check via API endpoint for detailed per-endpoint limits
    const limits = await client.api.rateLimits();

    The SDK automatically handles rate limit errors with exponential backoff and respects the Retry-After header when provided.

    import { SWCError } from 'swcombine-sdk';

    try {
    const character = await client.character.get({ uid: '1:12345' });
    } catch (error) {
    if (error instanceof SWCError) {
    console.error('Status:', error.statusCode); // 404
    console.error('Message:', error.message); // "Resource not found"
    console.error('Type:', error.type); // "not_found"
    console.error('Retryable:', error.retryable); // false
    }
    }

    Full TypeScript support with intelligent type inference:

    import { Message, MessageListItem } from 'swcombine-sdk';

    // Types are automatically inferred
    const character = await client.character.get({ uid: '1:12345' });
    // character: Character

    // Request parameters are typed
    const listedMessages = await client.character.messages.list({
    uid: '1:12345',
    mode: 'received', // Optional - TypeScript knows valid values: 'sent' | 'received'
    // mode: 'invalid', // TypeScript error
    });

    const messageListItem: MessageListItem | undefined = listedMessages[0];
    const messageId = messageListItem?.attributes.uid;

    if (messageId) {
    const messageDetail: Message = await client.character.messages.get({
    uid: '1:12345',
    messageId,
    });
    console.log(messageDetail.communication);
    }

    // Send message: receivers must be handle(s), not UID(s)
    await client.character.messages.create({
    uid: '1:12345',
    receivers: 'recipient_handle_1;recipient_handle_2',
    communication: 'Hello there',
    });
    interface ClientConfig {
    // Optional OAuth credentials
    // If provided, both must be set together
    clientId?: string;
    clientSecret?: string;

    // Optional authentication - string or full OAuthToken object
    token?: string | OAuthToken;

    // Optional OAuth settings
    redirectUri?: string;
    accessType?: 'online' | 'offline';

    // Optional HTTP settings
    baseURL?: string; // Default: https://www.swcombine.com/ws/v2.0/
    timeout?: number; // Default: 30000 (30 seconds)
    maxRetries?: number; // Default: 3
    retryDelay?: number; // Default: 1000ms
    debug?: boolean; // Default: false
    }

    interface OAuthToken {
    accessToken: string;
    refreshToken?: string;
    expiresAt: number; // Timestamp in milliseconds
    }

    See the examples directory for complete working examples:

    import { SWCombine } from 'swcombine-sdk';

    const client = new SWCombine();

    // Get character info
    const character = await client.character.getByHandle({
    handle: 'character-name',
    });

    console.log(`${character.name} (${character.uid})`);

    Interactive OAuth flow to obtain access tokens:

    npm run get-token
    

    Quickly get a character's UID from their handle:

    npm run get-character-uid YourHandle
    
    npm run test:integration
    
    # Install dependencies
    npm install

    # Build
    npm run build

    # Run unit tests (fast, no API calls)
    npm test

    # Run unit tests in watch mode
    npm run test:watch

    # Run all integration tests (requires .env with API credentials)
    npm run test:integration

    # Run integration tests for a specific resource
    npm run test:integration:character
    npm run test:integration:galaxy
    npm run test:integration:faction
    # Also: test:integration:api, test:integration:market, test:integration:news,
    # test:integration:types, test:integration:misc

    # Lint
    npm run lint

    # Format code
    npm run format
    • Node.js 18 or higher
    • TypeScript 5.5 or higher (for TypeScript projects)

    MIT © Dreks Selmur aka JonMarkGo

    Contributions are welcome! Please:

    1. Fork the repository
    2. Create a feature branch
    3. Make your changes
    4. Add tests if applicable
    5. Submit a pull request

    Made for the Star Wars Combine community