Test hosts and root domains

Bind a sandbox to a host, test a version there, and promote it from that host to live.

Docs menu

An app's environments are available on hosts chosen by its agent. For example, my-app-v2.substrio.com runs the same version and uses the same data as the dev sandbox, while my-app.substrio.com continues to serve the live version. When the test passes, one call makes that version live.

  • A root domain is a domain apps are served under, enabled by Substrio before any app can use it.
  • A test host is <label>.<root>: one DNS label under an enabled root, bound by an app to one of its environments (live or a sandbox) with env.host.set.

The agent's loop: test on a host, then promote

substrio_version_create ...                                  # version 2 pushed (version 1 is live)
substrio_sandbox_create      {"name": "dev"}
substrio_live_set            {"version": 2, "sandbox": "dev"}
substrio_env_host_set        {"host": "my-app-v2.substrio.com", "environment": "dev"}
  -> {"host": "my-app-v2.substrio.com", "label": "my-app-v2", "root": "substrio.com",
      "environment": "dev", "version": 2, "created_at": 1793080000}

GET https://my-app-v2.substrio.com/hello   -> version 2, the sandbox's data
GET https://my-app.substrio.com/hello      -> version 1, the app's data

substrio_live_set            {"from": "my-app-v2.substrio.com"}
  -> {"live": 2, "previous": 1, ...}
substrio_env_host_remove     {"host": "my-app-v2.substrio.com"}

With version, env.host.set first runs that version in the named sandbox, creating the sandbox if it does not exist. One call can therefore put a version on a host:

{"name": "substrio_env_host_set", "arguments": {"host": "my-app-v1.substrio.com", "environment": "one", "version": 1}}

Operations

Operation Route MCP tool CLI Who
env.host.set POST /v1/_env_hosts substrio_env_host_set substrio env host set host=H environment=E [version=N] the app's key or agent
env.host.list GET /v1/_env_hosts substrio_env_host_list substrio env host list the app's key or agent
env.host.remove DELETE /v1/_env_hosts/{host} substrio_env_host_remove substrio env host remove H --yes the app's key or agent

version.live.set accepts from instead of version, using a sandbox name or a host from env.host.list. The version running in that environment goes live through the same process as a numbered promotion, including check, backup, direct, and plan. See versioning.md.

env.host.set

Member
host required <label>.<root>, any case (stored lowercase)
environment required live, a sandbox name (dev) or its whole slug (my-app--dev), or another host of the app's
version optional runs this version in the sandbox before binding (a new sandbox is made); not with live

It returns the binding: host, label, root, environment, version (the version running now, or 0 when none), and created_at. Binding a host again moves it to the named environment. Binding it to its current environment changes nothing.

env.host.list

The response, {"hosts": [{host, label, root, environment, version, created_at}], "roots": [...]}, lists the hosts of the app and its sandboxes by label, and the roots currently available for binding.

The rules

  • One owner per label. Labels share a namespace with app slugs. A test host cannot take an app's slug, and an app cannot take a label already in use. A label resolves under every enabled root and has the same owner across them. This prevents another app from using the same label under a different root domain.
  • Reserved: www, api, mcp, platform, every app's slug, and any label with -- (sandbox hosts, <app>--<sandbox>).
  • One label under the root: a.b.substrio.com is refused (a root's certificate names one level).
  • The label rule: lowercase letters, digits and inner hyphens, 1 to 63 bytes. The refusal suggests the nearest valid host: eventsta_v15.substrio.com suggests eventsta-v15.substrio.com.
  • Isolation: a host serves its environment. A sandbox host reads and writes the sandbox's data, keys, and secrets rather than the live app's.
  • Removal: removing a host frees its label at once; removing a sandbox or an app removes its hosts in the same transaction.

Refusals

Each refusal uses the standard error body with field naming what to correct. Who holds a taken host is never shown.

Code Value Status next_action field When
HOST_TAKEN 0xC048 409 correct_request host another app holds the label
HOST_INVALID 0xC049 400 correct_request host not <label>.<root>, more than one label, or a label that breaks the rule; detail says what and where, suggestion the nearest valid host
HOST_RESERVED 0xC04A 409 correct_request host www, api, mcp, platform, an app's slug, or a -- label
ENV_HOST_NOT_FOUND 0xC04B 404 refresh_resource host env.host.remove of a host the app does not hold
ENVIRONMENT_NOT_FOUND 0xC04C 404 correct_request environment or from no such sandbox or host of the app's, or (for from) it runs no version