Skip to content

Hebra server API

JSON over HTTP. Everything is under /api/v1, and repository paths under /api/v1/repos/{owner}/{repo} (written … below). This is the API hb and the web hub use; a test keeps this page in step with the server.

Conventions

  • Sign in with Authorization: Bearer <token>: a mandate (hb mandate grant) or a web session.
  • Errors are { "error": { "code": "...", "message": "..." } }, with a stable code.
  • Limits: requests are rate limited per client; 429 says when to retry.
  • Private repositories answer 404 to anyone without access, so their existence is not revealed.
  • Bookmarks move with compare-and-swap: send the value you expect in old, and 409 means someone got there first. Tags are bookmarks under tags/.
  • Revisions in paths and queries are bookmark names or commit ids.

GET /capabilities says what this server offers, so clients can adapt without guessing.

Server

MethodPath
GET/capabilitiesWhat this server offers.
GET/healthAlive.
GET/readyReady for traffic (database reachable).
GET/plansPlans, on Cloud editions.
GET/transparency/keyPublic key that signs transparency logs.

Prometheus metrics are at /metrics, on the separate internal address HEBRA_METRICS_ADDR.

Signing in

MethodPath
POST/auth/githubExchange a GitHub OAuth code for a session.
POST/auth/inviteExchange a one-time invitation for a session.
POST/auth/logoutEnd the session.
POST/auth/deviceStart a device sign-in (hb login).
POST/auth/device/tokenPoll for the mandate of a device sign-in.
GET, POST/auth/device/{code}See and approve a device sign-in.

Accounts

MethodPath
GET/meWho you are.
GET, POST/me/mandatesYour mandates; issue one.
DELETE/me/mandates/{id}Revoke one, and everything derived from it.
POST/orgsCreate an organization.
GET/accounts/{handle}A person, organization or agent.
GET/accounts/{handle}/reposTheir repositories.
GET/accounts/{handle}/membersOrganization members.
PUT, DELETE/accounts/{handle}/members/{member}Add, change or remove one.
GET, POST/accounts/{handle}/teamsTeams.
DELETE/accounts/{handle}/teams/{team}Remove a team.
PUT, DELETE/accounts/{handle}/teams/{team}/members/{member}Team members.
GET, POST/accounts/{handle}/agentsAgent accounts.
DELETE/accounts/{handle}/agents/{agent}Disable an agent.
POST/accounts/{handle}/agents/{agent}/mandatesA mandate for an agent.
GET, POST/accounts/{handle}/runnersRunners.
DELETE/accounts/{handle}/runners/{name}Remove one.

Repositories

MethodPath
GET, POST/reposRepositories you can see; create one.
GET, PATCH, DELETE…Details and bookmarks; settings; delete.
GET…/accessWho has access.
PUT, DELETE…/access/{principal}Grant or revoke it.
POST…/forkFork. Instant: objects are shared.
GET…/eventsRecent events.
GET…/streamLive events (server-sent).
GET…/transparencyThe hash-chained log.

History

MethodPath
GET…/logCommits. ?rev=, ?limit= (500 at most).
GET…/commits/{id}One commit with its diff.
GET…/tree/{id}Files. ?path= for one; ?recursive=true for all names.
GET…/blame/{id}Who wrote each line. ?path=.
GET…/compareWhat head adds to base. ?base=&head=.
GET…/searchText in files, ignoring case. ?q=&rev=. 200 matches at most.

Moving objects

MethodPath
POST…/packObjects for { want, have, filter? }. filter: "blob:none" leaves file contents out.
POST…/objects/getThese exact objects: { ids }. What partial clones read.
POST…/objectsUpload a pack. Objects are verified, and reachable only once a bookmark moves to them.
POST…/bookmarksMove a bookmark: { name, old, new }.

A pack is HBPK1\n, then for each object its 32-byte id, its length as a little-endian u64 and its bytes (<kind>\0<data>). The id is the BLAKE3 hash of the bytes, and it is checked.

Working together

MethodPath
GET, POST…/presenceWho is working on what.
GET, POST…/reviewsReviews; open one.
GET…/reviews/{number}One review.
POST…/reviews/{number}/commentsComment, on a line if you like.
POST…/reviews/{number}/comments/{comment}/resolveResolve a thread.
POST…/reviews/{number}/approveApprove or request changes.
POST…/reviews/{number}/mergeMerge.
POST…/reviews/{number}/closeClose without merging.
GET…/queueThe merge queue.
GET, POST…/tasksTasks; create one.
GET, PATCH…/tasks/{number}One task.
POST…/tasks/{number}/claimTake it for a while.
POST…/tasks/{number}/releaseGive it back.
POST…/tasks/{number}/closeDone or cancelled.
POST…/tasks/{number}/reopenReopen.

Checks and runners

MethodPath
GET…/checksRuns.
POST…/checks/approveLet checks of a contribution run.
POST…/checks/rerunRun them again.
GET…/checks/{id}One run.
GET…/checks/{id}/logIts log.
POST…/checks/{id}/cancelCancel it.
POST/runner/claimA runner asks for work.
POST/runner/runs/{id}/heartbeatRenews the lease.
POST/runner/runs/{id}/logSends log lines.
POST/runner/runs/{id}/completeReports the result.
POST/runner/runs/{id}/agentModel calls of agent verification.
POST/runner/runs/{id}/artifactsA runner uploads a file the run left (?name=, raw body).
GET…/checks/{id}/artifactsFiles a run left.
GET…/checks/{id}/artifacts/{artifact}Download one.
GET…/insightsHeddle: durations, waits, failure and flake rates, time saved by reuse, per check.
GET…/secretsSecret names of the repository, and those it inherits (admins).
PUT, DELETE…/secrets/{secret}Set ({ "value": "..." }) or remove one. Values are sealed and never read back.
GET/accounts/{handle}/secretsSecrets every repository of the account gets.
PUT, DELETE/accounts/{handle}/secrets/{secret}Set or remove one.
POST/accounts/{handle}/runner-tokensA token machines register with: { "labels", "ephemeral", "uses", "ttl_secs" }.
GET/accounts/{handle}/queueQueued runs and runners (busy or idle), for orchestrators.
GET, PUT/accounts/{handle}/fleetHeddle's fleet: provider, settings, machines, decisions, cost. PUT sets { "enabled", "provider", "config", "credentials" }.
POST/accounts/{handle}/fleet/checkTries the provider's credentials and lists its machine types and prices.
POST/accounts/{handle}/fleet/simulateEach policy on the owner's own recent runs, with the fleet's prices.
DELETE/accounts/{handle}/fleet/machines/{id}Stops one machine now.
POST/runner/registerA machine registers itself with a runner token.
DELETE/runner/selfA runner removes itself (ephemeral machines).
POST…/checks/{id}/approveA person approves a deployment waiting for its environment's approvals.
PUT, DELETE…/environments/{env}Set ({ "required_approvals", "branches", "runner_labels", "url" }) or remove one.
GET…/environments/{env}/deploymentsIts deployment history.
GET…/environments/{env}/secretsNames of its secrets.
PUT, DELETE…/environments/{env}/secrets/{secret}Set or remove one; they win over repository and account secrets.

The claim answer carries the run, its secrets (only names the check asks for, never for contributions still waiting for approval) and the artifacts of the checks it needs. A failed run with retries left goes back to the queue.

Releases and webhooks

MethodPath
GET, POST…/releasesReleases; create one on a pushed tag: { "tag", "title", "notes", "draft", "prerelease" }.
GET, PATCH, DELETE…/releases/{tag}One release, with its files.
GET, PUT, POST, DELETE…/releases/{tag}/assets/{asset}Download, upload (raw body) or remove a file.
GET, POST…/webhooksWebhooks; add one: { "url", "secret", "events" } (push, review, task, check, release, or *).
PATCH, DELETE…/webhooks/{id}Switch on or off, change events, remove.
GET…/webhooks/{id}/deliveriesThe last deliveries: status, time, payload.
POST…/webhooks/{id}/pingSends a ping now.

Webhook addresses must be on the public internet unless the server allows private networks (HEBRA_ALLOW_PRIVATE_URLS). Deliveries are POSTs of { "event", "repo", "data", "at" } with X-Hebra-Event, X-Hebra-Delivery and X-Hebra-Signature-256: sha256=<HMAC-SHA256 of the body with the secret>. A failed delivery is tried three times.

Packages

MethodPath
GET/accounts/{handle}/packagesAn owner's npm packages and container images (?kind=npm or container).
GET, PATCH, DELETE/accounts/{handle}/packageOne package (?kind=&name=): versions and tags; { "public", "description" }; delete it or ?version=.

The registries themselves speak their own protocols, outside /api/v1:

  • npm at /npm/: npm publish, npm install, npm dist-tag, npm unpublish, for packages scoped by an account (@acme/ui). Put a mandate in .npmrc as _authToken.
  • Containers at /v2/ (the OCI distribution API): docker login <server> with any user name and a mandate as the password, then docker push <server>/acme/app:1.0. Chunked and monolithic uploads, cross-image mounts, image indexes (multi-platform), tags and _catalog.

Billing

On Cloud editions only.

MethodPath
GET/accounts/{handle}/billingPlan and usage.
POST/accounts/{handle}/billing/checkoutStart a subscription.
POST/accounts/{handle}/billing/portalManage it.
PUT/accounts/{handle}/billing/limitThe spending limit.
POST/billing/stripeStripe webhook.

Edit this page