ReferenceHTTP surfaces
HTTP surfaces#
What does a client see on the wire?
On this page
mehen is the supported client; nothing here is needed to use Mehen. This page is for reading what goes over the wire.
Machine requests#
Machines talk to the vault under https://app.mehen.dev/v1/. Every request from an enrolled machine carries a Mehen-Proof header, a signature over the method, the full URL and a hash of the exact body (Keys, proofs and signing). There is no bearer token.
| Route | What it is |
|---|---|
POST /v1/enrol, GET /v1/enrol/:enrolment, POST /v1/enrol/:enrolment/renew | Start an enrolment, poll it, renew its lease in place. Signed by the key being enrolled. |
GET /v1/me | This machine's identity, owner, scope and state. |
GET /v1/items, GET /v1/items/:slug | Items this machine may use, and one item's public description. |
POST /v1/relay | One HTTP request through the vault relay. |
POST /v1/intakes, GET /v1/intakes/:id, POST /v1/intakes/:id/cancel | Ask for a credential, poll the intake, cancel your own. |
POST /v1/connect, GET /v1/connect/:id, POST /v1/connect/:id/cancel | Ask for an OAuth connection, poll it, cancel your own. |
GET /v1/approvals/:id | Poll an approval; ?wait=1 long-polls up to 25 seconds. |
GET /v1/pending | This machine's own open asks, and the one notice a machine gets, that it was added to the workspace. |
POST /v1/projects, GET /v1/projects/:id, /v1/projects/:id/vars/:name | Create a project, read it, set a variable. |
POST /v1/runs, POST /v1/runs/:id/renew, DELETE /v1/runs/:id, POST /v1/lease | Start, renew and end a run; fetch a lease mid-run. |
POST /v1/freeze | Freeze the workspace. |
POST /v1/devices/self/revoke | Revoke this machine. |
GET /v1/seal-key | Unauthenticated: the vault's public seal key, which browsers seal secret fields to. |
Headers#
| Header | Direction | Meaning |
|---|---|---|
Mehen-Proof | request | The machine's signature over this exact request. |
Mehen-Error: 1 | response | The vault refused; the body is an error object (Errors and exit codes). |
Mehen-Upstream: 1 | response | A relayed upstream response, never a vault refusal. |
Mehen-Item | response | The item that acted, <slug> (<account>), so the transcript says which account was used. |
Mehen-Cli | response | On every /v1 answer: minimum=<v>, with ; recommended=<v> when the vault sets one. A mehen below the minimum is refused with cli_outdated (HTTP 426), except freeze and self-revoke. |
User-Agent | request | mehen/<version>. |
An upstream 403 and a vault refusal are never the same thing: only the vault's carries Mehen-Error.
Errors#
type ApiError = {
error: ErrorCode
message: string
next?: { url?: string; command?: string; say: string }
approval?: string
bindingCode?: string
choices?: { slug: string; account: string | null }[]
retryAfter?: number
expiresAt?: string
deciders?: string[]
transition?: ...
}Every code, its HTTP status and the exit code mehen gives it are in Errors and exit codes, and as JSON at /reference/errors.json.
The release channel#
Releases are served from https://mehen.dev/dl/:
| Path | What it is |
|---|---|
/dl/latest.json | The signed manifest of the current release. |
/dl/v<version>/manifest.json | One release's signed manifest: { version, commit, builtAt, files, signatures }, each file with its name, platform, size and SHA-256, compressed and uncompressed. |
/dl/v<version>/mehen-<os>-<arch>.gz | The binary, for darwin or linux on arm64 or x64. |
https://mehen.dev/install is the installer for a machine with no mehen. Its last line is the receipt, mehen-install: {"v":1,"result":"installed","version":...,"path":...,"onPath":...,"env":...,"rc":{...}}, where result is installed, already-installed or forced. Keys, proofs and signing says how a release is checked.