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.
Quick links
- Swagger UI — browseable reference with a try-it-out form on every endpoint.
- Raw OpenAPI 3.0 spec — feed to SDK generators (
openapi-typescript,oapi-codegen) or to LLM crawlers. - Personal Access Tokens — bearer credentials for programmatic access (PRO+ plans).
- Outbound webhooks — receive signed POSTs when workspace events fire.
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.
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:
X-RateLimit-Limit: 1000X-RateLimit-Remaining: 994X-RateLimit-Reset: 1717250060Retry-After: 30 # only on 429A 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.
// 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.
| Parameter | Default | Notes |
|---|---|---|
page | 1 | 1-indexed. |
limit | 20 | Capped at 100. |
sortBy | endpoint-specific | Field name; per-endpoint allowlist. Unknown values fall back to the endpoint default. |
sortOrder | desc | asc or desc. |
search | — | Full-text match where supported; capped at 200 chars. |
{ "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 CUIDs —
clx0123456789abcdefghij-shape strings. They appear in every URL path (/api/workspaces/:workspaceId/projects/:projectId/issues/:issueId) and as theidfield on every entity. There is no public slug-to-CUID lookup — fetchGET /api/workspacesfirst 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:
npm install @hiveship/sdkFor 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.
# Pythonpip install openapi-python-clientopenapi-python-client generate --url https://hiveship.app/api/openapi.json# Gogo install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@latestoapi-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.