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
npm install @monkeyhub/sdkInitialization
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>
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
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
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
// 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 Class | Code | HTTP | When |
|---|---|---|---|
| MonkeyNotFoundError | NOT_FOUND | 404 | Item, job, or file not found |
| MonkeyUnauthorizedError | UNAUTHORIZED | 401 | Missing API key |
| MonkeyForbiddenError | FORBIDDEN | 403 | Invalid key or mk_pub_ used for write |
| MonkeyValidationError | VALIDATION_ERROR | 400 | Scan without key, malformed input |
| MonkeyConflictError | CONFLICT | 409 | Duplicate task ID |
| MonkeyPayloadTooLargeError | PAYLOAD_TOO_LARGE | 413 | Item > 400KB or file > plan max |
| MonkeyQuotaExceededError | QUOTA_EXCEEDED | 402 | Free tier bundled usage exhausted |
| MonkeyRateLimitError | RATE_LIMITED | 429 | Rate limit hit (after SDK retries) |
| MonkeyServiceError | SERVICE_ERROR | 500/503 | Internal failure or temporary storage throttle |
Error handling pattern
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:
| Condition | Retries | Backoff |
|---|---|---|
| 429 (Rate Limited) | 3 | Exponential: 1s → 2s → 4s |
| 503 (Service Unavailable) | 3 | Exponential: 1s → 2s → 4s |
| Network error | 1 | 1s |
All other errors are thrown immediately. If retries are exhausted, the final error is thrown.
Pagination
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)