An example link publishes the shape of an environment without any of its contents: every variable name, plus its type, visibility and whether it is required, with every value blank. It is the file you would have hand-written as .env.example and then forgotten to update. Point a README at the link instead, and it can never drift from the environment it documents.
This feed carries no ciphertext and no values, which makes it a different risk profile from virtual environments. Nothing here needs the workspace passphrase, because there is nothing to decrypt. What it does publish is a complete inventory of your variable names, which has real reconnaissance value. Turn it on for environments whose key names you are comfortable showing the public.
Enable it
Open the environment settings
A member with the environments:update permission opens the environment, then Settings, and finds the Example link row. It is off by default and independent of Virtual Envs: you do not need to turn that on first, and turning it off later does not retract your example links.
Flip the toggle
Enabling is a step-up action, so you will be asked to confirm with a code. Once it is on, the Example URL field appears with the live link and a copy button.
An environment inside a private product can never publish an example link. The write is refused with 400 and A private product cannot publish an example link. Making a product private also retracts its example links immediately, with no further action.
The URLs
Every published version is addressable, and so is the live state of the environment.
| URL | Serves |
|---|---|
/example/<workspace>/<product>/<project>/<env>/versions/current | The live variables, as they are right now |
/example/.../versions/latest | The most recently published version |
/example/.../versions/v7 | A specific version, by its label or id |
/example/.../versions | The list of published versions |
On a custom domain the workspace slug drops out, so the link reads https://env.acme.com/example/<product>/<project>/<env>/versions/current.
One link serves both audiences. Open it in a browser and the API redirects (302) to the dashboard, which renders the readable page at https://envless.cloud/dashboard/example/.... Anything that is not a browser is served JSON directly, so curl, CI and the SDK never follow a redirect. The Example URL field in Environment settings gives you the dashboard link, which is the one to paste into a README.
The three renderings
The same URL serves three things, chosen by the Accept header or an explicit ?format=.
Opening the link in a browser lands on the dashboard viewer: the generated file, a key table and the raw JSON, with a copy button and a switcher for the live keys or any published version. The page is public, so a reader does not need an Envless account.
curl -H 'Accept: text/plain' https://api.envless.cloud/example/acme/watch/website/production/versions/currentDATABASE_URL=
ENABLE_BETA=
VITE_APP_URL=Nothing is injected: no header, no per-key annotations. The file is exactly the key names, one per line, ready to paste. The type, visibility and required flags live in the JSON rendering and on the page's Keys tab.
?format=env&download=1 serves the same bytes as a .env.example file attachment.
JSON is the default for anything that is not a browser, so a bare curl gets it with no header at all.
{
"format": "envless.env-example/v1",
"workspace": { "slug": "acme" },
"product": { "slug": "watch" },
"project": { "slug": "website" },
"environment": { "slug": "production" },
"source": {
"kind": "version",
"id": "0192a1b2-c3d4-7000-8000-000000000020",
"label": "v7",
"variableCount": 3,
"updatedAt": "2026-09-01T08:02:11.000Z"
},
"values": {
"included": false,
"reason": "This feed serves key names and metadata only. No values, no ciphertext."
},
"truncated": false,
"variables": [
{
"name": "DATABASE_URL",
"value": "",
"type": "string",
"visibility": "server",
"required": true,
"secret": true
}
]
}value is always present and always the empty string, so a consumer mapping variables into a record never has to special-case a missing key.
What is served, and what is not
Included
name, in the spelling it was stored with. Variable names are case-reserved, so folding them would produce a file that no longer matches whatenvless pullwrites.type, one ofstring,numberorboolean.visibility,serverorclient, so a reader knows which keys are browser-safe.required, the most useful column in a template.secret, which is the difference between "put a value here" and "fetch this from your vault".
Never served
- Every value and default value, on both the live variables and the version entries.
- The whole decryption block that the virtual env feed carries. There is no ciphertext here, so there is no key derivation to describe.
- Version notes, which are free text a teammate wrote for teammates.
- Every actor field: who created or last updated a variable, and which API key did it.
- Per-variable timestamps.
valueUpdatedAtin particular would be a rotation-timing oracle, so only an aggregate is published onsource.updatedAt. - Workspace, product, project and environment ids and names. Only slugs are emitted, and those are already in the URL you typed.
Caching and retraction
Responses carry a weak ETag and a short Cache-Control, so a If-None-Match request gets a 304. The dashboard viewer asks for ?include=document, which adds the rendered file to the JSON body so the page needs one request rather than two; machines that omit it get the lean payload. The live document is cached for 30 seconds and a pinned version for 60, which means retracting a link can take up to that long to be visible everywhere. A 404 is always no-store, so enabling a link takes effect immediately.
Names that are not valid .env keys are left out of the .env rendering. The JSON carries a skipped count alongside them, and the page states it, so nothing is dropped silently.
Turning it off
Flip the toggle back. The URL starts answering 404 with the same body as a link that never existed, so nothing is disclosed about whether the environment is real.