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

bash
npm install @hiveship/sdk

Available on npm and GitHub.

Quick 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:

typescript
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 schema

For workspace-scoped reads / writes, pass a Personal Access Token (or an agent bearer token):

typescript
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 typePrefixUse case
Personal Access Tokenhsp_Most third-party integrations. Per-token scopes + rate limits. See PAT docs.
Agent bearer tokenhsa_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:

typescript
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

typescript
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:

bash
export HIVESHIP_API_URL=https://hiveship.acme-corp.internal/api

Every 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:

typescript
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.