# Endpoints

The cloud compiler API is hosted at `https://compiler.quickback.dev`
(alias: `https://build.quickback.dev` — same Worker, same auth via
`quickback-api`, identical `/health` / `/templates` / `/compile`).

## Public (No Auth)

| Endpoint | Method | Description |
|----------|--------|-------------|
| `/health` | GET | Health check |
| `/templates` | GET | List available templates |

## Authenticated

| Endpoint | Method | Description |
|----------|--------|-------------|
| `/compile` | POST | Compile definitions into backend files |

The `/compile` endpoint requires either a session token (from `quickback login`) or an API key (via `QUICKBACK_API_KEY` header). See [Authentication](/tooling/cloud-compiler/authentication) for details.

## Raw-files mode (`POST /compile`)

`/compile` normally expects the parsed `CompilerInput` the CLI assembles client-side. Thin clients (agents, web builders, CI without the CLI) can instead send the project sources verbatim and let the compiler organize them server-side:

```json
{
  "rawFiles": {
    "quickback/quickback.config.ts": "import { defineConfig } from …",
    "quickback/features/todos/todos.ts": "import { feature, q } from …",
    "quickback/features/todos/actions/complete.ts": "…"
  }
}
```

The map uses project-root-relative paths and follows the same layout `quickback compile` reads from disk: `quickback/quickback.config.ts`, `quickback/features/**`, `quickback/services/**`, `quickback/{lib,hooks,plugins,middlewares,email-templates}/**`, plus `quickback/drizzle/**/meta/**` and `wrangler.toml` for incremental builds.

Two constraints, both fail-closed:

- **The config must be fully static.** The compiler parses `quickback.config.ts` with a literals-only evaluator — it never executes user code. Object/array/string/number/boolean literals, substitution-free template literals, and the `define*` helper calls all work; variables, computed values, and imports-as-values are rejected with a 400 that names the offending construct and line.
- **Action input schemas are contract-sensitive.** For v1, raw-files requests may omit `actionInputSchemas` and use the compiler's lower-fidelity static parser. V2 requires one usable client-harvested `z.toJSONSchema(action.input)` entry for every authored action. The CLI reports each missing action with its local bundle or evaluation error; the API independently reports missing or invalid action keys.

Raw-files requests work with both `?complete=true` and `?complete=false`
(validation-only) compiles. The v2 action-schema completeness gate applies to
both modes; `complete=false` is not an escape hatch for a partial harvest.

## Edge validation backend

Validation compiles (`POST /compile?complete=false`) may be served by an edge Worker instead of the compiler container. This is **transparent to clients**: same endpoint, same auth, same request and response shapes (plain or gzipped JSON, raw-files or parsed input, identical payload limits, error shapes, and generated-file envelopes) — just no container cold start.

The response header `X-Quickback-Compile-Backend` says which backend answered:

| Value | Meaning |
|-------|---------|
| `edge` | Served by the edge Worker |
| `container-fallback` | Edge is enabled but failed (5xx/unreachable); the container answered instead |
| _(absent)_ | Edge routing is not enabled; the container answered, as before |

Complete compiles (`?complete=true`, the default) always run in the container — they need the CLI toolchain (drizzle-kit, prebuilt SPA assets). The edge Worker rejects them with a 400 pointing at the container endpoint.

## Environment Variables

| Variable | Description |
|----------|-------------|
| `QUICKBACK_API_KEY` | API key for authentication (alternative to `quickback login`) |
| `QUICKBACK_API_URL` | Override compiler API URL (default: `https://compiler.quickback.dev`) |

### Custom Compiler URL

Point the CLI to a different compiler (local or custom):

```bash
QUICKBACK_API_URL=http://localhost:3000 quickback compile
```

See [Local Compiler](/tooling/cloud-compiler/local-compiler) for running the compiler locally with Docker.

## Streaming Protocol (`POST /compile`)

By default `/compile` returns a single JSON response. If the request includes `Accept: text/event-stream`, the compiler upgrades to Server-Sent Events so the CLI can render progress while the build runs.

There are two stream protocol versions, negotiated via the `X-Quickback-Stream` request header:

| Header | Protocol | Behavior |
|--------|----------|----------|
| _(absent)_ | **v1** | Sends `progress` events during the build, then a single `result` event with the entire compilation payload (config, generated files, drizzle output, SPA bundles, etc.) JSON-encoded as one frame. |
| `X-Quickback-Stream: v2` | **v2 (chunked)** | Sends `progress` events during the build, then a `meta` event with the file count, then one `file` event per generated file, then a final `done` event with metadata, commands, and warnings. |

The server echoes the chosen version back as the response `X-Quickback-Stream` header so the CLI knows which framing to parse.

### Why v2

Multi-megabyte SPA bundles (CMS + Account, with sourcemaps) take long enough to `JSON.stringify` that the v1 single-frame `result` event blocks Cloudflare's container event loop. Two things break: Docker's `HEALTHCHECK` fails, and the CLI's 120-second connection timeout fires before the body flushes. v2 emits files one at a time and yields back to the event loop every 10 files (`setImmediate`), keeping `/health` responsive and TCP backpressure alive.

The `@quickback-dev/cli` v0.10.x and later send `X-Quickback-Stream: v2` automatically. v1 is preserved for older clients.

### Event shapes (v2)

```
event: progress
data: { "stage": "vite-cms", "message": "..." }

event: meta
data: { "fileCount": 412, "version": "0.10.3" }

event: file
data: { "path": "src/...", "content": "...", ... }
…

event: done
data: { "meta": {...}, "commands": [...], "warnings": [...] }
```

On failure, an `error` event is emitted in either protocol:

```
event: error
data: { "error": "Compilation failed", "code": "...", "message": "..." }
```
