HatchedDocs
Reference

SDK (JavaScript / TypeScript)

Complete method reference for @hatched/sdk-js — HatchedClient, resources, error classes.

Package: @hatched/sdk-js

pnpm add @hatched/sdk-js

HatchedClient

Official Hatched SDK client for JavaScript/TypeScript.

Server-side (secret key):

const hatched = new HatchedClient({
  apiKey: process.env.HATCHED_API_KEY!,
});
const egg = await hatched.eggs.create({ userId: 'user_123' });
await hatched.eggs.updateStatus(egg.eggId, 'ready');
const op = await hatched.eggs.hatch(egg.eggId);

Browser (publishable key, scoped):

const hatched = new HatchedClient({
  publishableKey: 'hatch_pk_xxxxxxxx',
});
const buddy = await hatched.buddies.get('bdy_abc');

HatchedClient.health()

health()

Health check; returns API status metadata.

HatchedClient.getRateLimitInfo()

getRateLimitInfo()

Latest X-RateLimit-* snapshot from the most recent response.

HatchedClient.getLastRequestId()

getLastRequestId(): string | null

Request id of the most recent response (for support correlation).

EggsResource

EggsResource.create()

create(params: CreateEggParams, signal?: AbortSignal): Promise<Egg>

Creates a new pending egg bound to an external user. New eggs start in waiting; call updateStatus(eggId, 'ready') before hatch(). Pass ensure: true during a first-run bootstrap to reuse the user's existing waiting/ready egg instead of creating one.

@example

const egg = await hatched.eggs.create({ userId: 'user_42' });
await hatched.eggs.updateStatus(egg.eggId, 'ready');

EggsResource.get()

get(eggId: string, signal?: AbortSignal): Promise<Egg>

Fetches the canonical state of a single egg.

EggsResource.list()

list(params: ListEggsParams = {}): Promise<Egg[]>

Lists eggs with optional filters.

EggsResource.updateStatus()

updateStatus(eggId: string, status: 'ready' | 'cancelled', signal?: AbortSignal): Promise<EggStatusChange>

Transitions an egg to ready or cancelled. The API only permits ready and cancelled terminal statuses via this endpoint.

EggsResource.hatch()

hatch(eggId: string, signal?: AbortSignal): Promise<HatchResult>

Kicks off an async hatch operation. Poll the returned operationId via operations.wait() to resolve when the buddy art is ready. The egg must already be in ready status.

BuddiesResource

BuddiesResource.get()

get(buddyId: string, signal?: AbortSignal): Promise<Buddy>

Fetches a buddy by id.

BuddiesResource.list()

list(params: BuddyListParams = {}): Promise<BuddyList>

Lists buddies with optional filters.

BuddiesResource.updateName()

updateName(buddyId: string, name: string, signal?: AbortSignal): Promise<Buddy>

BuddiesResource.archive()

archive(buddyId: string, signal?: AbortSignal): Promise<Buddy>

BuddiesResource.updateSkills()

updateSkills(buddyId: string, updates: SkillUpdate[], signal?: AbortSignal)

BuddiesResource.earn()

earn(buddyId: string, params: EarnCoinsParams, idempotencyKey?: string, signal?: AbortSignal)

Adds coins to a buddy's ledger for a given reason. Alias: BuddiesResource.earnCoins.

BuddiesResource.spend()

spend(buddyId: string, params: SpendCoinsParams, idempotencyKey?: string, signal?: AbortSignal)

Debits coins from a buddy's ledger. Fails with InsufficientBalanceError if the buddy doesn't have enough.

BuddiesResource.awardBadge()

awardBadge(buddyId: string, badgeKey: string, reason?: string, signal?: AbortSignal)

BuddiesResource.getBadges()

getBadges(buddyId: string, signal?: AbortSignal)

BuddiesResource.equip()

equip(buddyId: string, params: EquipItemsParams, signal?: AbortSignal): Promise<EquipItemsResult>

Equips or unequips items on a buddy.

BuddiesResource.rerenderAppearance()

rerenderAppearance(buddyId: string, signal?: AbortSignal): Promise<RerenderAppearanceResult>

Regenerate the buddy's bare stage base image. Use after a hard generation failure or when appearance.status === 'failed' with code: 'needs_rerender'. Equipped items are removed from the rendered set; re-equip after the appearance returns to ready.

BuddiesResource.purchaseItem()

purchaseItem(buddyId: string, itemId: string, idempotencyKey?: string, signal?: AbortSignal)

BuddiesResource.getPurchasedItems()

getPurchasedItems(buddyId: string, signal?: AbortSignal)

BuddiesResource.getEvolution()

getEvolution(buddyId: string, signal?: AbortSignal)

BuddiesResource.evolve()

evolve(buddyId: string, signal?: AbortSignal)

Starts the async operation that advances a ready buddy to its next evolution stage. Use after events.send() returns effects.evolutionReady === true when auto-evolve is disabled.

BuddiesResource.getProgression()

getProgression(buddyId: string, signal?: AbortSignal)

BuddiesResource.tokens()

tokens(buddyId: string, signal?: AbortSignal): Promise<TokensSummary>

Typed token balances for a buddy, grouped into primary (spendable) and progression (accumulate-only). Returns null for either slot if the customer has not configured that kind.

BuddiesResource.evolutions()

evolutions(buddyId: string, params: { page?: number; limit?: number; signal?: AbortSignal } = {}): Promise<{
    data: BuddyEvolutionRecord[];
    pagination: { page: number; limit: number; total: number };
  }>

Paginated stage-transition timeline for a buddy (includes both prod and demo evolutions).

BuddiesResource.getUserSummary()

getUserSummary(userId: string, signal?: AbortSignal)

EventsResource

EventsResource.send()

send(params: SendEventParams, signal?: AbortSignal): Promise<EventEffects>

Ingests a domain event. The same eventId returning twice yields the cached effect without re-applying rules.

@example

const effects = await hatched.events.send({
  eventId: 'lesson_lsn_42_user_123',
  userId: 'user_123',
  type: 'lesson_completed',
  properties: { score: 94 },
});

EventsResource.sendBatch()

sendBatch(events: SendEventParams[], signal?: AbortSignal): Promise<{ results: EventEffects[] }>

Sends a batch of events in a single call.

OperationsResource

OperationsResource.get()

get(operationId: string, signal?: AbortSignal): Promise<Operation<TResult>>

Fetches an operation's current status.

OperationsResource.wait()

wait(operationId: string, options: WaitOptions = {}): Promise<Operation<TResult>>

Polls an operation until it reaches completed or failed.

@throws Error if the operation doesn't finish before timeoutMs elapses. @example

await hatched.eggs.updateStatus(egg.eggId, 'ready');
const op = await hatched.eggs.hatch(egg.eggId);
const finished = await hatched.operations.wait(op.operationId);

OperationsResource.waitForCompletion()

waitForCompletion(operationId: string, options: { timeout?: number; interval?: number; signal?: AbortSignal } = {}): Promise<Operation<TResult>>

@deprecated Use OperationsResource.wait instead.

WidgetSessionsResource

WidgetSessionsResource.create()

create(params: CreateSessionParams, signal?: AbortSignal): Promise<SessionToken>

Mints a short-lived widget session token for browser/interactive widgets. Never ship a secret API key to the browser — always go through this endpoint.

WidgetSessionsResource.revoke()

revoke(sessionId: string, signal?: AbortSignal): Promise<void>

EmbedTokensResource

EmbedTokensResource.create()

create(params: CreateEmbedTokenParams, signal?: AbortSignal): Promise<EmbedToken>

Mints a signed token for a read-only embedded widget.

WebhooksResource

WebhooksResource.list()

list(signal?: AbortSignal): Promise<WebhookEndpoint[]>

Lists webhook endpoints registered for the current customer.

WebhooksResource.create()

create(params: CreateWebhookParams, signal?: AbortSignal): Promise<WebhookEndpoint>

Registers a new webhook endpoint.

WebhooksResource.delete()

delete(endpointId: string, signal?: AbortSignal): Promise<void>

Deletes a webhook endpoint.

WebhooksResource.deliveries()

deliveries(params: ListDeliveriesParams): Promise<Page<WebhookDelivery>>

Lists recent deliveries for a given endpoint.

WebhooksResource.replay()

replay(endpointId: string, deliveryId: string, signal?: AbortSignal): Promise<unknown>

Replays a specific delivery attempt.

WebhooksResource.redeliver()

redeliver(endpointId: string, deliveryId: string, signal?: AbortSignal): Promise<unknown>

Re-enqueues a stored webhook delivery.

WebhooksResource.verifySignature()

static verifySignature(rawBody: string | Buffer, signatureHeader: string, secret: string, options: VerifySignatureOptions = {}): boolean

Verifies the Hatched-Signature header for a webhook payload.

The signature format is t=<unix_ts>,v1=<hmac_sha256_hex>. Pass the raw request body bytes (not the parsed JSON) — any reformatting will invalidate the signature.

@example

const valid = WebhooksResource.verifySignature(rawBody, header, process.env.HATCHED_WEBHOOK_SECRET!);
if (!valid) return new Response('invalid signature', { status: 400 });

HatchedError

Base class for every error raised by the Hatched SDK. Every subclass carries the HTTP status, stable error code, optional details payload, and the request id the API echoed back for support correlation.

No public methods.

AuthError

Shared base for 401/403 responses.

No public methods.

UnauthorizedError

No public methods.

ForbiddenError

No public methods.

PublishableKeyScopeError

Raised when a request uses a publishable key for an operation the publishable key is not scoped for (e.g. mutation endpoints).

No public methods.

NotFoundError

No public methods.

ValidationError

No public methods.

RateLimitError

No public methods.

InsufficientBalanceError

No public methods.

TooManyItemsError

Raised when an equip request asks the buddy to wear more items than the image compositing pipeline can reliably render. The current cap is four — the SDK surfaces max and attempted on details so callers can show a precise error to the end-user.

No public methods.

CategoryConflictError

Raised when an equip request tries to put two items in the same category slot (e.g. two head items). Only the accessory category allows stacking.

No public methods.

ConflictError

No public methods.

ConfigVersionMismatchError

Raised when a buddy is pinned to a config version that does not match the one the caller expected (e.g. after a migration race).

No public methods.

NoPublishedConfigError

Raised by POST /eggs (and the bootstrap flow) when the customer has not published a config version yet. details.publish_url points at the dashboard publish page.

No public methods.

ActiveEggLimitError

Raised when POST /eggs would exceed the per-user active-egg cap. details.active lists the existing eggs (id + status) so you can hatch or cancel one — or retry the create with ?ensure=true to reuse one.

No public methods.

UpstreamImageError

No public methods.

CreditInsufficientError

Raised when an AI / generative request cannot be authorised because the customer has no available credits across any pool. The details object includes the amount required and what remains in each pool, plus a URL the caller can redirect to so the end-customer can top up.

No public methods.

EventQuotaExceededError

Raised when a POST /events call would push the customer over the monthly event quota allowed by their plan. reset_at is an ISO timestamp for the first of the next UTC month; callers should back off until then or upgrade.

No public methods.

PlanFeatureLockedError

Raised when the customer's plan does not include the requested feature (e.g. a Free tier customer trying to use the marketplace API). The SDK surfaces which plan is required so callers can prompt an upgrade.

No public methods.

GatesResource

Generic spend-to-unlock primitive. Customers define gates in their dashboard (gate_key, token_key, cost, metadata). A buddy calls unlock to spend the configured token cost and flip the gate open — idempotent: repeat calls return alreadyUnlocked: true without touching the economy.

GatesResource.list()

list(signal?: AbortSignal): Promise<{ gates: TokenGate[] }>

Lists gates configured on this customer. Secret-key only.

GatesResource.unlock()

unlock(buddyId: string, gateKey: string, signal?: AbortSignal): Promise<UnlockResult>

Buddy spends gate.cost of gate.tokenKey to unlock gateKey. Fails with InsufficientBalanceError if the buddy lacks tokens and with ValidationError('progression_not_spendable') if the gate references a progression token.

GatesResource.unlocks()

unlocks(buddyId: string, signal?: AbortSignal): Promise<{ unlocks: BuddyUnlock[] }>

List gates a buddy has unlocked.

PathsResource

Guided journey primitive — a path is an ordered list of steps; each step holds an ordered list of sub-steps with an optional completion condition. Sub-step completions advance the buddy through the path automatically (rule-engine) or manually via completeSubStep.

The HttpClient auto-converts wire snake_case → camelCase on every response, so resource methods read camelCase fields directly without an intermediate DTO mapping layer.

PathsResource.list()

list(audience?: string, signal?: AbortSignal): Promise<PathDefinition[]>

PathsResource.get()

get(definitionId: string, signal?: AbortSignal): Promise<PathDefinitionWithSteps>

PathsResource.create()

create(params: CreatePathDefinitionParams, signal?: AbortSignal): Promise<PathDefinition>

PathsResource.update()

update(definitionId: string, params: UpdatePathDefinitionParams, signal?: AbortSignal): Promise<PathDefinition>

PathsResource.delete()

delete(definitionId: string, signal?: AbortSignal): Promise<void>

PathsResource.setActive()

setActive(definitionId: string, isActive: boolean, signal?: AbortSignal): Promise<PathDefinition>

Atomic single-active activation: deactivates every other path on the same (customer, audience) in a single transaction.

PathsResource.addStep()

addStep(definitionId: string, params: CreatePathStepParams, signal?: AbortSignal): Promise<PathStep>

PathsResource.updateStep()

updateStep(definitionId: string, stepId: string, params: UpdatePathStepParams, signal?: AbortSignal): Promise<PathStep>

PathsResource.deleteStep()

deleteStep(definitionId: string, stepId: string, signal?: AbortSignal): Promise<void>

PathsResource.reorderSteps()

reorderSteps(definitionId: string, ordering: Array<{ id: string; ordinal: number }>, signal?: AbortSignal): Promise<PathStep[]>

PathsResource.addSubStep()

addSubStep(definitionId: string, stepId: string, params: CreatePathSubStepParams, signal?: AbortSignal): Promise<PathSubStep>

PathsResource.updateSubStep()

updateSubStep(definitionId: string, stepId: string, subStepId: string, params: UpdatePathSubStepParams, signal?: AbortSignal): Promise<PathSubStep>

PathsResource.deleteSubStep()

deleteSubStep(definitionId: string, stepId: string, subStepId: string, signal?: AbortSignal): Promise<void>

PathsResource.reorderSubSteps()

reorderSubSteps(definitionId: string, stepId: string, ordering: Array<{ id: string; ordinal: number }>, signal?: AbortSignal): Promise<PathSubStep[]>

PathsResource.getForBuddy()

getForBuddy(buddyId: string, pathKey: string, signal?: AbortSignal): Promise<PathRuntimePayload>

PathsResource.completeSubStep()

completeSubStep(buddyId: string, pathKey: string, subStepKey: string, signal?: AbortSignal): Promise<ManualCompleteResult>

Manually mark a sub-step complete. Idempotent on (buddy, sub-step). Returns cascade flags so callers can paint celebrations without an extra round-trip.

Types

NoPublishedConfigDetails

export interface NoPublishedConfigDetails {
  customerId?: string;
  customer_id?: string;
  publishUrl?: string;
  publish_url?: string;
  docsUrl?: string;
  docs_url?: string;
}

ActiveEggLimitEgg

export interface ActiveEggLimitEgg {
  eggId: string;
  status: string;
  createdAt: string;
}

ActiveEggLimitDetails

export interface ActiveEggLimitDetails {
  max?: number;
  active?: ActiveEggLimitWireEgg[];
}

CreditInsufficientDetails

export interface CreditInsufficientDetails {
  required?: number;
  available?: number;
  welcome?: number;
  paid?: number;
  promo?: number;
  upgrade_url?: string;
  top_up_url?: string;
}

EventQuotaExceededDetails

export interface EventQuotaExceededDetails {
  used?: number;
  limit?: number;
  reset_at?: string;
  upgrade_url?: string;
}

PlanFeatureLockedDetails

export interface PlanFeatureLockedDetails {
  feature?: string;
  required_plan?: string;
  current_plan?: string;
  upgrade_url?: string;
}

EggStatus

export type EggStatus = 'waiting' | 'ready' | 'hatching' | 'hatched' | 'cancelled';

CreateEggParams

export interface CreateEggParams {
  /** The external user id that owns the egg. */
  userId: string;
  /** Free-form metadata attached to the egg. */
  metadata?: Record<string, unknown>;
  /**
   * When true, return the user's most recent `waiting`/`ready` egg if one
   * already exists instead of creating a new one (idempotent first-run
   * bootstrap; avoids hitting the per-user active-egg cap on retries).
   */
  ensure?: boolean;
}

Egg

export interface Egg {
  eggId: string;
  userId: string;
  status: EggStatus;
  visualVariant: number;
  configVersionId: string;
  /** The buddy hatched from this egg. Non-null once `status === 'hatched'`. */
  buddyId: string | null;
  metadata: Record<string, unknown>;
  createdAt: string;
}

EggStatusChange

export interface EggStatusChange {
  eggId: string;
  status: EggStatus;
  previousStatus: EggStatus;
}

HatchResult

export interface HatchResult {
  operationId: string;
  status: string;
}

ListEggsParams

export interface ListEggsParams {
  userId?: string;
  status?: EggStatus;
  page?: number;
  limit?: number;
  signal?: AbortSignal;
}

Buddy

export interface Buddy {
  id: string;
  customerId: string;
  userId: string;
  audience: string;
  name: string;
  configVersionId: string;
  evolutionStage: number;
  coins: number;
  status: 'active' | 'archived';
  skills: Record<string, number>;
  tokens: Record<string, number>;
  progression?: BuddyProgression;
  imageUrl: string | null;
  baseImageUrl: string | null;
  thumbUrl: string | null;
  equippedItems: BuddyEquippedItem[];
  appearance?: BuddyAppearance;
  createdAt: string;
  updatedAt: string;
}

BuddyProgression

export interface BuddyProgression {
  /** Player-facing XP. Currently maps to totalSkillLevel. */
  xp: number;
  totalSkillLevel: number;
  badgeCount: number;
  itemCount: number;
  currentStreak: number;
  longestStreak: number;
  customCounters: Record<string, number>;
}

BuddyEquippedItem

export interface BuddyEquippedItem {
  itemId: string;
  name: string;
  imageUrl: string | null;
}

BuddyAppearanceStatus

export type BuddyAppearanceStatus = 'ready' | 'pending' | 'awaiting_credits' | 'failed';

BuddyAppearance

export interface BuddyAppearance {
  status: BuddyAppearanceStatus;
  operationId: string | null;
  desiredEquippedItemIds: string[];
  renderedEquippedItemIds: string[];
  retryable: boolean;
  message: string | null;
  error: Record<string, unknown> | null;
}

BuddyListParams

export interface BuddyListParams {
  userId?: string;
  status?: string;
  evolutionStage?: number;
  page?: number;
  limit?: number;
  sort?: string;
  order?: 'asc' | 'desc';
  signal?: AbortSignal;
}

SkillUpdate

export interface SkillUpdate {
  key: string;
  action: 'increase' | 'decrease' | 'set';
  amount?: number;
  value?: number;
}

EarnCoinsParams

export interface EarnCoinsParams {
  amount: number;
  reason: string;
  referenceId?: string;
  /**
   * Token key to earn. Defaults to the customer's `primary` token. Passing
   * a progression token grants progress; passing any other configured token
   * key is accepted by the rule engine. Omit to earn the default coin / primary.
   */
  token?: string;
}

SpendCoinsParams

export interface SpendCoinsParams {
  amount: number;
  reason: string;
  itemId?: string;
  /**
   * Token key to spend. Defaults to the customer's `primary` token. Spending
   * a progression token fails with ValidationError('progression_not_spendable').
   */
  token?: string;
}

TokenBalance

export interface TokenBalance {
  /** Canonical `primary` or `progression` identifier. */
  kind: 'primary' | 'progression';
  /** Customer-defined token key (e.g. `gems`, `xp`). */
  key: string;
  /** Human-readable label for display. */
  label: string;
  /** Current balance. */
  balance: number;
  /** Lifetime earned (earn ledger sum). */
  lifetimeEarned: number;
  /** Lifetime spent (spend ledger sum) — always 0 for progression. */
  lifetimeSpent: number;
}

TokensSummary

export interface TokensSummary {
  primary: TokenBalance | null;
  progression: TokenBalance | null;
}

BuddyEvolutionRecord

export interface BuddyEvolutionRecord {
  id: string;
  buddyId: string;
  fromStage: number;
  toStage: number;
  triggeredByEventId: string | null;
  imageUrl: string | null;
  source: 'prod' | 'demo' | 'auto';
  metadata: Record<string, unknown>;
  occurredAt: string;
}

EquipItemsParams

export interface EquipItemsParams {
  equip?: string[];
  unequip?: string[];
}

EquipItemsResult

export interface EquipItemsResult {
  accepted: boolean;
  operationId: string | null;
  status: 'pending' | 'completed' | string;
  appearanceStatus: BuddyAppearanceStatus | string;
  cached: boolean;
}

RerenderAppearanceResult

export interface RerenderAppearanceResult {
  accepted: boolean;
  operationId: string;
  status: 'pending' | string;
  appearanceStatus: BuddyAppearanceStatus | string;
}

BuddyList

export interface BuddyList {
  data: Buddy[];
  meta: { total: number; page: number; limit: number };
}

SendEventParams

export interface SendEventParams {
  /** Stable id used for idempotency. Re-sending the same eventId is a no-op. */
  eventId: string;
  /** External user id the event belongs to. */
  userId: string;
  /** Event type (e.g. `lesson_completed`, `workout_finished`). */
  type: string;
  /**
   * Audience (role) this event belongs to. Required for customers with 2+
   * audiences; omit for single-audience customers and the server applies
   * the implicit default. Lowercase, snake_case, max 32 chars.
   */
  audience?: string;
  /** When the event occurred. Defaults to "now" server-side if omitted. */
  occurredAt?: Date | string;
  /** Arbitrary key-value payload forwarded to the rule engine. */
  properties?: Record<string, unknown>;
}

EventStreakUpdate

Per-streak progression entry returned alongside coin/badge effects when a tracked event advances a streak. The HTTP client deep-converts snake_case → camelCase, so SDK consumers see camelCase keys here.

export interface EventStreakUpdate {
  definitionKey: string;
  label: string;
  icon: string;
  current: number;
  longest: number;
  milestoneHit: number | null;
  hero: boolean;
}

EventPathSubStepCompletion

Per-path completion delta produced when a tracked event closes a sub-step.

export interface EventPathSubStepCompletion {
  pathKey: string;
  stepKey: string;
  subStepKey: string;
  rewardCoins: number;
  rewardBadgeKey: string | null;
}

EventPathStepCompletion

export interface EventPathStepCompletion {
  pathKey: string;
  stepKey: string;
  rewardCoins: number;
  rewardBadgeKey: string | null;
}

EventPathCompletion

export interface EventPathCompletion {
  pathKey: string;
}

EventPathUpdate

export interface EventPathUpdate {
  pathKey: string;
  subStepCompleted?: EventPathSubStepCompletion;
  stepCompleted?: EventPathStepCompletion;
  pathCompleted?: EventPathCompletion;
}

EventEffects

export interface EventEffects {
  coins?: number;
  badgesAwarded?: string[];
  badgesReady?: string[];
  tokens?: string[];
  /**
   * True when the buddy has met the next evolution condition. If the
   * customer's config does not auto-evolve, call `buddies.evolve(buddyId)`
   * server-side and wait on the returned operation.
   */
  evolutionReady?: boolean;
  streakMilestones?: number[];
  /** Per-streak deltas (current/longest, milestone hits) for active streaks. */
  streakUpdates?: EventStreakUpdate[];
  /**
   * Path widget reconciliation deltas. Each entry covers one sub-step
   * completion plus optional step / path roll-up flags so the host page
   * can paint celebrations without an extra round-trip.
   */
  pathUpdates?: EventPathUpdate[];
}

OperationStatus

export type OperationStatus = 'pending' | 'processing' | 'completed' | 'failed';

Operation

export interface Operation<TResult = unknown> {
  operationId: string;
  /** Alias for {@link Operation.operationId} for callers that prefer `id`. */
  id: string;
  type: string;
  status: OperationStatus;
  result?: TResult;
  error?: string;
  createdAt: string;
  updatedAt: string;
}

WaitOptions

export interface WaitOptions {
  /** Maximum total time to wait, in milliseconds. Default 30_000. */
  timeoutMs?: number;
  /** Poll interval, in milliseconds. Default 2000. */
  intervalMs?: number;
  /** External abort signal. */
  signal?: AbortSignal;
}

CreateSessionParams

export interface CreateSessionParams {
  buddyId: string;
  userId: string;
  scopes: string[];
  ttlSeconds?: number;
}

SessionToken

export interface SessionToken {
  token: string;
  sessionId: string;
  expiresAt: string;
  scopes: string[];
}

CreateEmbedTokenParams

export interface CreateEmbedTokenParams {
  buddyId: string;
  userId: string;
  ttlSeconds?: number;
}

EmbedToken

export interface EmbedToken {
  token: string;
  expiresAt: string;
  mode: 'read-only';
}

WebhookEndpoint

export interface WebhookEndpoint {
  id: string;
  url: string;
  events: string[];
  active: boolean;
  status: 'active' | 'paused';
  secret?: string;
  maskedSecret?: string;
  createdAt: string;
  updatedAt: string;
}

CreateWebhookParams

export interface CreateWebhookParams {
  url: string;
  events: string[];
  description?: string;
}

WebhookDelivery

export interface WebhookDelivery {
  id: string;
  endpointId?: string;
  event: string;
  eventType: string;
  status: 'pending' | 'success' | 'succeeded' | 'failed';
  responseCode?: number | null;
  responseStatus?: number | null;
  attempt: number;
  attempts: number;
  durationMs?: number | null;
  errorMessage?: string | null;
  createdAt: string;
  timestamp: string;
  lastAttemptAt?: string;
}

ListDeliveriesParams

export interface ListDeliveriesParams {
  endpointId: string;
  status?: 'pending' | 'success' | 'failed';
  cursor?: string;
  limit?: number;
  signal?: AbortSignal;
}

Page

export interface Page<T> {
  data: T[];
  nextCursor: string | null;
}

VerifySignatureOptions

export interface VerifySignatureOptions {
  /** Maximum clock-skew in seconds. Defaults to 5 minutes. */
  toleranceSeconds?: number;
  /** Clock used for timestamp validation — useful in tests. */
  now?: () => number;
}

TokenGate

export interface TokenGate {
  id: string;
  gateKey: string;
  tokenKey: string;
  cost: number;
  label: string | null;
  description: string | null;
  metadata: Record<string, unknown>;
  isActive: boolean;
  createdAt: string;
  updatedAt: string;
}

UnlockResult

export interface UnlockResult {
  gateKey: string;
  unlocked: true;
  alreadyUnlocked: boolean;
  unlockedAt: string;
  balanceAfter: number | null;
  metadata: Record<string, unknown>;
}

BuddyUnlock

export interface BuddyUnlock {
  gateKey: string;
  unlockedAt: string;
  metadata: Record<string, unknown>;
}

PathDisplayMode

export type PathDisplayMode = 'straight' | 'zigzag' | 'stepper';

PathIcon

export type PathIcon = 'path' | 'flame' | 'heart' | 'bolt' | 'star' | 'leaf';

PathConditionType

export type PathConditionType =
  | 'event_count'
  | 'milestone'
  | 'streak'
  | 'skill_level'
  | 'collection'
  | 'evolution'
  | 'coin'
  | 'badge_earned'
  | 'gate_unlocked'
  | 'custom';

PathCondition

export interface PathCondition {
  type: PathConditionType;
  config: Record<string, unknown>;
}

PathDefinition

export interface PathDefinition {
  id: string;
  customerId: string;
  audience: string;
  key: string;
  label: string;
  description: string | null;
  icon: PathIcon;
  accentColor: string | null;
  displayMode: PathDisplayMode;
  isActive: boolean;
  createdAt: string;
  updatedAt: string;
}

PathStep

export interface PathStep {
  id: string;
  pathDefinitionId: string;
  key: string;
  label: string;
  description: string | null;
  icon: string | null;
  ordinal: number;
  unlockCondition: Record<string, unknown> | null;
  completionCondition: PathCondition | null;
  rewardCoins: number;
  rewardBadgeKey: string | null;
  isActive: boolean;
  createdAt: string;
  updatedAt: string;
}

PathSubStep

export interface PathSubStep {
  id: string;
  pathStepId: string;
  key: string;
  label: string;
  description: string | null;
  ordinal: number;
  completionCondition: PathCondition | null;
  allowManualComplete: boolean;
  allowSkipAhead: boolean;
  rewardCoins: number;
  rewardBadgeKey: string | null;
  contentUrl: string | null;
  ctaLabel: string | null;
  isActive: boolean;
  createdAt: string;
  updatedAt: string;
}

PathSubStepStatus

export type PathSubStepStatus = 'locked' | 'available' | 'completed';

PathSubStepRuntime

export interface PathSubStepRuntime {
  id: string;
  key: string;
  label: string;
  description: string | null;
  ordinal: number;
  rewardCoins: number;
  rewardBadgeKey: string | null;
  contentUrl: string | null;
  ctaLabel: string | null;
  allowManualComplete: boolean;
  allowSkipAhead: boolean;
  isActive: boolean;
  status: PathSubStepStatus;
  completedAt: string | null;
}

PathStepRuntime

export interface PathStepRuntime {
  id: string;
  key: string;
  label: string;
  description: string | null;
  icon: string | null;
  ordinal: number;
  rewardCoins: number;
  rewardBadgeKey: string | null;
  isActive: boolean;
  unlocked: boolean;
  completed: boolean;
  subSteps: PathSubStepRuntime[];
}

PathRuntimePayload

export interface PathRuntimePayload {
  definition: {
    key: string;
    label: string;
    description: string | null;
    icon: PathIcon;
    accentColor: string | null;
    displayMode: PathDisplayMode;
  };
  steps: PathStepRuntime[];
  currentStepKey: string | null;
  completed: boolean;
  completedAt: string | null;
}

CreatePathDefinitionParams

export interface CreatePathDefinitionParams {
  audience?: string;
  key: string;
  label: string;
  description?: string;
  icon?: PathIcon;
  accentColor?: string;
  displayMode?: PathDisplayMode;
  isActive?: boolean;
}

UpdatePathDefinitionParams

export type UpdatePathDefinitionParams = Partial<CreatePathDefinitionParams>;

CreatePathStepParams

export interface CreatePathStepParams {
  key: string;
  label: string;
  description?: string;
  icon?: string;
  ordinal: number;
  unlockCondition?: Record<string, unknown>;
  completionCondition?: PathCondition;
  rewardCoins?: number;
  rewardBadgeKey?: string;
  isActive?: boolean;
}

UpdatePathStepParams

export type UpdatePathStepParams = Partial<CreatePathStepParams>;

CreatePathSubStepParams

export interface CreatePathSubStepParams {
  key: string;
  label: string;
  description?: string;
  ordinal: number;
  completionCondition?: PathCondition;
  allowManualComplete?: boolean;
  allowSkipAhead?: boolean;
  rewardCoins?: number;
  rewardBadgeKey?: string;
  contentUrl?: string;
  ctaLabel?: string;
  isActive?: boolean;
}

UpdatePathSubStepParams

export type UpdatePathSubStepParams = Partial<CreatePathSubStepParams>;

ManualCompleteResult

export interface ManualCompleteResult {
  alreadyCompleted: boolean;
  subStepKey: string;
  stepKey: string;
  stepCompleted: boolean;
  pathCompleted: boolean;
  rewardCoins: number;
  rewardBadgeKey: string | null;
}

On this page

HatchedClientHatchedClient.health()HatchedClient.getRateLimitInfo()HatchedClient.getLastRequestId()EggsResourceEggsResource.create()EggsResource.get()EggsResource.list()EggsResource.updateStatus()EggsResource.hatch()BuddiesResourceBuddiesResource.get()BuddiesResource.list()BuddiesResource.updateName()BuddiesResource.archive()BuddiesResource.updateSkills()BuddiesResource.earn()BuddiesResource.spend()BuddiesResource.awardBadge()BuddiesResource.getBadges()BuddiesResource.equip()BuddiesResource.rerenderAppearance()BuddiesResource.purchaseItem()BuddiesResource.getPurchasedItems()BuddiesResource.getEvolution()BuddiesResource.evolve()BuddiesResource.getProgression()BuddiesResource.tokens()BuddiesResource.evolutions()BuddiesResource.getUserSummary()EventsResourceEventsResource.send()EventsResource.sendBatch()OperationsResourceOperationsResource.get()OperationsResource.wait()OperationsResource.waitForCompletion()WidgetSessionsResourceWidgetSessionsResource.create()WidgetSessionsResource.revoke()EmbedTokensResourceEmbedTokensResource.create()WebhooksResourceWebhooksResource.list()WebhooksResource.create()WebhooksResource.delete()WebhooksResource.deliveries()WebhooksResource.replay()WebhooksResource.redeliver()WebhooksResource.verifySignature()HatchedErrorAuthErrorUnauthorizedErrorForbiddenErrorPublishableKeyScopeErrorNotFoundErrorValidationErrorRateLimitErrorInsufficientBalanceErrorTooManyItemsErrorCategoryConflictErrorConflictErrorConfigVersionMismatchErrorNoPublishedConfigErrorActiveEggLimitErrorUpstreamImageErrorCreditInsufficientErrorEventQuotaExceededErrorPlanFeatureLockedErrorGatesResourceGatesResource.list()GatesResource.unlock()GatesResource.unlocks()PathsResourcePathsResource.list()PathsResource.get()PathsResource.create()PathsResource.update()PathsResource.delete()PathsResource.setActive()PathsResource.addStep()PathsResource.updateStep()PathsResource.deleteStep()PathsResource.reorderSteps()PathsResource.addSubStep()PathsResource.updateSubStep()PathsResource.deleteSubStep()PathsResource.reorderSubSteps()PathsResource.getForBuddy()PathsResource.completeSubStep()TypesNoPublishedConfigDetailsActiveEggLimitEggActiveEggLimitDetailsCreditInsufficientDetailsEventQuotaExceededDetailsPlanFeatureLockedDetailsEggStatusCreateEggParamsEggEggStatusChangeHatchResultListEggsParamsBuddyBuddyProgressionBuddyEquippedItemBuddyAppearanceStatusBuddyAppearanceBuddyListParamsSkillUpdateEarnCoinsParamsSpendCoinsParamsTokenBalanceTokensSummaryBuddyEvolutionRecordEquipItemsParamsEquipItemsResultRerenderAppearanceResultBuddyListSendEventParamsEventStreakUpdateEventPathSubStepCompletionEventPathStepCompletionEventPathCompletionEventPathUpdateEventEffectsOperationStatusOperationWaitOptionsCreateSessionParamsSessionTokenCreateEmbedTokenParamsEmbedTokenWebhookEndpointCreateWebhookParamsWebhookDeliveryListDeliveriesParamsPageVerifySignatureOptionsTokenGateUnlockResultBuddyUnlockPathDisplayModePathIconPathConditionTypePathConditionPathDefinitionPathStepPathSubStepPathSubStepStatusPathSubStepRuntimePathStepRuntimePathRuntimePayloadCreatePathDefinitionParamsUpdatePathDefinitionParamsCreatePathStepParamsUpdatePathStepParamsCreatePathSubStepParamsUpdatePathSubStepParamsManualCompleteResultRelated