Base URL
https://api.hee.laAll endpoints are versioned under /v1.
Base URL
https://api.hee.laAll endpoints are versioned under /v1.
Authentication
Send your project token as a bearer header:
Authorization: Bearer hee_…Issue tokens from the portal or POST /v1/portal/projects/{slug}/tokens.
Content type
All request/response bodies are JSON. Send Content-Type: application/json on every POST.
Rate limits
Per-IP limits apply to unauthenticated and auth endpoints. Authenticated control-plane calls are currently uncapped — fair-use applies.
/v1/edge/domainsRegister a customer’s hostname. Idempotent — re-registering the same hostname in the same project returns the existing record with merged metadata.
Body parameters
| Field | Type | Required | Description |
|---|---|---|---|
hostname | string | yes | Fully-qualified domain name to route through Hee. |
metadata | object | no | Opaque JSON blob returned verbatim from /resolve. |
Request
curl -X POST https://api.hee.la/v1/edge/domains \ -H "Authorization: Bearer $HEE_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "hostname": "docs.customer.com", "metadata": { "workspaceId": "ws_abc123" } }'import { HeeClient } from "@heela/sdk";
const hee = new HeeClient({ token: process.env.HEE_TOKEN! });
await hee.domains.register({ hostname: "docs.customer.com", metadata: { workspaceId: "ws_abc123" },});await fetch("https://api.hee.la/v1/edge/domains", { method: "POST", headers: { Authorization: `Bearer ${process.env.HEE_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ hostname: "docs.customer.com", metadata: { workspaceId: "ws_abc123" }, }),});Response 200 OK
{ "hostname": "docs.customer.com", "projectSlug": "acme-saas", "verified": false, "verifiedAt": null, "createdAt": "2026-04-20T21:47:38.000Z", "metadata": { "workspaceId": "ws_abc123" }}Errors
| Status | Meaning |
|---|---|
400 | hostname fails FQDN validation |
402 | project is over its plan limit |
409 | hostname is claimed by another project |
/v1/edge/domainsList every domain owned by the token’s project.
Request
curl https://api.hee.la/v1/edge/domains \ -H "Authorization: Bearer $HEE_TOKEN"const domains = await hee.domains.list();Response 200 OK
[ { "hostname": "docs.customer.com", "projectSlug": "acme-saas", "verified": true, "verifiedAt": "2026-04-20T21:50:12.000Z", "createdAt": "2026-04-20T21:47:38.000Z", "metadata": { "workspaceId": "ws_abc123" } }, { "hostname": "app.customer.com", "projectSlug": "acme-saas", "verified": false, "verifiedAt": null, "createdAt": "2026-04-20T22:10:05.000Z", "metadata": {} }]/v1/edge/domains/{hostname}Soft-delete a domain. Certificate and config are retained briefly so a re-add doesn’t re-trigger issuance rate limits.
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
hostname | string | yes | URL-encoded FQDN to remove. |
Request
curl -X DELETE https://api.hee.la/v1/edge/domains/docs.customer.com \ -H "Authorization: Bearer $HEE_TOKEN"await hee.domains.remove("docs.customer.com");Response 204 No Content
Errors
| Status | Meaning |
|---|---|
404 | hostname is not owned by this project |
/v1/edge/resolveLook up routing metadata for a hostname. Used by upstream apps that need to know which project (and which workspace, tenant, etc.) a request belongs to.
Query parameters
| Field | Type | Required | Description |
|---|---|---|---|
hostname | string | yes | FQDN to resolve, unencoded in the query. |
Request
curl "https://api.hee.la/v1/edge/resolve?hostname=docs.customer.com" \ -H "Authorization: Bearer $HEE_TOKEN"Response 200 OK
{ "hostname": "docs.customer.com", "projectSlug": "acme-saas", "upstreamUrl": "https://acme.pages.dev", "metadata": { "workspaceId": "ws_abc123" }}/v1/auth/request-magic-linkEmail a signed magic-link to the user.
/v1/auth/callbackExchange a magic-link token for a session cookie.
/v1/auth/meReturn the current session’s user record.
/v1/auth/sign-outInvalidate the session cookie.
Request/response shapes live in the auth-user module.
/v1/portal/projectsCreate a project.
/v1/portal/projects/{slug}Get project details.
/v1/portal/projects/{slug}/tokensIssue an API token. Returns the raw token once — store it immediately.
/v1/portal/projects/{slug}/tokensList tokens (hashed preview only — raw values are never replayed).
/v1/portal/projects/{slug}/tokens/{tokenId}Revoke a token.
/v1/portal/projects/{slug}/domainsRegister a domain via the portal (mirrors the API-token path).
/v1/portal/projects/{slug}/domainsList domains for the project.
/v1/portal/projects/{slug}/domains/{hostname}Remove a domain.
/healthzUnauthenticated liveness probe.
Response 200 OK
{ "status": "ok" }/_check-hostnameCalled by Caddy’s on_demand_tls hook to decide whether to issue a certificate. Returns 200 if the domain is registered, a 4xx otherwise. Not intended for external use and subject to change without notice.
Query parameters
| Field | Type | Required | Description |
|---|---|---|---|
domain | string | yes | FQDN to check. |
A machine-readable OpenAPI 3.0 document is coming in Phase 2. Until then, this page and the TypeScript SDK types are the canonical reference.