HatchedDocs
Guides

SDK quickstart

Install @hatched/sdk-js, authenticate, and make your first calls from Node or TypeScript.

@hatched/sdk-js is the official TypeScript SDK for the Hatched API. It ships as dual ESM + CJS, runs on Node 18+, Cloudflare Workers, Vercel Edge, Deno, and Bun. Full package on npmjs.com/package/@hatched/sdk-js.

Install

pnpm add @hatched/sdk-js

Initialise a client

import { HatchedClient } from '@hatched/sdk-js';

const hatched = new HatchedClient({
  apiKey: process.env.HATCHED_API_KEY!,
  // optional overrides:
  baseUrl: 'https://api.hatched.live/api/v1',
  timeoutMs: 15_000,
  maxRetries: 3,
  fetch: globalThis.fetch,
});

The SDK parses the canonical error envelope and throws typed HatchedError subclasses with requestId, code, and statusCode fields.

Secret keys (hatch_live_*, hatch_test_*) are server-only. The SDK throws if instantiated in a DOM environment. See Auth model for browser options.

Core resources

// Eggs & buddies
await hatched.eggs.create({ userId, presetId });
await hatched.eggs.hatch(eggId);
await hatched.buddies.list({ userId });

// Economy
await hatched.buddies.earn(buddyId, { amount: 50, reason: 'lesson_reward' });
await hatched.buddies.spend(buddyId, { amount: 20, reason: 'item_purchase' });
await hatched.buddies.equip(buddyId, { equip: [itemId] });

// Events
await hatched.events.send({ eventId, userId, type, properties });

// Operations (async image jobs)
const op = await hatched.eggs.hatch(eggId);
const finished = await hatched.operations.wait(op.operationId);

// Widget sessions
await hatched.widgetSessions.create({ buddyId, userId, scopes, ttlSeconds });
await hatched.widgetSessions.revoke(sessionId);

Error handling

import { HatchedError, RateLimitError, ValidationError } from '@hatched/sdk-js';

try {
  await hatched.events.send({ ... });
} catch (err) {
  if (err instanceof RateLimitError) {
    await sleep(err.retryAfter * 1000);
  } else if (err instanceof ValidationError) {
    console.error('bad payload:', err.details);
  } else if (err instanceof HatchedError) {
    console.error(err.code, err.requestId, err.message);
  } else {
    throw err;
  }
}

The SDK exposes a typed class per known error code. See Error codes for the full catalogue.

Retries and idempotency

  • events.send is idempotent on eventId — passing the same id twice returns the cached effect without re-applying rules.
  • The client retries GETs and idempotent: true POSTs on network failures, 408, 429 (with Retry-After honoured), and 5xx responses. Exponential backoff + jitter.
  • 4xx responses (other than 408/429) surface immediately.

Cancellation

Every resource method accepts an optional AbortSignal as its last argument. The SDK combines it with the built-in timeout via AbortSignal.any, so either source can cancel the request.

const controller = new AbortController();
setTimeout(() => controller.abort(), 500);
await hatched.buddies.get(buddyId, controller.signal);

Rate limits + request ids

await hatched.events.send({ ... });

console.log(hatched.getRateLimitInfo());
// { limit: 1000, remaining: 986, reset: 1735689600, retryAfter: undefined }

console.log(hatched.getLastRequestId());
// 'req_abc_123'

Include the request id in any support ticket and we can look up the full trace.