Secrets

Write, list and delete the named values your app's functions read as environment variables.

Docs menu

Each secret has a key that your functions read as env.<KEY>. A secret can hold an API token or signing key, for example. You can write or replace a value, but you cannot read it back. List operations return names only.

Operations

Operation Route MCP tool What it does
secret.write PUT /v1/_secrets (or POST) substrio_secret_write Sets key to value (both required, not empty), replacing a value already there
secret.list GET /v1/_secrets substrio_secret_list Returns secrets (each {key, value: "***"}) and count
secret.delete DELETE /v1/_secrets/{key} substrio_secret_delete Removes one secret and returns {success, deleted, key}

Each write and delete is recorded in the app's audit log. Both are irreversible because the previous value cannot be read back, and no undo token is provided. An agent's call to either requires approval, as with other changes of authority.

The CLI commands are substrio secrets set KEY, substrio secrets list, and substrio secrets delete KEY. For set, provide the value on stdin, with --from-file, or with --from-env; do not pass it as an argument. The delete command asks for confirmation unless you pass --yes.

Refusals

Code Status When Field
SECRET_NOT_FOUND 404 secret.delete of a key the app does not hold key
INVALID_ARGUMENT 400 secret.write without a key or a value

Worked example: an agent sets and removes a secret

Every call is a plain MCP tools/call with the account key on the account's MCP server; app names the app.

[
  {"name": "substrio_secret_write", "arguments": {"app": "shop", "key": "API_TOKEN", "value": "..."}},
  {"name": "substrio_secret_list", "arguments": {"app": "shop"}},
  {"name": "substrio_secret_delete", "arguments": {"app": "shop", "key": "API_TOKEN"}}
]

The delete returns {"success": true, "deleted": true, "key": "API_TOKEN"}. Repeating it returns SECRET_NOT_FOUND with field: "key". Use secret.list to check the name before trying again.

Worked example: a site and a function that reads the secret, shipped with no hash

The function reads the secret from the global env.API_TOKEN. Commit the function and page to the app's history as text without computing a hash or uploading a file. Then promote the version returned by the commit, version 3 in this example:

[
  {"name": "substrio_version_commit", "arguments": {"app": "shop", "branch": "main", "message": "with a token",
    "units": [
      {"path": "functions/status.js", "text": "export default async () => new Response(env.API_TOKEN ? 'ready' : 'no token');\n"},
      {"path": "functions/status.json", "text": "{\"routes\":[\"GET /status\"]}"},
      {"path": "site/index.html", "text": "<!doctype html><h1>Shop</h1>\n"}]}},
  {"name": "substrio_live_set", "arguments": {"app": "shop", "version": 3}}
]

See versioning ("Developing over MCP": tree, read, edit, search, commit, promote) and static sites (large files uploaded with no hash).