service-kicad API contract

HTTP API for the service-kicad container. Every Adom tool that needs headless KiCad or the stock library hits this surface.

Version

  • API version: 1.0.0 (matches service.json::api_version).
  • Compatibility: clients check /version on startup and refuse to connect when major differs.
  • Service is stateless — safe to restart at any time.

Versioning

GET /version
→ { "service": "service-kicad", "version": "0.0.1", "api_version": "1.0.0" }

GET /health
→ { "ok": true, "service": "service-kicad", "version": "0.0.1",
    "kicad_version": "9.0.8" }

Consumers: adom-cli carbon watchdog, aci doctor, CI smoke.

Auth

Per PLAN decision 17 (Adom-platform JWT). Authorization: Bearer <jwt>. Service validates against carbon.adom.inc's JWKS. Dev: no auth.

kicad-cli PCB operations

POST /kicad/pcb/drc
  Request body:  <raw .kicad_pcb bytes>
  Content-Type:  application/octet-stream
  Response:      application/json — same shape as `kicad-cli pcb drc
                 --format json` output.

POST /kicad/pcb/export/svg?side=top|bottom
  Request body:  <raw .kicad_pcb bytes>
  Response:      image/svg+xml

POST /kicad/pcb/export/gerbers
  Request body:  <raw .kicad_pcb bytes>
  Response:      application/x-tar — the full fab layer set
                 (F.Cu, B.Cu, F.Mask, B.Mask, F.Silkscreen,
                  B.Silkscreen, Edge.Cuts).

POST /kicad/pcb/export/step
  Request body:  <raw .kicad_pcb bytes>
  Response:      model/step — with component 3D models substituted
                 (--subst-models --no-dnp).

POST /kicad/pcb/export/glb
  Request body:  <raw .kicad_pcb bytes>
  Response:      model/gltf-binary — with component 3D models.

kicad-cli schematic operations

POST /kicad/sch/erc
  Request body:  <raw .kicad_sch bytes>
  Response:      application/json — same shape as `kicad-cli sch erc
                 --format json`.

POST /kicad/sch/export/svg
  Request body:  <raw .kicad_sch bytes>
  Response:      image/svg+xml

POST /kicad/sch/export/pdf
  Request body:  <raw .kicad_sch bytes>
  Response:      application/pdf

POST /kicad/sch/export/bom
  Request body:  <raw .kicad_sch bytes>
  Response:      text/csv

Symbol + footprint lookup (by library + name)

Convenience wrappers for callers that know the canonical library/name but don't ship a local copy of the source file.

GET /sym/export/svg/:library/:name
  Path params:   library (e.g. "Device"), name (e.g. "R")
  Response:      image/svg+xml — rendered via `kicad-cli sym export svg`
                 on /usr/share/kicad/symbols/<library>.kicad_sym.

GET /fp/export/svg/:library/:name
  Path params:   library (e.g. "Package_SO"), name (e.g. "SOT-23")
  Response:      image/svg+xml — rendered via `kicad-cli fp export svg`
                 on /usr/share/kicad/footprints/<library>.pretty/<name>.kicad_mod.

Static library mounts

The ~5 GB kicad-packages3d library + the symbol/footprint trees are served read-only as static files. Clients stream whatever they need (most call sites only need a handful at a time).

GET /models/<path>        → static from /usr/share/kicad/3dmodels/
GET /footprints/<path>    → static from /usr/share/kicad/footprints/
GET /symbols/<path>       → static from /usr/share/kicad/symbols/

Example: curl -o LM1117.step $KICAD_SERVICE_API/models/Package_TO_SOT_SMD.3dshapes/SOT-223.step

Rate limits

  • kicad-cli endpoints (/kicad/*): 30 req/min/user, burst 10.
  • Static library (/models, /footprints, /symbols): 600 req/min/user, no burst cap — it's just disk reads.
  • Exceeding → HTTP 429 with Retry-After.

Error shape

{ "error": "human-readable message", "code": 400 }

Body is always JSON for error responses; HTTP status carries the primary signal.

Port configuration

The binary honors $PORT. Default 8780 (matches the legacy service- kicad container's port, so consumers that already point at 8780 migrate cleanly).

Stability policy

  • Major bump: any breaking change to an existing endpoint's request or response shape.
  • Minor bump: new endpoints.
  • Patch bump: bug fixes, dependency updates, no contract change.

Every bump edits service.json::api_version AND this doc's header.