Hiveship REST API

Hiveship exposes a REST API covering every workspace-scoped surface — issues, projects, comments, sprints, members, agents, and the integrations that link them to GitHub. The API is the same one the Hiveship web app uses; what you can do in the dashboard, you can script.

Authentication

Hiveship accepts three credential types. Pick the one that matches your caller — never send more than one on the same request.

Personal Access Token (recommended for scripts + integrations)

A workspace-scoped bearer token with per-entity scopes (read / write × issues / projects / comments). Issued from Workspace settings → API Tokens inside the dashboard.

HTTP requestbash
curl https://hiveship.app/api/workspaces/clx.../projects \
-H "Authorization: Bearer hsp_clu123_abcdef0123456789..."

Tokens carry the issuing workspace ID — a stolen token cannot pivot to another tenant. Full reference →

Cookie session (web app)

First-party callers (the Hiveship web app, the landing app's checkout) authenticate via the hiveship_access HttpOnly cookie set by POST /api/auth/login. The cookie is refreshed silently via /api/auth/refresh when it expires.

Agent bearer token

AI agents working inside a session authenticate with an hsa_* token. Capability tiers (READ / SESSION / WORKSPACE) determine which routes the agent can call. Provisioned via the agent rotation flow inside the dashboard, not via the public API.

Rate limits

  • Global per-IP throttle — 60 requests per minute, applied before authentication. Returns 429 Too Many Requests. This is the only limit on cookie-session and agent-bearer callers — there's no per-cookie or per-agent-token sliding window today.
  • Per-PAT sliding window — adds a token-scoped window on top of the global throttle: 1,000 req/min on PRO + TEAM; 5,000 req/min on ENTERPRISE. PAT-authenticated responses carry the current window state in headers:
Rate-limit response headershttp
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 994
X-RateLimit-Reset: 1717250060
Retry-After: 30 # only on 429

A handful of sensitive endpoints (login, register, password reset, agent token rotation, PAT creation, webhook creation) have a tighter 5 req/min/IP throttle on top of the global limit. These are still IP-keyed, not per-credential.

Response envelope

Successful responses always carry the curated envelope below; error responses come in two shapes depending on the failure path. Defensive SDK code should discriminate on presence of the success key rather than assuming one shape.

Response shapesjson
// Success — any 2xx
{
"success": true,
"data": { ... }
}
// Zod validation failure — 400
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": { "title": ["must be at least 1 char"] }
}
}
// All other errors (401, 403, 404, 409, 429, 500) — NestJS default envelope
{
"message": "Only workspace owners can manage billing",
"error": "Forbidden",
"statusCode": 403
}

Use the HTTP status code as the primary signal; the body's message field (curated or default envelope) is the human-readable cause. Plan-gate failures arrive as 403, plan-limit caps as 403, missing entities as 404, and duplicate-key collisions as 409.

Pagination

List endpoints accept four optional query parameters and return a paginated envelope. Defaults are sensible for one-off scripts; bump limit when you're scraping and adjust sortBy when you need stable ordering across pages.

ParameterDefaultNotes
page11-indexed.
limit20Capped at 100.
sortByendpoint-specificField name; per-endpoint allowlist. Unknown values fall back to the endpoint default.
sortOrderdescasc or desc.
searchFull-text match where supported; capped at 200 chars.
Paginated response shapejson
{
"success": true,
"data": {
"items": [ /* up to `limit` rows */ ],
"meta": {
"page": 1,
"limit": 20,
"total": 137,
"totalPages": 7,
"hasNext": true,
"hasPrev": false
}
}
}

The surface uses page+limit, not cursors. For tables that mutate while you paginate (issues created in real time), fix a sortBy: 'createdAt' and walk pages backwards or filter on createdAt < a known boundary — both avoid the duplicate-row drift that page+limit suffers under concurrent inserts.

Identifiers

Two identifier conventions an integrator needs to know:

  • Workspace, project, issue IDs are CUIDsclx0123456789abcdefghij-shape strings. They appear in every URL path (/api/workspaces/:workspaceId/projects/:projectId/issues/:issueId) and as the id field on every entity. There is no public slug-to-CUID lookup — fetch GET /api/workspaces first to find the workspace you have a slug for.
  • The human issue identifier (e.g. "ENG-247") is composed client-side from project.prefix + "-" + issue.number. The API returns the two parts separately on issue DTOs (and on the project DTO for the prefix); we don't ship a pre-composed string. Build it once at the boundary of your integration if you display issue references back to users.

CORS + browser callers

The API enables CORS only for the first-party origins (the web app, landing app, admin app) with credentials. Browser-side third-party JavaScript cannot call the Hiveship API directly — the preflight OPTIONS request fails on origin mismatch.

PATs are server-side credentials by design. If you need a browser-callable surface (an embedded widget, a customer portal), proxy through your backend. Cookie-session auth is available only to first-party Hiveship surfaces.

Allowed request headers for cross-origin calls (first-party): Content-Type, Authorization, x-workspace-id.

Idempotency

Hiveship does not honor an Idempotency-Key header today. If you retry a failed POST, deduplicate on your side — many endpoints (e.g. POST /comments) will create a second row on the second attempt.

Generating an SDK

For TypeScript, install the official @hiveship/sdk npm package — typed client + auto-generated response shapes, no manual fetch wrapper required:

bash
npm install @hiveship/sdk

For Python, Go, or other languages, the OpenAPI spec at /api/openapi.json is generator-ready. Pin a snapshot to your repo for reproducible builds; regenerate when you bump.

bash
# Python
pip install openapi-python-client
openapi-python-client generate --url https://hiveship.app/api/openapi.json
# Go
go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@latest
oapi-codegen -generate types,client -package hiveship \
https://hiveship.app/api/openapi.json > hiveship.gen.go
# TypeScript without the SDK (types-only, bring your own fetch)
npx openapi-typescript https://hiveship.app/api/openapi.json -o src/hiveship-types.ts

@hiveship/sdk is what we ship from the same spec — the TypeScript path is the best-supported. Pin to a version number, not latest, so a sleeping repo doesn't pick up a breaking change on its next CI run.

Plan requirements

The api-access feature flag is required for both Personal Access Tokens and outbound webhooks. It's enabled on the PRO, TEAM, and ENTERPRISE plans.

If a workspace downgrades to FREE, existing PATs and webhooks keep working — the auth path does not re-check the flag — but new ones cannot be issued. Upgrade the plan from Workspace settings → Billing to restore issuance.