Documentation
API reference
The complete HTTP resource reference, authenticated local access, streaming contracts, and clients generated from shared schemas.
Overview
The sidecar is a single Effect HttpApi. Every endpoint is a typed HttpApiEndpoint with schema-checked request and response bodies, so this reference, the generated SDK and the running server come from the same declaration in packages/api.
Across 232 paths and 35 resource groups.
Request, response and error shapes, each linked from the operations that use it.
Emitted by the sidecar at /api/openapi.json; the snapshot in packages/web is checked by bun run check:api-reference.
The desktop webview, the mobile companion, the AI bridge and scripts all call these same routes.
Base URL
There is no hosted CADCAMFUN API. The sidecar runs on your machine, binds 127.0.0.1 on a port the operating system picks (it listens on port 0), checks its own /api/health, and only then prints one JSON line on stdout. The base URL is http://127.0.0.1:<port> from that line.
export CADCAMFUN_TOKEN=dev-token
CADCAMFUN_DATA_DIR=$(mktemp -d) \
CADCAMFUN_MIGRATIONS_DIR=$PWD/packages/db/drizzle \
CADCAMFUN_AI_OFFLINE=true \
bun --no-env-file apps/sidecar/src/main.ts
# stdout: {"event":"ready","port":46709}
export CADCAMFUN_URL=http://127.0.0.1:46709 The port changes on every launch
ready line (the desktop shell does exactly that) instead of assuming a fixed number. Logs go to stderr so stdout carries only the ready or error event. Authentication
The contract declares one security scheme, bearer (HTTP Bearer). 324 of 325 operations require it; only GET /api/health is public.
| Credential | Sent as | Used by |
|---|---|---|
| Launch token | Authorization: Bearer <token> | The desktop webview and local scripts; the value of CADCAMFUN_TOKEN. |
| Companion token | Authorization: Bearer <token> | A paired phone; narrower access, see companion pairing. |
| Account session | x-session-token | Selects the acting account on top of the bearer token; see identity below. |
curl -s "$CADCAMFUN_URL/api/health"
curl -s "$CADCAMFUN_URL/api/projects" -H "Authorization: Bearer $CADCAMFUN_TOKEN" Conventions
- JSON in, JSON out. Bodies are
application/jsonunless a card says otherwise: two multipart uploads, one octet-stream webhook, a JavaScript bootstrap, a zip download, a binary plugin file, and two event streams. - Operation ids are dotted.
projects.get,vcs.commit: the group tag, a dot, the method name used by the generated clients. - Errors are typed. Failures are declared per endpoint and carry a
_tag; switch on it instead of parsing messages. Across the contract, 401 is declared on 269 operations, 500 on 264 and 400 on 206. - Operation anchors are stable. Each card is linkable as
#op-<method>-<path>, for example/docs/api/projects#op-get-api-projects-id.
Streaming
| Path | Shape | Carries |
|---|---|---|
GET /api/projects/{id}/events | SSE | Change events for one project. |
POST /api/ai/chat/stream | SSE | Assistant output as it is produced, plus heartbeats; see AI streaming. |
curl -N "$CADCAMFUN_URL/api/projects/$PROJECT_ID/events" \
-H "Authorization: Bearer $CADCAMFUN_TOKEN" Clients
@cadcamfun/api/sdk is generated from this same contract: every operation id below is a typed method on CadCam.make(...), taking one flat input of path parameters and body fields. 259 of the 325 operations are generated; each card shows its exact call.
import { CadCam } from "@cadcamfun/api/sdk"
const client = CadCam.make({
baseUrl: process.env.CADCAMFUN_URL!,
headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
})
const projects = await client.projects.list()
const created = await client.projects.create({ name: "Bracket" }) Resources
325 operations in 35 groups, arranged by what they serve.
Core
1 endpointsPublic process health probe with status and timestamp.
2 endpointsAuthenticated readiness and application version used by native clients.
2 endpointsProject-scoped server-sent events for live clients.
4 endpointsJSON-compatible preference and context entries with prefix listing and per-key operations.
2 endpointsUpload and download operations with endpoint-specific payload and response encoding.
Design
5 endpointsCreate, list, read, update, and remove projects with owner and organization access checks.
8 endpointsRead-only project drawings, components, toolpaths, library resources, and bounded previews for companion clients.
7 endpointsProject drawings and their saved geometry, metadata, and update operations.
5 endpointsReusable project components and their persisted design data.
5 endpointsAnalyze exact geometry, export STEP, and inspect assembly relationships from scene snapshots or saved drawings.
8 endpointsShared library records and component, material, and tool lookup collections.
Manufacturing
9 endpointsSaved machining programs, drawing associations, and validated portable manufacturing documents.
2 endpointsProject-scoped toolpath listing and creation with endpoint-specific response envelopes.
5 endpointsNative manufacture, settings-driven G-code generation, suggestions, parsing, and replay verification.
8 endpointsToolpath versions, restoration, library discovery, and threaded program comments.
21 endpointsEstimates, calculation requests, material costs, operation costs, and tool-wear records.
Resources
5 endpointsMaterial records, application machining properties, and resource access.
5 endpointsMaterial storage attachments and JSON import/export for library interchange.
5 endpointsCutter records and dimensions used by application machining workflows.
7 endpointsTool storage data and collection or per-tool import/export.
7 endpointsMachine configuration records, updates, removal, and cloning.
5 endpointsMachine storage attachments and configuration import/export.
Extensions
52 endpointsProviders, credentials, conversations, streaming turns, action invocation, bridge tokens, skills, and session recovery.
22 endpointsProject Git-compatible commits, branches, restores, reviews, GitHub mirroring, and workflow dispatch.
16 endpointsPlugin registry, package installation, configuration, enable/disable, and served plugin assets.
8 endpointsMCP connection configuration CRUD and server-info requests.
5 endpointsDesktop gateway state, enable/disable, device pairing, and device revocation.
Accounts
15 endpointsAccount sign-in, sign-up, recovery, verification, magic links, session lookup, and passkey registration.
18 endpointsProfiles, account resources, API keys, token records, passwords, and account removal.
5 endpointsOrganization lists and managed organization records.
4 endpointsNotification listing, read-state updates, deletion, and mark-all-read.
15 endpointsSubscription information, Stripe checkout/portal integration, trial maintenance, and signed webhook ingestion.
10 endpointsApplication metrics, recent activity, usage queries, and tracking requests.
10 endpointsDesktop integration routes, tracked project operations, notifications, and push-subscription records.
1 endpointsSubmit waitlist registration through the local application API.
OpenAPI document
Download /docs/api/openapi.json (the checked-in snapshot this site renders) or fetch the live document from a running sidecar at /api/openapi.json. Regenerate the snapshot with bun run generate:api-reference in packages/web after changing an endpoint.
Contract and server
@cadcamfun/api defines request and response schemas with Effect HttpApi. It exports the root Api, domain records, tagged errors, and clients. Request handlers, authorization decisions, database queries, and provider calls run in the sidecar. Importing a schema does not start a server.
The sidecar publishes its served contract at GET /api/openapi.json. Use that running document to inspect methods, path parameters, payloads, and status codes for the application you are connected to. The server assembles its groups in apps/sidecar/src/layers.ts; the shared contract is assembled in packages/api/src/index.ts.
Resource families
- Design: projects, drawings, components, drawing versions, entity import/export, and exact CAD analysis, STEP export, and assembly analysis.
- Manufacturing: toolpaths and versions, comments, generator suggestions, parsing, replay verification, native manufacture jobs, materials, tools, machine configurations, library items, and production costs.
- Assistant: providers, credentials, models, sessions, streaming turns, session controls, actions, project memory, workspace context, and stateless advice.
- Collaboration: branches, commits, diffs, pull requests, reviews, GitHub mirrors, workflow files and runs, live events, and companion pairing.
- Application services: users, authentication, organizations, notifications, files, plugins, billing, analytics, waitlist, MCP configuration, and local key-value storage.
The contract groups retain their endpoint-specific response shapes. A client should decode the schema of the operation it calls instead of assuming a single application-wide JSON envelope.
Responses and failures
Common tagged errors map to HTTP 400 (BadRequest), 401 (Unauthorized), 403 (Forbidden), 404 (NotFound), 405 (MethodNotAllowed), 409 (Conflict), and 500 (InternalError). Their declared schemas carry a human-readable message. Some groups use an envelope with success: false, message, and errors; a small number use an error field.
Success responses can be a record, an array, a nullable value, or an envelope. Envelope includes success, message, and data; EnvelopeOpt makes the message optional. Creation endpoints explicitly declare 201 where appropriate. Do not infer success solely from a JSON field without checking the HTTP status and endpoint schema.
Schema decoding validates transport input before the handler executes. Business validation still runs in the service: a structurally valid request may refer to an inaccessible drawing, contain a stale manufacturing artifact, or request a conflicting branch operation.
Use the shared client
ApiClient.layer takes a baseUrl and application token. It supplies the fetch transport and the client authorization middleware. Its methods are derived directly from Api, so this client also covers operations omitted by code generation.
import { ApiClient } from "@cadcamfun/api"
import { Effect } from "effect"
const projects = Effect.gen(function* () {
const api = yield* ApiClient
return yield* api.projects.list()
}).pipe(Effect.provide(ApiClient.layer({ baseUrl, token }))) The base URL is the sidecar's loopback address and assigned port. Resolve it from the desktop connection, rather than persisting a port across launches. Keep tokens out of URLs and logs.
Design and manufacturing requests
Project operations use /api/projects; drawings and toolpaths have their own collections and detail routes. POST /api/toolpaths/generate produces G-code, parsed program data, warnings, and statistics from generator settings and geometry. /suggest, /parse, and /verify expose parameter advice, G-code interpretation, and stock replay. These computations do not create a saved toolpath.
POST /api/toolpaths/manufacture accepts a versioned CAD snapshot and returns a kernel result with NC, tool assignments, cutting data, claims, issues, and a release level. Save a resulting document separately through a toolpath create or update operation. See Setups for evidence validation during persistence.
POST /api/cad/exact/analyze, /step, and /assembly accept explicit elements or a stored drawing identifier. Reading a stored drawing applies the caller's normal drawing access checks.
Streaming and recovery
The AI stream carries typed events for text, reasoning, tool calls and results, permission and question requests, retries, turn state, context, and completion. Clients must consume events incrementally and retain the session identifier. An HTTP connection ending is not sufficient evidence that a model turn finished: session state can be read again after reconnecting.
AI event schemas live in packages/api/src/ai-events.ts and packages/ai/src/events.ts. General live events use the events group. Binary downloads, JavaScript plugin bootstrap responses, and signed raw webhook bodies require their own transport handling.
List routes that page their results use page and limit query parameters. For machine configurations, page defaults to 1, limit defaults to 20 and is clamped to 1–100, and the response carries pagination with page, limit, total, and totalPages (apps/sidecar/src/http/machine-configs.ts). Check each group's reference page for the parameters it actually declares.
Generated SDKs
@cadcamfun/httpapi-codegen reflects HttpApi groups into operation metadata and generated clients. The API generator writes a Promise SDK to packages/api/src/sdk/generated and Effect clients to packages/api/src/client/generated. The public Promise SDK is exported as @cadcamfun/api/sdk.
bun run --filter @cadcamfun/api generate
bun run --filter @cadcamfun/api generate:check Both generated targets omit profile multipart upload, plugin multipart installation, MCP creation with multiple success schemas, MCP update with colliding identifiers, project toolpath creation with duplicate input names, and plugin file serving with stream headers. The Promise target also omits Stripe raw webhooks, plugin JavaScript bootstrap, binary file download, and the generator's generate/suggest requests. These omissions are explicit in packages/api/scripts/generate-clients.ts; use the contract client or the appropriate raw transport for those operations.
Source organization
groups/ contains resource contracts. Shared geometry and CAM schemas come from @cadcamfun/core; cad-exact.ts, cam-kernel.ts, and cam-program.ts describe rich CAD/CAM results and portable documents. client.ts builds the contract client, while the generation script owns generated targets and omission lists.
Integration rules
Reuse contract schemas at transport boundaries and keep database dependencies in the sidecar. Introduce an endpoint through its contract, handler, service or repository, and focused HTTP coverage together. Generated files are outputs: edit their contract or generator and regenerate them. An API schema version, a portable file version, and a plugin API version describe separate contracts.
Resource reference
325 operations across 232 paths and 35 resource groups, with 56 named schemas. Each resource page lists its operations and shows declared path/query/header parameters, required and optional fields, nullable values, content types, success and error statuses, and full schemas.
The data is emitted from packages/api/src/index.ts, the same composed HttpApi contract used by the clients and sidecar. The pages describe the checked-out contract; inspect the running server's /api/openapi.json if you connect to another version.
HTTP resource
Health
Public process health probe with status and timestamp.
HTTP resource
System
Authenticated readiness and application version used by native clients.
HTTP resource
Projects
Create, list, read, update, and remove projects with owner and organization access checks.
HTTP resource
Workspace
Read-only project drawings, components, toolpaths, library resources, and bounded previews for companion clients.
HTTP resource
Drawings
Project drawings and their saved geometry, metadata, and update operations.
HTTP resource
Components
Reusable project components and their persisted design data.
HTTP resource
Exact CAD
Analyze exact geometry, export STEP, and inspect assembly relationships from scene snapshots or saved drawings.
HTTP resource
Toolpaths
Saved machining programs, drawing associations, and validated portable manufacturing documents.
HTTP resource
Project toolpaths
Project-scoped toolpath listing and creation with endpoint-specific response envelopes.
HTTP resource
Machining
Native manufacture, settings-driven G-code generation, suggestions, parsing, and replay verification.
HTTP resource
Toolpath history
Toolpath versions, restoration, library discovery, and threaded program comments.
HTTP resource
Materials
Material records, application machining properties, and resource access.
HTTP resource
Material storage
Material storage attachments and JSON import/export for library interchange.
HTTP resource
Tools
Cutter records and dimensions used by application machining workflows.
HTTP resource
Tool storage
Tool storage data and collection or per-tool import/export.
HTTP resource
Machines
Machine configuration records, updates, removal, and cloning.
HTTP resource
Machine storage
Machine storage attachments and configuration import/export.
HTTP resource
Library
Shared library records and component, material, and tool lookup collections.
HTTP resource
Production costs
Estimates, calculation requests, material costs, operation costs, and tool-wear records.
HTTP resource
AI sessions and actions
Providers, credentials, conversations, streaming turns, action invocation, bridge tokens, skills, and session recovery.
HTTP resource
History and workflows
Project Git-compatible commits, branches, restores, reviews, GitHub mirroring, and workflow dispatch.
HTTP resource
Project events
Project-scoped server-sent events for live clients.
HTTP resource
Companion pairing
Desktop gateway state, enable/disable, device pairing, and device revocation.
HTTP resource
Plugins
Plugin registry, package installation, configuration, enable/disable, and served plugin assets.
HTTP resource
MCP configuration
MCP connection configuration CRUD and server-info requests.
HTTP resource
Files
Upload and download operations with endpoint-specific payload and response encoding.
HTTP resource
Key-value storage
JSON-compatible preference and context entries with prefix listing and per-key operations.
HTTP resource
Organizations
Organization lists and managed organization records.
HTTP resource
Notifications
Notification listing, read-state updates, deletion, and mark-all-read.
HTTP resource
Authentication
Account sign-in, sign-up, recovery, verification, magic links, session lookup, and passkey registration.
HTTP resource
Users
Profiles, account resources, API keys, token records, passwords, and account removal.
HTTP resource
Billing
Subscription information, Stripe checkout/portal integration, trial maintenance, and signed webhook ingestion.
HTTP resource
Analytics
Application metrics, recent activity, usage queries, and tracking requests.
HTTP resource
Application services
Desktop integration routes, tracked project operations, notifications, and push-subscription records.
HTTP resource
Waitlist
Submit waitlist registration through the local application API.
Download OpenAPI JSON · Follow requests with captured responses
Connection and request conventions
The API is supplied by the local sidecar rather than a fixed hosted endpoint. Tauri obtains its dynamically selected loopback URL and launch token. A manually started sidecar announces its port in a JSON ready event. A paired mobile client connects through its configured HTTPS gateway instead.
curl --silent --show-error "$CADCAMFUN_URL/api/projects" \
--header "Authorization: Bearer $CADCAMFUN_TOKEN" Set both variables from the actual connection. Request templates on resource pages deliberately use placeholders and payload files. Optional transport fields are not promises that every business operation can omit them: project creation, for example, rejects a missing name in its handler.
| Convention | Client behavior |
|---|---|
| Path parameters | Replace the named segment and URL-encode its value. Treat an identifier as a single segment. |
| Query parameters | Encode declared values. Pagination and filtering are per-endpoint; there is no universal page-size contract. |
| JSON payload | Send the declared object with Content-Type: application/json. Required presence and accepting null are independent. |
| Multipart payload | Build form parts with the upload client or FormData; let the transport choose its boundary. |
| Binary, JavaScript, or stream response | Consume the declared media type. Do not call response.json() unconditionally. |
| Errors | Check HTTP status and decode the endpoint's declared failure shape. Error envelopes differ across resource families. |
| Retried writes | Read state after an interrupted operation before resubmitting a mutation. The contract does not provide a universal idempotency-key mechanism. |
Generated reference maintenance
packages/web/script/generate-api-reference.mjs reads the composed contract using the API package's installed Effect implementation and writes the reference JSON. The documentation Worker consumes the generated content; it does not initialize the application server to answer documentation requests.
bun run generate:api-reference
bun run check:api-reference
bun run check:docs-index Resource coverage is checked against every declared operation. A newly added group must receive reader-facing metadata and navigation, and a changed request or response must be regenerated. Handwritten guides still explain authorization rules, side effects, service configuration, and limits that an HTTP schema alone cannot express.
Integration recipes
Start with captured HTTP requests to see how project creation, business validation, bearer rejection, related records, and key-value persistence actually respond. Use typed client integration to reproduce those operations with the Promise SDK or Effect client and handle their distinct failure channels.
| Integration | Procedure | Key state to retain |
|---|---|---|
| Project editor | Create, save, and reopen work | Project/resource identity, saved data, actual update semantics. |
| Manufacturing pipeline | Generate and persist a native job | Captured request, exact NC/program, release claims, matching portable document. |
| Assistant UI | Consume events and recover sessions | Project/session identity, pending permissions/questions, terminal turn state. |
| External capability | Author a supported plugin | Manifest, module exports, capability grant, argument validation and tool result. |
| Review automation | Version and review project work | Commit/ref, structural diff, reviews, committed workflow, individual check outputs. |
| Paired client | Enable and manage device access | Gateway address, certificate fingerprint, individually revocable device token. |
These recipes connect HTTP contracts to real service behavior. A schema can describe required presence, encoding, and a returned shape; its linked guide explains access rules, persistence effects, supported recovery, and limits that cannot be inferred from those types alone.
Operations per resource group
The contract currently declares 270 operations in 34 groups, all under a single bearer HTTP security scheme. The only operation without bearer security is the public health probe. The table is computed from the generated OpenAPI document: operations per group, the HTTP methods used, how many distinct paths, and one representative path.
| Group | Tag | Ops | Methods | Paths | Example path |
|---|---|---|---|---|---|
| Health | health | 1 | GET 1 | 1 | /api/health |
| System | system | 2 | GET 2 | 2 | /health |
| Projects | projects | 5 | DELETE 1, GET 2, POST 1, PUT 1 | 2 | /api/projects |
| Drawings | drawings | 5 | DELETE 1, GET 2, POST 1, PUT 1 | 2 | /api/drawings/{id} |
| Components | components | 5 | DELETE 1, GET 2, POST 1, PUT 1 | 2 | /api/components/{id} |
| Exact CAD | cadExact | 3 | POST 3 | 3 | /api/cad/exact/analyze |
| Toolpaths | toolpaths | 7 | DELETE 1, GET 3, POST 2, PUT 1 | 3 | /api/drawings/{id}/toolpaths |
| Project toolpaths | projectToolpaths | 2 | GET 1, POST 1 | 1 | /api/projects/{id}/toolpaths |
| Machining | toolpathGenerator | 5 | POST 5 | 5 | /api/toolpaths/generate |
| Toolpath history | toolpathExtras | 8 | DELETE 1, GET 3, POST 3, PUT 1 | 5 | /api/toolpaths/library |
| Materials | materials | 5 | DELETE 1, GET 2, POST 1, PUT 1 | 2 | /api/materials |
| Material storage | materialsStorage | 5 | DELETE 1, GET 2, POST 2 | 2 | /api/materials/export-import |
| Tools | tools | 5 | DELETE 1, GET 2, POST 1, PUT 1 | 2 | /api/tools |
| Tool storage | toolsStorage | 7 | DELETE 1, GET 3, POST 3 | 3 | /api/tools/export-import |
| Machines | machineConfigs | 6 | DELETE 1, GET 2, POST 2, PUT 1 | 3 | /api/machine-configs |
| Machine storage | machineConfigsStorage | 5 | DELETE 1, GET 2, POST 2 | 2 | /api/machine-configs/export-import |
| Library | library | 8 | DELETE 1, GET 5, POST 1, PUT 1 | 5 | /api/library |
| Production costs | production-costs | 21 | DELETE 4, GET 8, POST 5, PUT 4 | 9 | /api/production-costs/estimates |
| AI sessions and actions | ai | 34 | DELETE 3, GET 8, POST 21, PUT 2 | 32 | /api/ai/actions |
| History and workflows | vcs | 22 | GET 10, POST 11, PUT 1 | 19 | /api/projects/{id}/actions/dispatch |
| Project events | events | 1 | GET 1 | 1 | /api/projects/{id}/events |
| Companion pairing | companion | 5 | DELETE 1, GET 1, POST 3 | 5 | /api/companion |
| Plugins | plugins | 16 | DELETE 1, GET 8, PATCH 1, POST 4, PUT 2 | 12 | /api/plugins |
| MCP configuration | mcp | 8 | DELETE 2, GET 2, POST 2, PUT 2 | 3 | /api/mcp/config |
| Files | files | 2 | GET 1, POST 1 | 2 | /api/download |
| Key-value storage | kv | 4 | DELETE 1, GET 2, PUT 1 | 2 | /api/kv |
| Organizations | organizations | 5 | DELETE 1, GET 2, POST 1, PUT 1 | 2 | /api/organizations |
| Notifications | notifications | 4 | DELETE 1, GET 1, POST 1, PUT 1 | 3 | /api/notifications |
| Authentication | auth | 12 | GET 1, POST 11 | 12 | /api/auth/forgot-password |
| Users | user | 16 | DELETE 2, GET 10, POST 2, PUT 2 | 12 | /api/user/api-keys |
| Billing | billing | 15 | DELETE 1, GET 5, POST 8, PUT 1 | 10 | /api/better-auth-stripe/billing-portal |
| Analytics | analytics | 10 | DELETE 1, GET 7, POST 2 | 9 | /api/analytics |
| Application services | misc | 10 | DELETE 2, GET 3, POST 4, PUT 1 | 6 | /api/app-control/notify |
| Waitlist | waitlist | 1 | POST 1 | 1 | /api/waitlist |
Status codes across the contract
Counting each declared response once per operation gives this picture of what a client must be ready to decode:
| Status | Declared on | Typical body |
|---|---|---|
| 200 | 242 operations | Resource, array, nullable value or Envelope |
| 201 | 28 operations | The created record (for example POST /api/projects) |
| 204 | 1 operation | No body |
| 400 | 206 operations | BadRequest, EnvBadRequest and family-specific variants |
| 401 | 269 operations | Unauthorized (bearer middleware) |
| 403 | 101 operations | Forbidden / EnvForbidden |
| 404 | 149 operations | NotFound / EnvNotFound |
| 405 | 30 operations | EnvMethodNotAllowed / KeyedMethodNotAllowed |
| 409 | 29 operations | Conflict / EnvConflict |
| 500 | 264 operations | InternalError, EnvInternal, KeyedInternal and family variants |
| 501, 503 | 1 operation each | Endpoint-specific |
Every error is an Effect tagged error, so its JSON body always contains a _tag discriminator next to its fields. There are three body families, inherited from the legacy handlers so existing clients keep working:
{ "_tag": "NotFound", "message": "Project not found" } { "_tag": "EnvNotFound", "success": false, "message": "Material not found", "errors": null } { "_tag": "KeyedInternal", "error": "Failed to load components" } Success envelopes mirror the error envelope: { success: true, message, data }, where data may be null. The EnvelopeOpt variant omits message when the handler did not provide one. Switch on _tag rather than on the presence of message or error.
How a request is processed
- The router matches method and path. Unknown routes never reach a handler.
- The bearer middleware compares the token in constant time. A missing or wrong token stops the request with 401 before any decoding.
- Path, query, headers and body are decoded against the operation's schemas. Structural problems become 400 without running business code.
- The handler resolves the acting account, checks ownership or organization membership (403/404) and runs the service.
- The result is encoded with the declared success schema, or the failure with its tagged error schema and status.
Responses that are not JSON
| Operation | Media type | How to consume |
|---|---|---|
POST /api/ai/chat/stream | text/event-stream | Read incrementally; each data: line is one typed assistant event. |
GET /api/projects/{id}/events | text/event-stream | Live project events; reconnect and re-read state after a drop. |
GET /api/plugins/bootstrap.js | application/javascript | Loaded by the plugin host, not parsed as JSON. |
GET /api/plugins/serve | application/octet-stream | Plugin file bytes. |
GET /api/download | application/zip | Save as a file; use response.blob() or stream to disk. |
The generated Promise SDK rejects a streaming response whose content type is not text/event-stream with ClientError("UnsupportedContentType"), and a single SSE event larger than 16 MiB with SseEventTooLarge.
Calling the API without a client
type TaggedError = { _tag: string; message?: string; error?: string }
async function call<T>(base: string, token: string, method: string, path: string, body?: unknown): Promise<T> {
const response = await fetch(new URL(path, base), {
method,
headers: {
authorization: `Bearer ${token}`,
...(body === undefined ? {} : { "content-type": "application/json" }),
},
body: body === undefined ? undefined : JSON.stringify(body),
})
if (response.status === 204) return undefined as T
const payload = await response.json()
if (!response.ok) {
const failure = payload as TaggedError
throw new Error(`${response.status} ${failure._tag}: ${failure.message ?? failure.error}`)
}
return payload as T
}
const project = await call<{ id: string; name: string }>(
process.env.CADCAMFUN_URL!, process.env.CADCAMFUN_TOKEN!,
"POST", "/api/projects", { name: "Bracket" },
) Prefer the generated clients in TypeScript: they know each operation's success status and declared error statuses, and treat anything else as UnexpectedStatus instead of guessing.