Skip to content
CADCAMFUN
Docs

Documentation

Exact CAD

Analyze exact geometry, export STEP, and inspect assembly relationships from scene snapshots or saved drawings.

Playground

Send these requests to your own running sidecar. Values stay in this browser.

Not connected
How this works

The sidecar listens on a loopback port chosen at startup and prints it in its ready line; use that URL and the CADCAMFUN_TOKEN it was started with. Requests go straight from this page to that address.

The sidecar sends CORS headers only to the Tauri origins and to http://localhost or http://127.0.0.1 on any port. From the hosted docs the browser blocks the response, so run the docs locally (bun run dev in packages/web) to use the playground, or copy the request as curl. To experiment without touching real data, start the sidecar with CADCAMFUN_DATA_DIR pointed at a throwaway directory — see the API walkthrough.

Operations

5 endpoints in the cadExact group, generated from the sidecar's own OpenAPI document. Protected operations take Authorization: Bearer $CADCAMFUN_TOKEN; see authentication. Behaviour and limits are in the subsystem guide.

post /api/cad/exact/analyze cadExact.analyze
post /api/cad/exact/step cadExact.step
post /api/cad/exact/assembly cadExact.assembly
post /api/cad/exact/setups cadExact.setups
post /api/cad/exact/hole cadExact.hole
Exact CAD operations in 3D Drag to orbit · scroll to zoom · right-drag to pan
One block per operation (5), stacked per resource section of this page and coloured by method: green GET, orange POST, blue PUT, violet PATCH, red DELETE. Generated from the OpenAPI document at build time.

/api/cad/exact

post /api/cad/exact/analyze # cadExact.analyze

Requires Authorization: Bearer <token>.

Request body · required · application/json
{
  elements?: object[]
  drawingId?: string
  ids?: string[]
  machining?: boolean
}
Responses
200 object application/json
{
  parts: Array<{
    id: string
    name: string
    valid: boolean
    issues: string[]
    volume: number
    area: number
    centroid: {
      x: number
      y: number
      z: number
    }
    bounds: {
      min: {
        x: number
        y: number
        z: number
      }
      max: {
        x: number
        y: number
        z: number
      }
    }
    faces: number
    edges: number
    vertices: number
    surfaces: {
      [key: string]: number
    }
    throughHoles?: number
    holes: Array<{
      entry: {
        x: number
        y: number
        z: number
      }
      direction: {
        x: number
        y: number
        z: number
      }
      diameter: number
      depth: number
      form: "simple" | "counterbore" | "countersink"
      bottom: "through" | "flat" | "drill-point"
      headDiameter?: number
      headDepth?: number
    }>
    machining: {
      prismatic: true
      holes: number
      pockets: number
      outlines: number
      top: number
      bottom: number
      islands?: number
      sideHoles?: number
      hiddenFaces?: number
    } | {
      prismatic: false
      reason: string
    }
    bosses: Array<{
      diameter: number
      length: number
      free: "near" | "far" | "both" | "none"
      origin: {
        x: number
        y: number
        z: number
      }
      axis: {
        x: number
        y: number
        z: number
      }
    }>
    nurbsFaces?: Array<{
      face: number
      normal: {
        x: number
        y: number
        z: number
      }
      spread: number
      trimmed: boolean
    }>
    fillets?: Array<{
      face: number
      kind: "cylinder" | "torus"
      radius: number
      convex: boolean
      length: number
    }>
    swarfWalls?: Array<{
      face: number
      kind: "plane" | "cone" | "cylinder"
      near: {
        x: number
        y: number
        z: number
      }
      height: number
      lean: number
      concaveRadius?: number
    }>
    faceNames?: string[]
    repair?: {
      verticesWelded: number
      edgesWelded: number
      collapsedUses: number
      validAfter: boolean
      issuesAfter: string[]
    }
  }>
  skipped: Array<{
    id: string
    name: string
    reason: string
  }>
  totals: {
    parts: number
    volume: number
    area: number
  }
}
400 BadRequestEncoded application/json
BadRequestEncoded
401 UnauthorizedEncoded application/json
UnauthorizedEncoded
403 ForbiddenEncoded application/json
ForbiddenEncoded
404 NotFoundEncoded application/json
NotFoundEncoded
500 InternalErrorEncoded application/json
InternalErrorEncoded
SDK example
cadExact.analyze
import { CadCam } from "@cadcamfun/api/sdk"

const client = CadCam.make({
  baseUrl: process.env.CADCAMFUN_URL!,
  headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
})

// CadExactAnalyzeInput
const result = await client.cadExact.analyze({
  elements: [
    {}
  ],
  drawingId: "",
  ids: [
    ""
  ],
  machining: false
})
curl
POST /api/cad/exact/analyze
curl --request POST "${CADCAMFUN_URL}/api/cad/exact/analyze" \
  --header "Authorization: Bearer ${CADCAMFUN_TOKEN}" \
  --header "Content-Type: application/json" \
  --data-binary @request.json
Try it
post /api/cad/exact/step # cadExact.step

Requires Authorization: Bearer <token>.

Request body · required · application/json
{
  elements?: object[]
  drawingId?: string
  ids?: string[]
  faceted?: boolean
  author?: string
}
Responses
200 object application/json
{
  step?: string
  parts: Array<{
    id: string
    name: string
    exact: boolean
    faces: number
    valid: boolean
    note?: string
  }>
  skipped: Array<{
    id: string
    name: string
    reason: string
  }>
}
400 BadRequestEncoded application/json
BadRequestEncoded
401 UnauthorizedEncoded application/json
UnauthorizedEncoded
403 ForbiddenEncoded application/json
ForbiddenEncoded
404 NotFoundEncoded application/json
NotFoundEncoded
500 InternalErrorEncoded application/json
InternalErrorEncoded
SDK example
cadExact.step
import { CadCam } from "@cadcamfun/api/sdk"

const client = CadCam.make({
  baseUrl: process.env.CADCAMFUN_URL!,
  headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
})

// CadExactStepInput
const result = await client.cadExact.step({
  elements: [
    {}
  ],
  drawingId: "",
  ids: [
    ""
  ],
  faceted: false,
  author: ""
})
curl
POST /api/cad/exact/step
curl --request POST "${CADCAMFUN_URL}/api/cad/exact/step" \
  --header "Authorization: Bearer ${CADCAMFUN_TOKEN}" \
  --header "Content-Type: application/json" \
  --data-binary @request.json
Try it
post /api/cad/exact/assembly # cadExact.assembly

Requires Authorization: Bearer <token>.

Request body · required · application/json
{
  elements?: object[]
  drawingId?: string
  washers?: boolean
}
Responses
200 object application/json
{
  parts: number
  interference: {
    clashes: Array<{
      a: string
      b: string
      aName: string
      bName: string
      volume: number
      centroid: {
        x: number
        y: number
        z: number
      }
    }>
    expected: Array<{
      a: string
      b: string
      aName: string
      bName: string
      volume: number
      note: string
    }>
    touching: Array<{
      a: string
      b: string
    }>
    undetermined: Array<{
      a: string
      b: string
      reason: string
    }>
    checked: number
  }
  clearance?: Array<{
    a: string
    b: string
    aName: string
    bName: string
    distance: number
    overlap: boolean
  }>
  bom: Array<{
    item: number
    name: string
    designation?: string
    material?: string
    quantity: number
    volume: number
    mass?: number
    parts: string[]
  }>
  joints: Array<{
    parent: string
    child: string
    parentName: string
    childName: string
    kind: "revolute" | "fixed"
    origin: {
      x: number
      y: number
      z: number
    }
    axis: {
      x: number
      y: number
      z: number
    }
    axes: number
  }>
  fasteners: {
    plans: Array<{
      id: string
      size: string
      threadName: string
      designation: string
      length: number
      seat: {
        x: number
        y: number
        z: number
      }
      direction: {
        x: number
        y: number
        z: number
      }
      bodies: string[]
      tapped?: string
      grip: number
      engagement?: number
      headWasher?: {
        designation: string
        inner: number
        outer: number
        thickness: number
      }
      nutWasher?: {
        designation: string
        inner: number
        outer: number
        thickness: number
      }
      nutWasherAt?: {
        x: number
        y: number
        z: number
      }
      nut?: {
        designation: string
        across: number
        height: number
        at: {
          x: number
          y: number
          z: number
        }
      }
      warnings: string[]
    }>
    unfastened: Array<{
      bodies: string[]
      at: {
        x: number
        y: number
        z: number
      }
      reason: string
    }>
    existing: number
  }
  skipped: Array<{
    id: string
    name: string
    reason: string
  }>
}
400 BadRequestEncoded application/json
BadRequestEncoded
401 UnauthorizedEncoded application/json
UnauthorizedEncoded
403 ForbiddenEncoded application/json
ForbiddenEncoded
404 NotFoundEncoded application/json
NotFoundEncoded
500 InternalErrorEncoded application/json
InternalErrorEncoded
SDK example
cadExact.assembly
import { CadCam } from "@cadcamfun/api/sdk"

const client = CadCam.make({
  baseUrl: process.env.CADCAMFUN_URL!,
  headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
})

// CadExactAssemblyInput
const result = await client.cadExact.assembly({
  elements: [
    {}
  ],
  drawingId: "",
  washers: false
})
curl
POST /api/cad/exact/assembly
curl --request POST "${CADCAMFUN_URL}/api/cad/exact/assembly" \
  --header "Authorization: Bearer ${CADCAMFUN_TOKEN}" \
  --header "Content-Type: application/json" \
  --data-binary @request.json
Try it
post /api/cad/exact/setups # cadExact.setups

Requires Authorization: Bearer <token>.

Request body · required · application/json
{
  elements?: object[]
  drawingId?: string
  ids?: string[]
  fixture?: "bottom" | "none"
  allowed?: Array<"+Z" | "-Z" | "+X" | "-X" | "+Y" | "-Y">
}
Responses
200 object application/json
{
  parts: Array<{
    id: string
    name: string
    plan: {
      setups: Array<{
        orientation: "+Z" | "-Z" | "+X" | "-X" | "+Y" | "-Y"
        faces: number[]
        area: number
        share: number
        holes: Array<{
          entry: {
            x: number
            y: number
            z: number
          }
          direction: {
            x: number
            y: number
            z: number
          }
          diameter: number
          depth: number
          form: "simple" | "counterbore" | "countersink"
        }>
        prismatic: {
          ok: true
          holes: number
          pockets: number
          outlines: number
        } | {
          ok: false
          reason: string
        }
      }>
      uncovered: Array<{
        face: number
        kind: string
        area: number
        reason: string
      }>
      held: Array<{
        face: number
        kind: string
        area: number
      }>
      indexed: Array<{
        entry: {
          x: number
          y: number
          z: number
        }
        direction: {
          x: number
          y: number
          z: number
        }
        diameter: number
        depth: number
        form: "simple" | "counterbore" | "countersink"
      }>
      reach: Array<{
        orientation: "+Z" | "-Z" | "+X" | "-X" | "+Y" | "-Y"
        faces: number
        area: number
        share: number
      }>
      faces: number
      area: number
      notes: string[]
    }
  }>
  skipped: Array<{
    id: string
    name: string
    reason: string
  }>
}
400 BadRequestEncoded application/json
BadRequestEncoded
401 UnauthorizedEncoded application/json
UnauthorizedEncoded
403 ForbiddenEncoded application/json
ForbiddenEncoded
404 NotFoundEncoded application/json
NotFoundEncoded
500 InternalErrorEncoded application/json
InternalErrorEncoded
fetch example
cadExact.setups
// Not generated in the Promise SDK (multipart, binary or raw body): call it with fetch.
const response = await fetch(`${process.env.CADCAMFUN_URL}/api/cad/exact/setups`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
})
curl
POST /api/cad/exact/setups
curl --request POST "${CADCAMFUN_URL}/api/cad/exact/setups" \
  --header "Authorization: Bearer ${CADCAMFUN_TOKEN}" \
  --header "Content-Type: application/json" \
  --data-binary @request.json
Try it
post /api/cad/exact/hole # cadExact.hole

Requires Authorization: Bearer <token>.

Request body · required · application/json
{
  elements?: object[]
  drawingId?: string
  id: string
  hole?: number
  boss?: number
  fillet?: number
  nurbs?: number
  distance?: number
  direction?: {
    x: number
    y: number
    z: number
  }
  mode?: "move" | "offset" | "draft"
  angle?: number
  neutral?: number
  pull?: {
    x: number
    y: number
    z: number
  }
  tolerance?: number
  radius?: number
  diameter?: number
  taper?: number
  fill?: boolean
}
Responses
200 object | object | object | object | object application/json
{
  ok: true
  id: string
  name: string
  hole: number
  holes: number
  before: {
    diameter: number
    depth: number
    form: "simple" | "counterbore" | "countersink"
  }
  edit: {
    kind: "resize"
    diameter: number
    taper?: number
  } | {
    kind: "fill"
  }
  volume: number
  originalVolume: number
  volumeChange: number
  faces: number
  valid: boolean
} | {
  ok: true
  id: string
  name: string
  boss: number
  bosses: number
  before: {
    diameter: number
    length: number
  }
  diameter: number
  taper?: number
  volume: number
  originalVolume: number
  volumeChange: number
  faces: number
  valid: boolean
} | {
  ok: true
  id: string
  name: string
  fillet: number
  fillets: number
  before: {
    radius: number
    convex: boolean
  }
  radius: number
  volume: number
  originalVolume: number
  volumeChange: number
  faces: number
  valid: boolean
} | {
  ok: true
  id: string
  name: string
  nurbs: number
  nurbsFaces: number
  mode: "move" | "offset" | "draft"
  before: {
    normal: {
      x: number
      y: number
      z: number
    }
    spread: number
  }
  distance?: number
  direction?: {
    x: number
    y: number
    z: number
  }
  angle?: number
  approximate?: {
    deviation: number
  }
  volume: number
  originalVolume: number
  volumeChange: number
  faces: number
  valid: boolean
} | {
  ok: false
  error: string
}
400 BadRequestEncoded application/json
BadRequestEncoded
401 UnauthorizedEncoded application/json
UnauthorizedEncoded
403 ForbiddenEncoded application/json
ForbiddenEncoded
404 NotFoundEncoded application/json
NotFoundEncoded
500 InternalErrorEncoded application/json
InternalErrorEncoded
fetch example
cadExact.hole
// Not generated in the Promise SDK (multipart, binary or raw body): call it with fetch.
const response = await fetch(`${process.env.CADCAMFUN_URL}/api/cad/exact/hole`, {
  method: "POST",
  headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
})
curl
POST /api/cad/exact/hole
curl --request POST "${CADCAMFUN_URL}/api/cad/exact/hole" \
  --header "Authorization: Bearer ${CADCAMFUN_TOKEN}" \
  --header "Content-Type: application/json" \
  --data-binary @request.json
Try it

Schemas

Named schemas reachable from this group's parameters, bodies and responses. A ? marks an optional field; | null marks a field that may be present with a null value.

BadRequestEncoded
{
  _tag: "BadRequest"
  message: string
}
ForbiddenEncoded
{
  _tag: "Forbidden"
  message: string
}
InternalErrorEncoded
{
  _tag: "InternalError"
  message: string
}
NotFoundEncoded
{
  _tag: "NotFound"
  message: string
}
UnauthorizedEncoded
{
  _tag: "Unauthorized"
  message: string
}

Calling this group

Operation ids have the form cadExact.<name>. The generated Promise SDK (@cadcamfun/api/sdk) exposes most of them as client.<namespace>.<method>(input), where input is one flat object of path parameters and body fields; each card's SDK example shows the exact accessor and input type. Multipart uploads, binary or JavaScript responses and raw webhooks are not generated; those cards show fetch instead.

Errors from the Promise SDK
import { CadCam, ClientError } from "@cadcamfun/api/sdk"

const client = CadCam.make({
  baseUrl: process.env.CADCAMFUN_URL!,
  headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
})

try {
  await client.projects.list()
} catch (error) {
  if (error instanceof ClientError) {
    // Transport | UnexpectedStatus | UnsupportedContentType | MalformedResponse | SseEventTooLarge
  } else {
    // a declared error body: switch on error._tag
  }
}

Troubleshooting

SymptomLikely causeFix
401 on every callToken from a previous launch, or missing Bearer prefixSend Authorization: Bearer <token> with the token the sidecar was started with.
400 before anything happensBody or parameter does not match the schemaCompare the payload with the request schema on the card.
403 or 404 on a record you can see elsewhereThe acting account differsSend the right x-session-token, or use the local profile that owns the record.
409Conflicting state, such as a duplicate name or a stale branch headRe-read the resource and retry with current data.
Try it says "blocked by CORS"The docs are served from a non-loopback originRun the docs locally or copy the request as curl.
Connection refusedThe sidecar restarted on a new portRead the port from the new ready line.