Use user API keys to call the Hostless HTTP API from scripts, CI pipelines, or other services. Each key belongs to your account, carries explicit scopes, and acts on behalf of you across every project you can access.
Base URL
All paths below are prefixed with /v1.
Authentication
API keys (automation)
Send the full token as the Authorization header. Do not add a Bearer prefix.
curl -sS \
-H "Authorization: hlk_a1b2c3d4_your_secret_here" \
"https://api.hostless.dev/v1/apps"
| Header | Value |
|---|
Authorization | hlk_<prefix>_<secret> |
Some HTTP clients always send Bearer. This is also accepted when the token starts with hlk_:
Authorization: Bearer hlk_a1b2c3d4_your_secret_here
User sessions (dashboard / key management)
Browser login and creating or revoking API keys require a normal JWT session:
Authorization: Bearer <access_token>
API keys cannot call key-management routes or account-level billing routes (payment methods, currency).
Quick start
- In the dashboard, open Account → Settings → API Keys.
- Create a key, select scopes, set optional expiry, and copy the token immediately (shown once).
- Call any allowed platform endpoint with
Authorization: hlk_....
export HOSTLESS_API="https://api.hostless.dev"
export HOSTLESS_TOKEN="hlk_xxxxxxxx_your_secret"
# List apps across all projects you can access
curl -sS -H "Authorization: $HOSTLESS_TOKEN" "$HOSTLESS_API/v1/apps"
List endpoints return resources from all projects you belong to. Optional ?projectId= filters to one project. When creating resources with an API key, include projectId in the request body.
Model Context Protocol (MCP)
AI agents can read the docs and operate the platform over MCP, using the same API keys, JWTs, and scopes as the REST API. See the MCP server guide for endpoints, client setup for Claude, ChatGPT, and Cursor, OAuth, and the tool reference.
Key management API
These endpoints require a user JWT, not an API key. You can only create or revoke your own keys.
Create API key
POST /v1/users/me/api-keys
Request body
{
"name": "CI deploy",
"scopes": ["apps:read", "deployments:write"],
"expiresAt": "2026-12-31T23:59:59.000Z"
}
| Field | Type | Required | Description |
|---|
name | string | yes | Label for the key (1–128 characters). |
scopes | string[] | yes | One or more scopes from the scope reference. |
expiresAt | string (ISO 8601) | no | Expiry time. Omit or null for no expiry. Must be in the future. |
Response 201
{
"token": "hlk_a1b2c3d4f8e7d6c5b4a39281726354849302ab1cd2ef3a4b5c6d7e8f9a0b1",
"apiKey": {
"id": "674a1b2c3d4e5f6789012345",
"name": "CI deploy",
"prefix": "hlk_a1b2c3d4",
"scopes": ["apps:read", "deployments:write"],
"expiresAt": "2026-12-31T23:59:59.000Z",
"lastUsedAt": null,
"createdAt": "2026-05-22T12:00:00.000Z"
}
}
| Field | Description |
|---|
token | Full secret. Returned only once. Store it securely; it cannot be retrieved later. |
apiKey.prefix | Public identifier for lists (not the secret). |
apiKey.id | Use when revoking the key. |
Example
curl -sS -X POST "$HOSTLESS_API/v1/users/me/api-keys" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{
"name": "CI deploy",
"scopes": ["apps:read", "deployments:write"],
"expiresAt": null
}'
List API keys
GET /v1/users/me/api-keys
Response 200 — array of key metadata (no secrets):
[
{
"id": "674a1b2c3d4e5f6789012345",
"name": "CI deploy",
"prefix": "hlk_a1b2c3d4",
"scopes": ["apps:read", "deployments:write"],
"expiresAt": "2026-12-31T23:59:59.000Z",
"lastUsedAt": "2026-05-22T14:30:00.000Z",
"createdAt": "2026-05-22T12:00:00.000Z"
}
]
Revoke API key
DELETE /v1/users/me/api-keys/{keyId}
Response 200
Revoked keys stop working immediately.
Send Authorization: hlk_... on any endpoint below. The required scope is determined by HTTP method and path:
| Method | Typical scope |
|---|
GET, HEAD | resource:read (or deployments:read / logs:read when the path matches those segments) |
POST, PUT, PATCH | resource:write (or deployments:write / hostless-file:write) |
DELETE | resource:delete (integrations and billing use :write for DELETE) |
Paths use {appName}, {siteName}, {workerName}, {cronJobName}, {databaseName}, {projectId}, {deploymentId}, and {id} as path parameters. Expand a scope to see every matching route.
With an API key, GET list routes return data from all projects you can access unless you pass ?projectId=. POST create routes require projectId in the JSON body.
API reference (by scope)
apps:read — List and get apps
| Method | Path |
|---|
GET | /apps |
GET | /apps/{appName} |
GET | /apps/{appName}/search |
GET | /apps/{appName}/environment-variables |
GET | /apps/{appName}/custom-domains |
GET | /apps/{appName}/commits |
GET | /apps/{appName}/collaborators |
GET | /apps/{appName}/review-apps |
GET | /apps/{appName}/review-apps/pull-requests |
GET | /apps/{appName}/worker-processes |
GET | /apps/{appName}/worker-processes/{workerId} |
GET | /apps/{appName}/metrics/request-count |
GET | /apps/{appName}/metrics/response-duration |
GET | /apps/{appName}/metrics/cpu-usage |
GET | /apps/{appName}/metrics/memory-usage |
apps:write — Create and update apps
| Method | Path |
|---|
POST | /apps |
PATCH | /apps/{appName} |
POST | /apps/{appName}/restart |
POST | /apps/{appName}/custom-domains |
PATCH | /apps/{appName}/upgrade |
PATCH | /apps/{appName}/collaborators |
POST | /apps/{appName}/scale/down |
POST | /apps/{appName}/scale/up |
POST | /apps/{appName}/review-apps/trigger |
PATCH | /apps/{appName}/review-apps/extend |
PATCH | /apps/{appName}/worker-processes/{workerId} |
POST | /apps/{appName}/worker-processes |
apps:delete — Delete apps
| Method | Path |
|---|
DELETE | /apps/{appName} |
DELETE | /apps/{appName}/custom-domains |
DELETE | /apps/{appName}/collaborators/{email} |
DELETE | /apps/{appName}/worker-processes/{workerId} |
sites:read — List and get sites
| Method | Path |
|---|
GET | /sites |
GET | /sites/{siteName} |
GET | /sites/{siteName}/search |
GET | /sites/{siteName}/environment-variables |
GET | /sites/{siteName}/custom-domains |
GET | /sites/{siteName}/commits |
GET | /sites/{siteName}/review-sites |
GET | /sites/{siteName}/review-sites/pull-requests |
GET | /sites/{siteName}/visual-builder/project |
GET | /sites/{siteName}/visual-builder/assets |
GET | /sites/{siteName}/metrics/request-count |
GET | /sites/{siteName}/metrics/request-count/total |
GET | /sites/{siteName}/metrics/response-duration |
GET | /sites/{siteName}/metrics/bandwidth |
GET | /sites/{siteName}/metrics/unique-visitors |
GET | /sites/{siteName}/metrics/top-paths |
GET | /sites/{siteName}/metrics/cpu-usage |
GET | /sites/{siteName}/metrics/memory-usage |
GET | /sites/{siteName}/deployments/{siteDeploymentId}/metrics/build-stats |
sites:write — Create and update sites
| Method | Path |
|---|
POST | /sites |
POST | /sites/from-upload |
POST | /sites/from-visual-builder |
PATCH | /sites/{siteName} |
POST | /sites/{siteName}/restart |
POST | /sites/{siteName}/upload |
POST | /sites/{siteName}/custom-domains |
POST | /sites/{siteName}/scale/down |
POST | /sites/{siteName}/scale/up |
POST | /sites/{siteName}/review-sites/trigger |
PUT | /sites/{siteName}/visual-builder/project |
POST | /sites/{siteName}/visual-builder/publish |
POST | /sites/{siteName}/visual-builder/assets |
sites:delete — Delete sites
| Method | Path |
|---|
DELETE | /sites/{siteName} |
DELETE | /sites/{siteName}/custom-domains |
workers:read — List and get workers
| Method | Path |
|---|
GET | /workers |
GET | /workers/{workerName} |
GET | /workers/{workerName}/search |
GET | /workers/{workerName}/environment-variables |
GET | /workers/{workerName}/commits |
GET | /workers/{workerName}/collaborators |
GET | /workers/{workerName}/metrics/cpu-usage |
GET | /workers/{workerName}/metrics/memory-usage |
workers:write — Create and update workers
| Method | Path |
|---|
POST | /workers |
PATCH | /workers/{workerName} |
POST | /workers/{workerName}/restart |
POST | /workers/{workerName}/scale/down |
POST | /workers/{workerName}/scale/up |
PATCH | /workers/{workerName}/collaborators |
workers:delete — Delete workers
| Method | Path |
|---|
DELETE | /workers/{workerName} |
DELETE | /workers/{workerName}/collaborators/{email} |
cron-jobs:read — List and get cron jobs (standalone and per-app)
| Method | Path |
|---|
GET | /cron-jobs |
GET | /cron-jobs/{cronJobName} |
GET | /cron-jobs/{cronJobName}/search |
GET | /cron-jobs/{cronJobName}/environment-variables |
GET | /cron-jobs/{cronJobName}/commits |
GET | /cron-jobs/{cronJobName}/runs |
GET | /cron-jobs/{cronJobName}/runs/{runId} |
GET | /cron-jobs/{cronJobName}/metrics/cpu-usage |
GET | /cron-jobs/{cronJobName}/metrics/memory-usage |
GET | /apps/{appName}/cron-jobs |
GET | /apps/{appName}/cron-jobs/{jobId} |
GET | /apps/{appName}/cron-jobs/{jobId}/runs |
GET | /apps/{appName}/cron-jobs/{jobId}/runs/{runId} |
cron-jobs:write — Create and update cron jobs
| Method | Path |
|---|
POST | /cron-jobs |
PATCH | /cron-jobs/{cronJobName} |
POST | /cron-jobs/{cronJobName}/pause |
POST | /cron-jobs/{cronJobName}/resume |
POST | /apps/{appName}/cron-jobs |
PATCH | /apps/{appName}/cron-jobs/{jobId} |
POST | /apps/{appName}/cron-jobs/{jobId}/run |
cron-jobs:delete — Delete cron jobs
| Method | Path |
|---|
DELETE | /cron-jobs/{cronJobName} |
DELETE | /apps/{appName}/cron-jobs/{jobId} |
deployments:read — List deployments and get deployment details
Applies when the path contains /deployments (except mutating routes below).
| Method | Path |
|---|
GET | /apps/{appName}/deployments |
GET | /apps/{appName}/deployments/{deploymentId} |
GET | /apps/{appName}/deployments/{deploymentId}/stats |
GET | /apps/{appName}/build/stats |
GET | /sites/{siteName}/deployments |
GET | /sites/{siteName}/deployments/{deploymentId} |
GET | /workers/{workerName}/deployments |
GET | /workers/{workerName}/deployments/{deploymentId} |
GET | /cron-jobs/{cronJobName}/deployments |
GET | /cron-jobs/{cronJobName}/deployments/{deploymentId} |
deployments:write — Trigger, rerun, or create deployments
| Method | Path |
|---|
POST | /apps/{appName}/deployments/new |
POST | /apps/{appName}/deployments/{deploymentId}/rerun |
POST | /sites/{siteName}/deployments/new |
POST | /sites/{siteName}/deployments/{deploymentId}/rerun |
POST | /workers/{workerName}/deployments/new |
POST | /workers/{workerName}/deployments/{deploymentId}/rerun |
POST | /cron-jobs/{cronJobName}/deployments/new |
POST | /cron-jobs/{cronJobName}/deployments/{deploymentId}/rerun |
logs:read — Runtime, deployment, build, and run logs
Applies when the path contains /logs, /post-build-logs, or /runtime-logs.
| Method | Path |
|---|
GET | /apps/{appName}/logs |
GET | /apps/{appName}/deployments/{deploymentId}/logs |
GET | /apps/{appName}/deployments/{deploymentId}/post-build-logs |
GET | /sites/{siteName}/logs |
GET | /sites/{siteName}/deployments/{deploymentId}/logs |
GET | /workers/{workerName}/logs |
GET | /workers/{workerName}/deployments/{deploymentId}/logs |
GET | /cron-jobs/{cronJobName}/logs |
GET | /cron-jobs/{cronJobName}/deployments/{deploymentId}/logs |
GET | /cron-jobs/{cronJobName}/runs/{runId}/logs |
GET | /apps/{appName}/cron-jobs/{jobId}/runs/{runId}/logs |
GET | /databases/{databaseName}/import/{cloneId}/logs |
databases:read — List and get databases
| Method | Path |
|---|
GET | /databases |
GET | /databases/{databaseName}/search |
GET | /databases/{databaseName}/details |
GET | /databases/{databaseName}/linked-apps |
GET | /databases/{databaseName}/import/{cloneId}/status |
databases:write — Create and update databases
| Method | Path |
|---|
POST | /databases |
PATCH | /databases/{databaseName} |
PATCH | /databases/{databaseName}/tier |
POST | /databases/{databaseName}/pause |
POST | /databases/{databaseName}/unpause |
POST | /databases/{databaseName}/import |
databases:delete — Delete databases
| Method | Path |
|---|
DELETE | /databases/{databaseName} |
integrations:read — Discover and list integrations
| Method | Path |
|---|
GET | /integrations/available |
GET | /projects/{projectId}/integrations |
integrations:write — Configure project integrations
| Method | Path |
|---|
POST | /projects/{projectId}/integrations/slack |
PUT | /projects/{projectId}/integrations/slack |
DELETE | /projects/{projectId}/integrations/slack |
POST | /projects/{projectId}/integrations/slack/test |
projects:read — Get project metadata
Only GET / HEAD on /projects paths (except git, integrations, and members routes).
| Method | Path |
|---|
GET | /projects |
GET | /projects/{projectId} |
GET | /projects/{projectId}/apps |
GET | /projects/{projectId}/connected-accounts |
git:read — Read project Git provider connections
| Method | Path |
|---|
GET | /projects/{projectId}/github/accounts |
GET | /projects/{projectId}/github/accounts/{accountLogin}/repos |
GET | /projects/{projectId}/gitlab/repos |
GET | /projects/{projectId}/bitbucket/workspaces |
GET | /projects/{projectId}/bitbucket/workspaces/{workspace}/repos |
git:write — Connect or disconnect Git accounts
| Method | Path |
|---|
DELETE | /projects/{projectId}/github/disconnect |
DELETE | /projects/{projectId}/gitlab/disconnect |
DELETE | /projects/{projectId}/bitbucket/disconnect |
traces:read — App traces
| Method | Path |
|---|
GET | /traces/{appName} |
hostless-file:read — Cost estimation from a Hostless file
| Method | Path |
|---|
POST | /estimate-costs |
hostless-file:write — Generate, update, or commit Hostless file config
| Method | Path |
|---|
POST | /apps/{appName}/hostless-file/generate |
POST | /apps/{appName}/hostless-file/update |
POST | /apps/{appName}/hostless-file/commit |
POST | /apps/{appName}/hostless-file/calculate-costs |
virtual-machines:read — List and get VMs
| Method | Path |
|---|
GET | /virtual-machines |
GET | /virtual-machines/pricing |
GET | /virtual-machines/project/{projectId} |
GET | /virtual-machines/{id} |
GET | /virtual-machines/{id}/metrics |
GET | /virtual-machines/{id}/metrics/cpu-usage |
GET | /virtual-machines/{id}/metrics/memory-usage |
GET | /virtual-machines/{id}/metrics/network-in |
GET | /virtual-machines/{id}/metrics/network-out |
GET | /virtual-machines/{id}/metrics/disk-usage |
GET | /virtual-machines/{id}/firewall |
virtual-machines:write — Create and manage VMs
| Method | Path |
|---|
POST | /virtual-machines |
POST | /virtual-machines/{id}/start |
POST | /virtual-machines/{id}/stop |
POST | /virtual-machines/{id}/restart |
PUT | /virtual-machines/{id}/resources |
PUT | /virtual-machines/{id}/firewall |
virtual-machines:delete — Delete VMs
| Method | Path |
|---|
DELETE | /virtual-machines/{id} |
billing:read — Usage, cycles, and invoices (account-wide)
| Method | Path |
|---|
GET | /billing/breakdown |
GET | /billing/databases/breakdown |
GET | /billing/cycles |
GET | /billing/currencies |
GET | /billing/payment-config |
GET | /invoices |
GET | /invoices/{id} |
GET | /invoices/{id}/receipt |
billing:write — Pay a project invoice
| Method | Path |
|---|
POST | /billing/pay/{invoiceId} |
metrics:read — Standalone metrics routes
No customer routes are mounted at /metrics today. App, site, worker, and cron job metrics use each resource's :read scope (for example apps:read on GET /apps/{appName}/metrics/...). This scope is reserved for future /metrics endpoints.
Not available with API keys
These routes require a user JWT (dashboard session), not an API key:
- Key management:
/users/me/api-keys
- Account auth and profile:
/auth, /users (except your own key routes above)
- Project members and transfers:
/projects/{projectId}/members, PATCH /projects/{projectId}, DELETE /projects/{projectId}, resource transfers
- Payment methods and currency:
/billing/stripe/*, /billing/paystack/*, PATCH /billing/currency/*, GET /billing/currencies/{currencyCode}
- Admin, SSH keys, health, campaigns, credit, and standalone
/github, /gitlab, /bitbucket OAuth callbacks
Example: trigger a deployment
curl -sS -X POST \
-H "Authorization: $HOSTLESS_TOKEN" \
-H "Content-Type: application/json" \
"$HOSTLESS_API/v1/apps/my-app/deployments/new" \
-d '{}'
Requires deployments:write (and project role owner/editor if your user is a viewer).
Example: read billing breakdown
curl -sS \
-H "Authorization: $HOSTLESS_TOKEN" \
"$HOSTLESS_API/v1/billing/breakdown?startDate=2026-05-01&endDate=2026-05-31"
Requires billing:read. Returns usage across all projects you can access.
Scope reference
Scopes use the format resource:action.
| Scope | Description |
|---|
| Apps | |
apps:read | List and get apps |
apps:write | Create and update apps |
apps:delete | Delete apps |
| Sites | |
sites:read | List and get sites |
sites:write | Create and update sites |
sites:delete | Delete sites |
| Workers | |
workers:read | List and get workers |
workers:write | Create and update workers |
workers:delete | Delete workers |
| Cron jobs | |
cron-jobs:read | List and get cron jobs |
cron-jobs:write | Create and update cron jobs |
cron-jobs:delete | Delete cron jobs |
| Deployments | |
deployments:read | List deployments, get deployment details |
deployments:write | Trigger, rerun, or create deployments |
| Logs | |
logs:read | Deployment logs, post-build logs, runtime logs |
| Databases | |
databases:read | List and get databases |
databases:write | Create and update databases |
databases:delete | Delete databases |
| Integrations | |
integrations:read | List project integrations |
integrations:write | Configure or update integrations |
| Project | |
projects:read | Get project and list project apps |
git:read | Read project git account connections |
git:write | Connect or disconnect project git accounts |
| Observability | |
metrics:read | App/site/worker metrics endpoints |
traces:read | App trace endpoints |
| Hostless file | |
hostless-file:read | Read or estimate from hostless file config |
hostless-file:write | Update hostless file config |
| Virtual machines | |
virtual-machines:read | List and get VMs |
virtual-machines:write | Create and update VMs |
virtual-machines:delete | Delete VMs |
| Billing | |
billing:read | Usage breakdown, cycles, invoices (account-wide) |
billing:write | Pay an invoice |
Authorization rules
Access is the intersection of:
- Valid API key — not revoked, not expired, correct secret.
- Scopes — the key includes every scope required for the route.
- Project role — the key creator's membership role still applies. For example, a project viewer cannot perform
POST/PUT/PATCH/DELETE even if the key has write scopes.
- App collaborators — existing app-level collaborator checks still apply.
Scopes are a ceiling, not an elevation: they cannot bypass role or collaborator rules.
Errors
| Status | Meaning |
|---|
401 Unauthorized | Missing/invalid token, expired key, or wrong secret. |
403 Forbidden | Missing scope, viewer blocked on mutation, wrong project resource, or JWT-only route called with an API key. |
404 Not Found | Project or resource not found (or not in a project you can access). |
Example scope error:
{
"statusCode": 403,
"message": "Missing required scope(s): deployments:write",
"error": "Forbidden"
}