PlayableLabs Docs
Developers

SDKs and Examples

API client examples in TypeScript and JavaScript, common patterns, and future SDK plans for PlayableLabs

Overview

PlayableLabs does not yet offer an official SDK package. However, the REST API is straightforward to use with any HTTP client. This page provides ready-to-use code patterns for common operations.

TypeScript API Client

A minimal typed client you can drop into any TypeScript project:

const API_BASE = 'https://api.playablelabs.studio/api'

interface RequestOptions {
  method?: string
  body?: Record<string, unknown>
  params?: Record<string, string>
}

async function apiClient<T>(
  endpoint: string,
  token: string,
  options: RequestOptions = {}
): Promise<T> {
  const { method = 'GET', body, params } = options

  const url = new URL(`${API_BASE}${endpoint}`)
  if (params) {
    Object.entries(params).forEach(([key, value]) =>
      url.searchParams.set(key, value)
    )
  }

  const response = await fetch(url.toString(), {
    method,
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json',
    },
    body: body ? JSON.stringify(body) : undefined,
  })

  if (!response.ok) {
    const error = await response.json()
    throw new Error(error.message || `API error: ${response.status}`)
  }

  return response.json()
}

Common Patterns

List Games with Pagination

interface PaginatedResponse<T> {
  data: T[]
  meta: { page: number; limit: number; total: number; totalPages: number }
}

interface Game {
  id: string
  name: string
  createdAt: string
}

const games = await apiClient<PaginatedResponse<Game>>(
  '/games',
  'YOUR_TOKEN',
  { params: { page: '1', limit: '20' } }
)

console.log(`Found ${games.meta.total} games`)

Upload an Asset

Asset uploads use pre-signed URLs. The flow is two steps:

// Step 1: Get a pre-signed upload URL
const { uploadUrl, assetId } = await apiClient<{
  uploadUrl: string
  assetId: string
}>('/storage/urls', 'YOUR_TOKEN', {
  method: 'POST',
  body: {
    fileName: 'hero-sprite.png',
    contentType: 'image/png',
    organizationId: 'YOUR_ORG_ID',
  },
})

// Step 2: Upload the file directly to storage
await fetch(uploadUrl, {
  method: 'PUT',
  headers: { 'Content-Type': 'image/png' },
  body: fileBuffer,
})

Trigger an Export

const exportResult = await apiClient('/export', 'YOUR_TOKEN', {
  method: 'POST',
  body: {
    variantId: 'VARIANT_ID',
    network: 'unity',
  },
})

Error Handling Pattern

try {
  const games = await apiClient('/games', 'YOUR_TOKEN')
  console.log(games)
} catch (error: unknown) {
  if (error instanceof Error) {
    if (error.message.includes('401')) {
      console.error('Invalid or expired token')
    } else if (error.message.includes('429')) {
      console.error('Rate limited -- retry after a delay')
    } else {
      console.error('API error:', error.message)
    }
  }
}

cURL Quick Reference

# List games
curl -H "Authorization: Bearer YOUR_TOKEN" \
  "https://api.playablelabs.studio/api/games?page=1&limit=10"

# Get a single game
curl -H "Authorization: Bearer YOUR_TOKEN" \
  https://api.playablelabs.studio/api/games/GAME_ID

# List assets
curl -H "Authorization: Bearer YOUR_TOKEN" \
  "https://api.playablelabs.studio/api/assets?organizationId=YOUR_ORG_ID"

# Trigger export
curl -X POST \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"variantId":"VARIANT_ID","network":"unity"}' \
  https://api.playablelabs.studio/api/export

Future SDK Plans

Official SDK packages are planned for:

  • npm (@playablelabs/sdk) -- TypeScript/JavaScript client with full type safety
  • Python (playablelabs) -- For data pipeline and automation workflows

Planned SDK features:

  • Auto-pagination helpers
  • Built-in retry logic with exponential backoff
  • Token refresh and rotation support
  • Typed request and response interfaces

Until official SDKs are available, use the patterns on this page as a starting point.

Next Steps

On this page