service-kicad
Public Made by Adomby adom
Shared headless KiCad 10: DRC, ERC, SVG/Gerber/STEP export, Altium library conversion, symbol/footprint/3D-model lookup. Every Adom tool shells to this CLI instead of calling the HTTP API directly.
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(matchesservice.json::api_version). - Compatibility: clients check
/versionon 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.
# 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
```json
{ "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.