Skip to content
CADCAMFUN
Docs

Documentation

API walkthrough with captured responses

Exercise health, authorization, project creation, and preference persistence with real handler responses from an isolated database.

Environment and captured responses

The responses on this page were captured from the actual sidecar routes on 15 October 2026 using apps/sidecar/test/helpers.ts. That harness builds the application handlers with a migrated in-memory SQLite database, a disposable file directory, the direct AI host, and no provider calls. The requests go through the HTTP router in-process; this run does not exercise the Tauri launcher, network sockets, TLS, or a paired phone.

The response bodies below are unedited. Identifiers and timestamps therefore belong to that disposable run. Your instance returns its own values. Use the project identifier returned by your create request rather than reuse the captured identifier.

Start a disposable real HTTP instance from the repository root
CADCAMFUN_TOKEN=local-development-token \
CADCAMFUN_DATA_DIR=/tmp/cadcamfun-api-walkthrough \
CADCAMFUN_MIGRATIONS_DIR="$PWD/packages/db/drizzle" \
CADCAMFUN_AI_HOST=direct \
CADCAMFUN_AI_OFFLINE=1 \
bun --no-env-file apps/sidecar/src/main.ts

This example token is only for an isolated development process. Choose your own value, keep the terminal open, and read the port from the JSON ready event. In a second terminal, set the connection variables below after replacing READY_PORT. The sidecar chooses a new port on another launch.

Connection variables in the second terminal
export CADCAMFUN_URL="http://127.0.0.1:READY_PORT"
export CADCAMFUN_TOKEN="local-development-token"

The on-disk development database differs from the capture's in-memory database. If you reuse that data directory, previously created projects and preferences remain. Use a separate disposable directory for a fresh run. The packaged desktop uses its native application data directory instead.

Check health

/api/health is the public probe. It confirms that this route answers; it does not test credentials, a model provider, or manufacturing resources.

bash
curl --silent --show-error "$CADCAMFUN_URL/api/health"
Captured HTTP 200
{
  "status": "ok",
  "timestamp": "2026-10-15T02:43:50.682Z"
}

The native /health and /version operations require the application bearer token. Read their exact contracts in the system reference.

Understand authorization

A project request without a bearer token is rejected before project data is returned.

bash
curl --silent --show-error --include "$CADCAMFUN_URL/api/projects"
Captured HTTP 401
{
  "_tag": "Unauthorized",
  "message": "Unauthorized"
}

The error contains its tagged error name and a readable message. Do not parse the message as a stable error code. HTTP status, the endpoint's schema, and its declared tag together describe the failure.

Use Authorization: Bearer … for admitted application calls. An optional x-session-token selects an account session after bearer admission. AI bridge tokens can call only the two action bridge routes; they cannot substitute for an application token in this walkthrough. Companion tokens are accepted by the paired gateway with its own route policy.

Read and create a project

bash
curl --silent --show-error "$CADCAMFUN_URL/api/projects" \
  --header "Authorization: Bearer $CADCAMFUN_TOKEN"
Captured HTTP 200 on an empty working copy
[]

The response is a plain array, without a data or success wrapper. A structurally valid but incomplete create request is rejected by business validation:

bash
curl --silent --show-error --request POST "$CADCAMFUN_URL/api/projects" \
  --header "Authorization: Bearer $CADCAMFUN_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{}'
Captured HTTP 400
{
  "_tag": "BadRequest",
  "message": "Project name is required"
}

The transport schema makes name optional, but the handler requires a non-empty value. To create the project:

bash
curl --silent --show-error --request POST "$CADCAMFUN_URL/api/projects" \
  --header "Authorization: Bearer $CADCAMFUN_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{"name":"API walkthrough","description":"Disposable documentation example"}'
Captured HTTP 201
{
  "id": "ccaff34c-49f3-4a23-a6b6-427745f9641a",
  "name": "API walkthrough",
  "description": "Disposable documentation example",
  "createdAt": "2026-10-15T02:43:50.741Z",
  "updatedAt": "2026-10-15T02:43:50.741Z",
  "ownerId": "894c5064-576e-4e43-b7f0-79c6120e8345",
  "organizationId": null,
  "isPublic": false
}

The create result is the new project row. Omitted isPublic becomes false in this run; no organization is selected. The owner is the acting local profile. Assigning an organization requires membership; updating an existing project also checks its owner or organization role.

Read back related data

Copy the identifier returned by your create request into PROJECT_ID, then read the detail route:

bash
export PROJECT_ID="your-returned-project-id"
curl --silent --show-error "$CADCAMFUN_URL/api/projects/$PROJECT_ID" \
  --header "Authorization: Bearer $CADCAMFUN_TOKEN"
Captured HTTP 200
{
  "id": "ccaff34c-49f3-4a23-a6b6-427745f9641a",
  "name": "API walkthrough",
  "description": "Disposable documentation example",
  "createdAt": "2026-10-15T02:43:50.741Z",
  "updatedAt": "2026-10-15T02:43:50.741Z",
  "ownerId": "894c5064-576e-4e43-b7f0-79c6120e8345",
  "organizationId": null,
  "isPublic": false,
  "owner": {
    "id": "894c5064-576e-4e43-b7f0-79c6120e8345",
    "name": "Local user",
    "email": "local@cadcamfun.local"
  },
  "organization": null,
  "_count": {
    "drawings": 0,
    "components": 0
  }
}

Detail includes the owner, nullable organization, and drawing/component counts. Creation and retrieval have related but different response schemas. A missing or inaccessible project returns 404 with Project not found or access denied; callers should not infer a private project's existence from that result.

Projects API also documents update and deletion. Updating requires a non-empty name; deleting requires the owner or an organization administrator. Do not implement update as an arbitrary JSON patch without following its payload contract.

Paged lists such as machine configurations accept page (default 1) and limit (default 20, maximum 100) and return a pagination object with total and totalPages. Request the next page instead of raising limit past the cap; larger values are clamped to 100.

Persist a preference

The key-value API demonstrates a second response shape and missing-resource behavior. A key that has not been saved returns 404:

bash
curl --silent --show-error "$CADCAMFUN_URL/api/kv/docs.walkthrough.units" \
  --header "Authorization: Bearer $CADCAMFUN_TOKEN"
Captured HTTP 404
{
  "_tag": "NotFound",
  "message": "Key not found"
}

Save a JSON-compatible value with PUT. This is a preference example; it does not globally change the geometry kernel's units.

bash
curl --silent --show-error --request PUT "$CADCAMFUN_URL/api/kv/docs.walkthrough.units" \
  --header "Authorization: Bearer $CADCAMFUN_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{"value":"mm"}'
Captured HTTP 200
{
  "key": "docs.walkthrough.units",
  "value": "mm",
  "updatedAt": "2026-10-15T02:43:50.755Z"
}

Reading the same key returns the stored entry, including its update timestamp. The response does not wrap the value in a project record or success envelope.

Captured subsequent GET, HTTP 200
{
  "key": "docs.walkthrough.units",
  "value": "mm",
  "updatedAt": "2026-10-15T02:43:50.755Z"
}

Use GET /api/kv?prefix=docs.walkthrough. to list matching entries, or DELETE the encoded key to remove it. The store rejects blank keys, overlong keys, and values outside its JSON-compatible domain. It is not a credential vault.

Handle failures and retries

ResultNext action
401 on a protected callVerify the current launch token and its type; use the newly announced URL after a restart.
400 on project creationRead the business error and correct the request; resending the same missing name will fail again.
404 on a project or preferenceCheck the identifier/key and acting account; apply the resource's missing/access policy.
Connection loss during a writeRead back the resulting resource or state before repeating the write. These create endpoints do not declare an idempotency-key contract.
5xxInspect the sidecar logs and failed service. Do not assume a response error proves that no earlier persistent operation took effect.

In production clients, check response.ok and decode the appropriate success or error body. Avoid relying on a uniform envelope: this walkthrough alone includes an array, plain records, and tagged failures.

Next integration steps

Use the full reference to select a resource. The machining endpoints distinguish computation from saving a toolpath; the history endpoints distinguish working-copy changes from commits and remote synchronization. The AI resource covers session identifiers and streaming controls.

Read the running sidecar's /api/openapi.json when integrating a different build. The downloadable documentation snapshot describes the checked-out contract; it cannot establish which binary another machine is running.

All captured responses at a glance

The responses on this page were captured from a real sidecar with a fresh database. Identifiers and timestamps will differ on your machine; shapes and statuses will not.

StepPathStatusBody (truncated)
Public health/api/health200{"status": "ok", "timestamp": "2026-10-15T02:43:50.682Z"}
Missing bearer/api/projects401{"_tag": "Unauthorized", "message": "Unauthorized"}
Empty projects/api/projects200[]
Missing project name/api/projects400{"_tag": "BadRequest", "message": "Project name is required"}
Create project/api/projects201{"id": "ccaff34c-49f3-4a23-a6b6-427745f9641a", "name": "API walkthrough", "description": "Disposable documenta…
Read project/api/projects/ccaff34c-49f3-4a23-a6b6-427745f9641a200{"id": "ccaff34c-49f3-4a23-a6b6-427745f9641a", "name": "API walkthrough", "description": "Disposable documenta…
Missing preference/api/kv/docs.walkthrough.units404{"_tag": "NotFound", "message": "Key not found"}
Save preference/api/kv/docs.walkthrough.units200{"key": "docs.walkthrough.units", "value": "mm", "updatedAt": "2026-10-15T02:43:50.755Z"}
Read preference/api/kv/docs.walkthrough.units200{"key": "docs.walkthrough.units", "value": "mm", "updatedAt": "2026-10-15T02:43:50.755Z"}

The whole tour as one script

tour.sh
#!/usr/bin/env bash
set -euo pipefail
: "${CADCAMFUN_URL:?set to the sidecar URL}" "${CADCAMFUN_TOKEN:?set to the launch token}"
auth=(--header "Authorization: Bearer $CADCAMFUN_TOKEN")
json=(--header "Content-Type: application/json")

curl -sS "$CADCAMFUN_URL/api/health"; echo
curl -sS -o /dev/null -w "no token -> %{http_code}\n" "$CADCAMFUN_URL/api/projects"
curl -sS "${auth[@]}" "$CADCAMFUN_URL/api/projects"; echo
curl -sS "${auth[@]}" "${json[@]}" -d '{}' "$CADCAMFUN_URL/api/projects"; echo   # 400

id=$(curl -sS "${auth[@]}" "${json[@]}" \
  -d '{"name":"API walkthrough","description":"Disposable documentation example"}' \
  "$CADCAMFUN_URL/api/projects" | sed -E 's/.*"id":"([^"]+)".*/\1/')
curl -sS "${auth[@]}" "$CADCAMFUN_URL/api/projects/$id"; echo

key=docs.walkthrough.units
curl -sS -w " %{http_code}\n" "${auth[@]}" "$CADCAMFUN_URL/api/kv/$key"   # 404 first time
curl -sS -X PUT "${auth[@]}" "${json[@]}" -d '{"value":{"units":"mm"}}' "$CADCAMFUN_URL/api/kv/$key"; echo
curl -sS "${auth[@]}" "$CADCAMFUN_URL/api/kv/$key"; echo

The script uses sed to extract the id so it has no dependencies; with jq installed, prefer jq -r .id. Run it against a disposable data directory: it creates a real project.

Clean up after the tour

Remove what the tour created
curl -sS -X DELETE --header "Authorization: Bearer $CADCAMFUN_TOKEN" "$CADCAMFUN_URL/api/projects/$id"
curl -sS -X DELETE --header "Authorization: Bearer $CADCAMFUN_TOKEN" "$CADCAMFUN_URL/api/kv/docs.walkthrough.units"

Deleting the project cascades to its drawings, components, toolpaths, history and workflow runs. The key-value entry is independent and must be removed separately.

In 3D

The API surface the tour walks through Drag to orbit · scroll to zoom · right-drag to pan
Every API group as a column, height = operations counted from the generated OpenAPI document (270 in total). Rows are the six sidebar categories; ai (34), history (22) and costs (21) are the largest groups.