intentic
Create your workspace
Start here

The shape of a call

There is no envelope and no versioning scheme. The contract's path is the URL, the body you send is the declared shape, and two conventions cover every route on the site.

On this page(5 sections)

Where the sandbox is

Each sandbox answers on its own hostname, https://sandbox-<id>.<zone>, over its private tunnel. The app shows the exact address under Sandbox → Overview. One route stays open, and it is the one every launch script and readiness loop asks first.

Is a daemon there
curl https://sandbox-a1b2c3d4e5f6.intentic.dev/health

{ "ok": true, "sandboxId": "a1b2c3d4e5f6", "boot": { }, "announce": { } }

The sandbox id in that answer is how a caller proves it reached this daemon rather than something else on the same port. On the machine actually running the sandbox there is also https://local-<id>.<zone>, a public name that resolves to the loopback address: a real certificate on 127.0.0.1, so a browser on that machine skips the round trip out through the tunnel and back.

Two conventions, all 261 routes

ConventionDetail
Input on GETThe query string.
Input on everything elseA JSON body. Including DELETE, which sends its parameters in the body rather than the query.
OutputJSON, except the byte routes below and the streams.
FailureA JSON object with a message, never an empty body. See when a call fails.
Two calls
SANDBOX=https://sandbox-a1b2c3d4e5f6.intentic.dev

# GET: input rides the query string
curl "$SANDBOX/workspace/file?path=README.md" \
  -H "x-intentic-control: $INTENTIC_TOKEN"

# Everything else: input rides the JSON body, including DELETE
curl -X POST "$SANDBOX/git/root/commit" \
  -H "x-intentic-control: $INTENTIC_TOKEN" \
  -H "content-type: application/json" \
  -d '{"message":"Fix the flaky parser test"}'

Path parameters

A templated segment is written {repo} or {id} throughout this reference, and is URL-encoded in the request. For every git route, root is the workspace repository itself and any other value is a repository's directory relative to the workspace root.

Routes that answer bytes

Four routes fall outside the JSON contract entirely, because bytes are not a shape a JSON contract can describe.

RouteWhy it's different
GET /workspace/rawA file's bytes with a content type worked out from its extension: how an image or a PDF is previewed, where the text route would corrupt it.
GET /workspace/mediaA streamed byte range for audio and video. A media element cannot send a header, so this takes a short-lived ticket minted by POST /workspace/media-ticket, which is in the reference.
POST /workspace/uploadRaw bytes, in parts, so a large file stays under the edge's body limit.
GET /extensions/{id}/bundleAn installed extension's code, as bytes.

Old daemon, new client

Your browser is routinely newer than the daemon it is talking to: one released app plane serves every sandbox, whatever image each user last pulled. That is supported rather than tolerated, and it is why the identity route and the event stream's opening frame both advertise the route names this particular daemon implements. A client compares that list against the contract it was built with, so a route the daemon predates surfaces as a named gap instead of a 404 nobody can attribute.

Pin nothing; ask.

Type to search every page, in the docs and the API reference.