TypeScript SDK
@hiveship/sdk is the official typed TypeScript client for the Hiveship REST API. Every endpoint and response shape is auto-generated from the canonical OpenAPI document — drift between client and server is impossible by construction.
Built on openapi-fetch — ~3 KB runtime, zero dependencies beyond the global fetch. Runs on Node 20+, Cloudflare Workers, Deno, Bun, and modern browsers.
Install
npm install @hiveship/sdkQuick start
The simplest call — a public liveness check — needs no auth. Production base URL is the default, so a fresh client works out of the box:
import { HiveshipClient } from '@hiveship/sdk';const hiveship = new HiveshipClient();const { data, error, response } = await hiveship.client.GET('/health');if (error) throw new Error(`Health check failed: ${response.status}`);console.log(data); // typed from the OpenAPI response schemaFor workspace-scoped reads / writes, pass a Personal Access Token (or an agent bearer token):
import { HiveshipClient } from '@hiveship/sdk';const hiveship = new HiveshipClient({ token: process.env.HIVESHIP_TOKEN, // hsp_userid_secret});const { data, error } = await hiveship.client.GET( '/workspaces/{workspaceId}/projects/{projectId}/issues', { params: { path: { workspaceId: 'cmpxxx', projectId: 'cmqxxx' }, query: { limit: 20 }, }, },);if (error) { console.error('API error', error); process.exit(1);}for (const issue of data.items) { console.log(`${issue.projectPrefix}-${issue.number}: ${issue.title}`);}Path strings are checked at compile time. A typo (/workspacs/...) or a removed endpoint surfaces as a TypeScript error before runtime. data and error are narrowed by the OpenAPI response schemas — no manual response.ok branching, no manual JSON parsing, no runtime casts.
Authentication
The SDK takes a single bearer-token string. Both PAT and agent formats are accepted:
| Token type | Prefix | Use case |
|---|---|---|
| Personal Access Token | hsp_ | Most third-party integrations. Per-token scopes + rate limits. See PAT docs. |
| Agent bearer token | hsa_ | Agent-side tooling. Capability tier bound to the agent record. See agent docs. |
Public endpoints (/health, /health/ready) work without a token. Workspace-scoped endpoints return 401 if the token is missing or malformed.
Error handling
openapi-fetch returns a { data, error, response } tuple. Non-2xx responses surface on error — there's no thrown exception to catch:
const { data, error, response } = await hiveship.client.POST( '/workspaces/{workspaceId}/projects/{projectId}/issues', { params: { path: { workspaceId, projectId } }, body: { title: 'New issue', delegateType: 'HUMAN' }, },);if (error) { if (response.status === 403) console.log('Forbidden — check your scopes'); else if (response.status === 422) console.log('Validation failed', error); else console.log('Unexpected error', error); return;}console.log(`Created issue ${data.projectPrefix}-${data.number}`);The API returns one of two error envelopes — Zod/custom ({ success: false, error: { code, message, details? } }) or NestJS default ({ message, error, statusCode }). Both are visible on error; branch on response.status for the HTTP code.
Configuration
new HiveshipClient({ token?: string; // Bearer token (PAT or agent). Empty string throws. baseUrl?: string; // Resolution: explicit > HIVESHIP_API_URL env var > public default fetch?: typeof fetch; // Custom fetch (instrumented / mocked / polyfilled)});baseUrl should NOT include a trailing slash. The fetch option threads a custom implementation through every request — useful for tracing, request mocking in tests, or polyfilling on runtimes without a global fetch.
Self-hosted deployments
If you're running Hiveship on your own infrastructure, set HIVESHIP_API_URL once at deploy time:
export HIVESHIP_API_URL=https://hiveship.acme-corp.internal/apiEvery new HiveshipClient({ token }) then routes correctly without touching the constructor surface. Explicit baseUrl still wins over the env var if you need per-call overrides.
Why this matters: without setting either the env var or baseUrl, the SDK defaults to https://hiveship.app/api (the public hosted Hiveship). A self-hosted PAT sent to the hosted host gets a 401 — but the token still traverses a third-party server over the wire. Set HIVESHIP_API_URL to keep credentials inside your perimeter.
Pulling response types directly
The SDK re-exports the generated paths / components / operations type trees so you can write strongly-typed wrappers around the underlying client without duplicating shapes:
import type { paths } from '@hiveship/sdk';type IssueListResponse = paths['/workspaces/{workspaceId}/projects/{projectId}/issues']['get']['responses']['200']['content']['application/json'];// Now you can build typed helpers that compose the SDK:async function listIssueTitles(hiveship: HiveshipClient, wId: string, pId: string) { const { data, error } = await hiveship.client.GET( '/workspaces/{workspaceId}/projects/{projectId}/issues', { params: { path: { workspaceId: wId, projectId: pId } } }, ); if (error) throw error; return data.items.map((i): string => i.title);}Generating your own SDK
The SDK ships a TypeScript client for convenience; the source of truth is the OpenAPI spec itself. If you want a Python, Go, Rust, or other-language client, generate it straight from the live spec — that's what the SDK does internally on every release. See the API overview for the per-language recipes.
Versioning
@hiveship/sdk follows semver. Surface additions on the API (new endpoints, new optional fields) ship as MINOR releases since they don't break existing consumers. Renames or removals ship as MAJOR. The full release history lives in the package's CHANGELOG.
API additions don't always force an SDK release. The SDK only re-publishes when the maintainer refreshes the spec snapshot and pushes a new release tag.