SDK Reference

The TypeScript client library for all MonkeyHub products. One client instance provides Collection<T>, Tasks,Bucket, and Box interfaces.

Prefer the shell? See CLI for the command-line client built on top of this SDK.

Installation

bash
npm install @monkeyhub/sdk

Initialization

typescript
import { Monkey } from '@monkeyhub/sdk'

const db = new Monkey('mk_live_your_api_key')

The client handles auth injection, request chunking, rate limit retries, and error normalization transparently.

Collection<T>

typescript
interface Collection<T> {
  name: string

  find(keys: (string | number)[], sortKeys?: (string | number)[]): Promise<T[]>
  findOne(key: string | number, sortKey?: string | number): Promise<T | null>
  query(query: QueryOptions): Promise<QueryResult<T>>
  save(item: T | T[]): Promise<void>
  remove(key: string | number, sortKey?: string | number): Promise<void>
  search(options: SearchOptions): Promise<SearchResult<T>>
}

interface CollectionOptions {
  indexes?: (string | IndexDefinition)[]
  key?: { hashKey?: string; rangeKey?: string }
  search?: { fields: string[] }
}

// Usage
const users = db.collection<User>('users', { indexes: ['email', 'role'] })

See MonkeyDB for full query syntax, indexing, and limits.

Tasks

typescript
interface TasksClient {
  create(input: CreateTaskInput): Promise<TaskHandle>
  list(options?: TaskListOptions): Promise<TaskDefinition[]>
  lookup(idOrName: string): Promise<TaskHandle | null>
  update(idOrName: string, input: UpdateTaskInput): Promise<TaskHandle>
  remove(idOrName: string): Promise<void>
}

interface TaskHandle {
  id: string
  name: string
  status: 'enabled' | 'paused'

  pause(): Promise<TaskHandle>
  resume(): Promise<TaskHandle>
  runNow(input?: RunTaskInput): Promise<TaskRun>
  runBatch(inputs: RunTaskInput[]): Promise<TaskRun[]>
  listHistory(limit?: number, options?: { status?: string }): Promise<{ items: TaskRun[]; cursor?: string }>
  getRun(runId: string): Promise<TaskRun | null>
  cancel(runId: string): Promise<void>
  retry(runId: string): Promise<TaskRun>
}

// Usage
const task = await monkey.tasks.create({ name: 'weekly-report', execution: { url: 'https://...' } })
await task.runNow({ payload: { userId: '123' } })

See MonkeyTasks for the full task lifecycle, schedules, and webhook auth.

Bucket

typescript
interface Bucket {
  name: string

  put(filename: string, file: BodyInit, options?: PutOptions): Promise<FileRecord>
  getUrl(filename: string, options?: GetUrlOptions): Promise<string>
  getMeta(filename: string): Promise<FileRecord>
  query(options?: BucketQueryOptions): Promise<BucketQueryResult>
  remove(filename: string): Promise<void>
}

interface FileRecord {
  filename: string
  visibility: 'public' | 'private'
  contentType: string
  ext: string
  status: 'uploading' | 'ready'
  size?: number
  metadata?: Record<string, string>
  url?: string
  createdAt: number
  updatedAt: number
}

// Usage
const bucket = db.bucket('uploads')

See MonkeyBuckets for upload flow, CDN vs signed URLs, and file limits.

Box

typescript
// db.box — create and manage cloud dev environments
const box = await db.boxes.create({ name: 'workspace', image: 'default', size: 'small' })

// Execute commands
const result = await box.exec('npm run build')

// File operations
await box.upload('/workspace/data.json', '{"key": "value"}')
const content = await box.download('/workspace/output.txt')

// Lifecycle
await box.pause()
await box.resume()
await box.destroy()

// Snapshots
const snapshot = await box.snapshot({ name: 'checkpoint' })
const restored = await snapshot.createBox({ name: 'from-snapshot' })

// Templates
const build = await db.boxes.templates.build({ name: 'python-ml', from: 'default', dockerfile: '...' })
const mlBox = await db.boxes.create({ name: 'ml-runner', image: build.templateId! })

See MonkeyBox for the full API including terminals, mounts, and networking.

Error Types

All errors extend MonkeyError with a status code, machine-readable code, and human-readable message.

Error ClassCodeHTTPWhen
MonkeyNotFoundErrorNOT_FOUND404Item, job, or file not found
MonkeyUnauthorizedErrorUNAUTHORIZED401Missing API key
MonkeyForbiddenErrorFORBIDDEN403Invalid key or mk_pub_ used for write
MonkeyValidationErrorVALIDATION_ERROR400Scan without key, malformed input
MonkeyConflictErrorCONFLICT409Duplicate task ID
MonkeyPayloadTooLargeErrorPAYLOAD_TOO_LARGE413Item > 400KB or file > plan max
MonkeyQuotaExceededErrorQUOTA_EXCEEDED402Free tier bundled usage exhausted
MonkeyRateLimitErrorRATE_LIMITED429Rate limit hit (after SDK retries)
MonkeyServiceErrorSERVICE_ERROR500/503Internal failure or temporary storage throttle

Error handling pattern

typescript
import { MonkeyNotFoundError, MonkeyRateLimitError } from '@monkeyhub/sdk'

try {
  const user = await users.findOne('user_01')
} catch (err) {
  if (err instanceof MonkeyNotFoundError) {
    // Handle missing item
  } else if (err instanceof MonkeyRateLimitError) {
    // SDK already retried 3 times — back off at the application level
  } else {
    throw err
  }
}

Auto-Retry

The SDK automatically retries on transient failures:

ConditionRetriesBackoff
429 (Rate Limited)3Exponential: 1s → 2s → 4s
503 (Service Unavailable)3Exponential: 1s → 2s → 4s
Network error11s

All other errors are thrown immediately. If retries are exhausted, the final error is thrown.

Pagination

typescript
interface QueryResult<T> {
  items: T[]
  cursor?: string  // Pass to next query. Absent when no more results.
}

// Paginate through all results
let cursor: string | undefined
do {
  const result = await users.query({
    hashKey: 'admin',
    index: 'role',
    limit: 20,
    cursor,
  })
  processItems(result.items)
  cursor = result.cursor
} while (cursor)