Support
Hosting

Concepts

Variants, deployments, async jobs, and secrets — the mental model behind the Node.js Hosting API.

The API is small — five resource groups, roughly fifteen endpoints — but three concepts run through all of them: variants, async jobs, and deployments. Once you have those, the rest of the surface reads itself.

Variants

Every app has two runtime variants:

VariantWhat it isTypical use
previewWorking copy. Receives new source uploads and secret changes.Iteration, integration testing, staging.
publishProduction copy. Serves live traffic.Whatever your users actually hit.

Uploads land on preview. Publishing promotes the current preview to publish. Rollback points publish at a prior deployment. preview is never rolled back — only overwritten by the next upload.

Per-variant reads differ by endpoint. GET /status returns both variants in one response with no filter parameter. GET /secrets accepts an optional variant query parameter. GET /logs uses a required target query parameter (preview or publish), plus source, since, and optional lines. Secret writes take variant in the request body.

Async jobs

Operations that outlive a single request return immediately with a job or deployment record. Poll a status endpoint until they reach a terminal state.

Rendering diagram...

Terminal states

Job typePoll endpointTerminal states
Create appGET /apps/jobs/{jobId}active (ready), failed
Source uploadGET /apps/{appId}/source/status?jobId=...succeeded, failed (exact enum values are in the reference)
Publish / rollbackGET /apps/{appId}/deployments and GET /apps/{appId}/statusLatest deployment reports a completed status; runtime status flips to running on the affected variant

Polling guidance

  • Interval: 2–5 seconds is a good starting point. Back off on longer jobs.
  • Give-up window: most create/upload jobs complete in under a minute. If you're still in pending after several minutes, treat it as stuck and surface an error.
  • Idempotency: re-polling is free. The status endpoints have no side effects.

Deployments

A deployment is a snapshot of source + config that ran (or is running). Deployments are numbered and durable — even after publish overwrites the live one, older deployments remain listable and are eligible rollback targets.

POST /apps/{appId}/source           # upload zip → job → new source on preview
POST /apps/{appId}/deployments      # publish preview → new deployment on publish
GET  /apps/{appId}/deployments      # history (paginate with limit, default 20, max 50)
POST /apps/{appId}/rollback         # publish variant → prior deploymentId

Runtime status (GET /apps/{appId}/status) is a separate concern from deployments — it tells you whether the variant is actually up and serving, independent of what deployment it points at.

Secrets

Secrets are set per-variant. They can be added, updated, or deleted in a single call, up to 50 of each per request:

{
  "variant": "preview",
  "operations": {
    "additions": [{ "name": "STRIPE_KEY", "value": "sk_test_..." }],
    "updates":   [{ "name": "DB_URL",    "value": "postgres://..." }],
    "deletions": [{ "name": "OLD_FLAG" }]
  }
}

The response contains metadata only — names, last-updated timestamps, etc. Values are never returned by any endpoint, including reads. If you need to know what a secret is set to, look it up in whatever system generated it.

Listing secrets (GET /apps/{appId}/secrets) currently requires the secrets:write scope even though it's a read operation. Treat that as the effective requirement for now.

Putting it together

Rendering diagram...

Every step above is a single API call plus polling. That's the whole model.

See also

Last updated on

How is this guide?

On this page