Design a KiCad PCB from a prompt: parts, schematic checks, routing, KiCad DRC and Gerbers.
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Bearer sc_… key from Settings → Design from your own AI agent at app.koppar.ai (free sign-up)
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
Lay exact copper by hand where the routers leave a gap: tracks as polylines on one copper layer, and through vias. width_mm, diameter_mm and drill_mm default to the board's current track and via sizes. Nets must exist on the board. Nothing is checked here: run_drc afterwards, and ripup_routing takes copper back out.
The design id returned by import_kicad_project or list_designs.
Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot).
This tool isn't marked read-only, so it may change something on the server or in an account you connected.
Lay exact copper by hand where the routers leave a gap: tracks as polylines on one copper layer, and through vias. width_mm, diameter_mm and drill_mm default to the board's current track and via sizes. Nets must exist on the board. Nothing is checked here: run_drc afterwards, and ripup_routing takes copper back out.
| Argument | Type | Description |
|---|---|---|
| vias | array | |
| tracks | array | |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"vias": {
"type": "array",
"items": {
"type": "object",
"required": [
"net",
"x_mm",
"y_mm"
],
"properties": {
"net": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"x_mm": {
"type": "number"
},
"y_mm": {
"type": "number"
},
"drill_mm": {
"type": "number",
"maximum": 5,
"exclusiveMinimum": 0
},
"diameter_mm": {
"type": "number",
"maximum": 5,
"exclusiveMinimum": 0
}
}
},
"maxItems": 500
},
"tracks": {
"type": "array",
"items": {
"type": "object",
"required": [
"net",
"layer",
"points"
],
"properties": {
"net": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"layer": {
"type": "string",
"pattern": "^(F|B|In\\d{1,2})\\.Cu$"
},
"points": {
"type": "array",
"items": {
"type": "array",
"items": [
{
"type": "number"
},
{
"type": "number"
}
],
"maxItems": 2,
"minItems": 2,
"description": "[x_mm, y_mm]",
"additionalItems": false
},
"maxItems": 500,
"minItems": 2
},
"width_mm": {
"type": "number",
"maximum": 10,
"exclusiveMinimum": 0
}
}
},
"maxItems": 200
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
}
}
}Give the design a footprint of your own: a KiCad .kicad_mod (the file's text) for a package KiCad's libraries lack. It joins the design's "custom" footprint library and is used as "custom:<name>": pass that to create_custom_symbol (footprint=) or name it in the SKiDL script's footprint=; the board builder loads it like a library footprint and the KiCad project download carries it. The pads must be numbered like the pins. The CLI: `koppar footprint <design> part.kicad_mod`.
| Argument | Type | Description |
|---|---|---|
| name | string | The footprint name (default: the name inside the file). |
| design_id* | string | The design id returned by create_design or list_designs. |
| kicad_mod* | string | The .kicad_mod file, as text. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id",
"kicad_mod"
],
"properties": {
"name": {
"type": "string",
"maxLength": 100,
"description": "The footprint name (default: the name inside the file)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
},
"kicad_mod": {
"type": "string",
"maxLength": 1000000,
"minLength": 20,
"description": "The .kicad_mod file, as text."
}
}
}Unpack a ZIP into the project folder, keeping its paths: new footprints into a .pretty library the fp-lib-table names, 3D models, a library table. Existing files are kept unless overwrite is true; the reply lists written, replaced and kept files. Base64, up to about 18 MB zipped.
| Argument | Type | Description |
|---|---|---|
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
| overwrite | boolean | |
| zip_base64* | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id",
"zip_base64"
],
"properties": {
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
},
"overwrite": {
"type": "boolean"
},
"zip_base64": {
"type": "string",
"maxLength": 24000000,
"minLength": 100
}
}
}Dense placement by simulated annealing: wirelength inside the outline with courtyard gaps, edge connectors held on their edge, fixed and locked parts held, keepout rectangles kept clear (routing corridors), and a per-pad price for the bottom side (flip_cost, mm of wirelength; each bottom-side pad whose net has top-side pins costs a via). Starts from the current positions unless from_scratch. Slower than auto_place (a minute per 600k iterations) and much denser. Check overlapping_pairs and run_drc afterwards.
| Argument | Type | Description |
|---|---|---|
| t0 | number | Start temperature (default 15). ~0.5 keeps the current placement and only tidies it (refine, or squeeze into a smaller outline). |
| edge | object | Connector ref to the edge it sits on, optionally @mm: where along that edge its centre goes, from the outline's top-left corner (x on top/bottom, y on left/right) — the same meaning as in auto_place and a board plan. A fixed or locked ref keeps its pin. |
| halo | object | Routing room per ref, mm (a number all round, or footprint-local [left, top, right, bottom]). |
| near | array | Keep ref at its anchor (a decoupling capacitor at its IC, a crystal at its MCU): the board plan's near constraint, as a strong pull in the anneal. |
| refs | array | The footprints that may move (default: every unlocked one). |
| seed | integer | |
| fixed | object |
Pack footprints inside the board outline with Koppar's heuristic placer (ratsnest-driven, courtyard-legal). By default every unlocked footprint moves and locked ones stay; refs names exactly which move (all others stay). Constraints: fixed (exact origin positions and rotation, never moved; locked footprints likewise), side, keepouts (rectangles), groups, near (ref within maxMm of an anchor), edge (ref to "left|right|top|bottom", optionally "@mm" along that edge from the outline's top-left corner). Nothing is left past the outline except a USB/barrel/jack opening's 1.2 mm lip; placement_notes lists every part that could not be placed where asked. Coarse by design: refine the result with place_footprints.
| Argument | Type | Description |
|---|---|---|
| edge | object | Ref to the edge it sits on, optionally @mm: where along that edge its centre goes, from the outline's top-left corner (x on top/bottom, y on left/right). |
| near | array | |
| refs | array | The footprints that may move. |
| side | object | |
| fixed | object | |
| shove | number | Legaliser: a part may take a spot held only by movable parts under this fraction of its area (default 0.3, 0 off). |
| groups | array | |
| placer | string |
The numbers a designer judges routed copper by — signal vias per net, share of signal nets without a via, share of signal copper on the outer layers, vias in SMD pads, plane stitching — next to the bands of designer-routed reference boards with the same layer count, and a gap_to_designers list saying where this board is not yet human-grade.
| Argument | Type | Description |
|---|---|---|
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
}
}
}A filled pour cut into islands by routing: one through-via per island that KiCad finds cut off from its net, placed well inside the island and inside the net's main copper on another layer, clear of every other net between. Reports the islands it found no site for. Run run_drc afterwards.
| Argument | Type | Description |
|---|---|---|
| nets | array | Net names; * and ? wildcards, e.g. ["USB_D*", "+3V3"]. |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| max_vias | integer | |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"nets": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"maxItems": 500,
"description": "Net names; * and ? wildcards, e.g. [\"USB_D*\", \"+3V3\"]."
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"max_vias": {
"type": "integer",
"maximum": 200,
"minimum": 1
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
}
}
}Check the copper against the project's net classes and differential pairs, which KiCad's DRC does not: every class or pair net's narrowest track and the length below its class width, and every pair (X_P/X_N, X+/X-, CAN X_H/X_L) with its coupled share at the class's diff_pair_gap, both lengths and the skew. Routing applies the same rules.
| Argument | Type | Description |
|---|---|---|
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
}
}
}Judge the copper by physics, which KiCad's DRC does not: impedance from the stackup on controlled nets, IR drop and heating on rails with a stated current, pair and lane skew, a ground via beside every high-speed layer change, 3W spacing between high-speed runs, and the via path under exposed paddles. Each check runs only when the board states something it can judge. With repair, the fixable findings are fixed in place (track width, skew meanders, return vias, widened rails), each kept only if KiCad counts nothing worse. finish_board runs the same repairs.
| Argument | Type | Description |
|---|---|---|
| repair | boolean | |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"repair": {
"type": "boolean"
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
}
}
}Pick which offer a BOM line uses: the line's references and a seller part number or MPN from its offer or alternatives in get_bom; null goes back to the automatic pick. Sourcing only: a different component is a circuit change.
| Argument | Type | Description |
|---|---|---|
| part* | any | Seller part number or MPN from get_bom, or null. |
| refs* | array | References of the line, e.g. ["C1","C2"]. |
| design_id* | string | The design id returned by create_design or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id",
"refs",
"part"
],
"properties": {
"part": {
"anyOf": [
{
"type": "string",
"maxLength": 80
},
{
"type": "null"
}
],
"description": "Seller part number or MPN from get_bom, or null."
},
"refs": {
"type": "array",
"items": {
"type": "string",
"maxLength": 20
},
"maxItems": 200,
"minItems": 1,
"description": "References of the line, e.g. [\"C1\",\"C2\"]."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
}
}
}Sweep the routing: zero-length and duplicate tracks, stub tracks (a free end, and everything the track touches stays joined without it), and vias that meet their net on fewer than two layers. Contact is copper overlap, as KiCad judges it. Refills the zones first so pours count as connections. Locked items stay. The board is put back if the unconnected count or the DRC errors rise. A track running on past its last junction is cut back to it (trim_overhangs). list_removed names every item that went.
| Argument | Type | Description |
|---|---|---|
| refill | boolean | |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
| list_removed | boolean | |
| trim_overhangs | boolean | |
| dangling_tracks | boolean | |
| duplicate_tracks | boolean |
Move every resistor, capacitor and inductor bought outside JLCPCB's basic library onto an in-stock basic-library part of the same value, package and (capacitors) at least the same voltage rating. Each part outside that library adds a loading fee to a JLCPCB order, usually more than the part. Each swap becomes the line's choice (choose_bom_part with null undoes it); lines with no readable value, no SMD size or no basic part are reported and left alone.
| Argument | Type | Description |
|---|---|---|
| boards | integer | Boards the stock must cover (default 1). |
| design_id* | string | The design id returned by create_design or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"boards": {
"type": "integer",
"maximum": 10000,
"minimum": 1,
"description": "Boards the stock must cover (default 1)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
}
}
}After route_board: re-route the weakly coupled differential pairs one at a time, least coupled first. Both legs are ripped and routed alone around everything else as a pair; the new copper stays only when the pair's coupled share rises by min_gain_pct, its skew stays within max_skew_mm, KiCad counts no new open item or DRC error, and the board gains at most max_extra_vias vias. Pairs routed with the whole board lose their lanes; alone they couple. Run check_net_rules before and after.
| Argument | Type | Description |
|---|---|---|
| pairs | array | Only pairs with a leg matching these (default every pair under target_pct). |
| tries | integer | Router seeds per pair; the best acceptable one is kept (default 2). |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
| ml_options | object | |
| target_pct | number | Pairs coupled below this are tried (default 70). |
Register a connectable schematic symbol for a part that is NOT in KiCad's libraries (search_kicad_symbol returned nothing). Use this for specialty ICs — LED-matrix drivers, niche sensors, etc. — INSTEAD of telling the synthesizer to model the part with discrete passives (which leaves every pin dangling and breaks the board). Provide the full datasheet pinout. The part then becomes available to the synthesizer as Part('custom', '<name>') with the exact pin names you supply here, and is added to the Verified parts table. A part with three or more pins needs footprint= naming a real, in-library footprint for its package (search_kicad_footprint with the family and pin count, e.g. 'LGA-14'); the call is rejected without one, since a generated grid of pads cannot be assembled. List every pad of the footprint, NC pins included. When the package is not in KiCad's libraries, bring your own footprint instead: footprint_mod takes the whole .kicad_mod file as text (KiCad 6+, up to 1 MB; the CLI reads it with `koppar custom-symbol --footprint-file`). It is checked as a KiCad footprint, every pad must have a pin with that pad's number (and every pin a pad), and it is stored as 'custom:<name>': the symbol uses it, and it goes on the board, into project.zip and into the fp-lib-table. footprint is then not needed. The name is used for file names: letters, digits and _ . + - (anything else becomes _). The symbol belongs to design_id.
| Argument | Type | Description |
|---|---|---|
| name* | string | Part number, used as the symbol name (letters, digits, _ . + -). |
| pins* | array | Every pin from the datasheet. |
| datasheet | string | |
| design_id* | string |
Start a new design from the user's brief (what the board must do, its interfaces, power, size and constraints). Returns the design_id every other tool takes and the web_url where the user follows the design. Uses no generation quota: the work is done by you.
| Argument | Type | Description |
|---|---|---|
| brief* | string | The design brief, in the user's terms plus anything you clarified with them. |
| title | string | A short name for the design. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"brief"
],
"properties": {
"brief": {
"type": "string",
"maxLength": 20000,
"minLength": 10,
"description": "The design brief, in the user's terms plus anything you clarified with them."
},
"title": {
"type": "string",
"maxLength": 120,
"description": "A short name for the design."
}
}
}Move a design (or a board workspace) to the trash: it leaves list_designs and the web app, and restore_design brings it back for 7 days, after which it is removed for good. permanent removes it, its files and its session right away. Refused while a run on it is in progress. The CLI: `koppar delete <design>`.
| Argument | Type | Description |
|---|---|---|
| design_id* | string | The design id returned by create_design or list_designs. |
| permanent | boolean | Remove it now, with no trash to restore from (default false). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
},
"permanent": {
"type": "boolean",
"description": "Remove it now, with no trash to restore from (default false)."
}
}
}For every net still open (or the nets named): each pad with the escape corridors free on its own layer, whether a via can be dropped beside it at all, and what blocks it (which part's pads, which net's tracks or vias, the board edge). A pad with no free corridor and no via site is CRAMPED — no router can reach it; the advice names the parts to move. Otherwise the advice says which nets to rip and route first. Use it instead of repeating repair_board on a net that keeps failing.
| Argument | Type | Description |
|---|---|---|
| nets | array | Only these nets (default: every open net). |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| max_nets | integer | |
| reach_mm | number | How far a corridor must stay free (default 1.5). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"nets": {
"type": "array",
"items": {
"type": "string",
"maxLength": 80
},
"maxItems": 50,
"description": "Only these nets (default: every open net)."
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"max_nets": {
"type": "integer",
"maximum": 100,
"minimum": 1
},
"reach_mm": {
"type": "number",
"maximum": 5,
"minimum": 0.5,
"description": "How far a corridor must stay free (default 1.5)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
}
}
}Apply SEARCH/REPLACE patches to your latest script and re-run every check, as submit_circuit does. The latest script is your last submission when it was sent back (attempt_N_circuit.py), otherwise the design's circuit.py. Each search must match the current file exactly once (whitespace-sensitive); an empty replace deletes. Nothing is applied if any block fails to match.
| Argument | Type | Description |
|---|---|---|
| edits* | array | Ordered patches. |
| design_id* | string | The design id returned by create_design or list_designs. |
| check_sourcing | boolean | Check the parts against supplier catalogues (default true). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id",
"edits"
],
"properties": {
"edits": {
"type": "array",
"items": {
"type": "object",
"required": [
"search",
"replace"
],
"properties": {
"search": {
"type": "string",
"minLength": 1
},
"replace": {
"type": "string"
}
}
},
"maxItems": 50,
"minItems": 1,
"description": "Ordered patches."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
},
"check_sourcing": {
"type": "boolean",
"description": "Check the parts against supplier catalogues (default true)."
}
}
}Export the assembled board as STEP (3D models, DNP parts left out). Download it as workspace.step; workspace.zip includes it.
| Argument | Type | Description |
|---|---|---|
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
}
}
}Refill every copper zone with KiCad's zone filler.
| Argument | Type | Description |
|---|---|---|
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
}
}
}Close what the router left open the way a designer does: for each open net the diagnosis names the copper boxing it in; that copper is ripped (never a poured net), the open nets are routed FIRST into the space, then the ripped nets go back around them; up to `rounds` rounds, each kept only if KiCad counts fewer unconnected items. Use it after route_board leaves a handful of nets open (route_board's default pipeline already runs three rounds; this adds more, or follows a single route); repair_board never moves the blockers.
| Argument | Type | Description |
|---|---|---|
| rounds | integer | Rip-and-reroute rounds (default 3). |
| router | string | |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| reach_mm | number | Radius cleared of tracks and vias around a pad with no way out (default 1.5). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
| class_vias | boolean | Route with the Default class's via instead of the board's smallest legal one. |
| ml_options | object |
What the board plan is decided from: the computed minimum board, BOARD STATS (pad density, fine-pitch parts, fanout), the parts and nets, board instructions the user gave, and the plan schema with its rules. Needs an accepted schematic.
| Argument | Type | Description |
|---|---|---|
| design_id* | string | The design id returned by create_design or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
}
}
}The board as it stands: copper layers, outline, design rules and net classes, counts (footprints, nets, tracks, vias, zones, keepouts, KiCad unconnected items), zones and keepouts, and every footprint with reference, value, footprint, position (origin, mm), rotation, side, locked, DNP, courtyard box and 3D models.
| Argument | Type | Description |
|---|---|---|
| refs | array | Only these footprints. |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
| include_footprints | boolean | List footprints (default true). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"refs": {
"type": "array",
"items": {
"type": "string",
"maxLength": 40
},
"maxItems": 2000,
"description": "Only these footprints."
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
},
"include_footprints": {
"type": "boolean",
"description": "List footprints (default true)."
}
}
}The design's latest board job: its status and, once it ends, its result or error. wait_s holds the call until it ends.
| Argument | Type | Description |
|---|---|---|
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
}
}
}The board run: stage, size, layers, placement, routing completion, open nets, DRC counts; once finished, DRC violations by type, whether the fab files are released and, when not, the diagnosed causes (first = fix first: parts that did not fit, collisions, missing footprints, open nets, thin power). wait_s holds the call until the run ends (or that many seconds pass).
| Argument | Type | Description |
|---|---|---|
| wait_s | integer | Seconds to wait for a running board to finish (max 55). |
| design_id* | string | The design id returned by create_design or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for a running board to finish (max 55)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
}
}
}The live-priced BOM: each line with references, value, footprint, the chosen offer (seller, part number, MPN, price, stock, match quality), alternatives and totals. refresh asks the sellers again (tens of seconds).
| Argument | Type | Description |
|---|---|---|
| tier | string | JLCPCB PCBA tier to source for, kept with the design. 'economic' swaps Standard-only parts for Economic-eligible ones that match as well; default 'standard' (no filter). The BOM reports which parts decide the tier either way. |
| boards | integer | Boards to price for (default 1). |
| refresh | boolean | Ask the sellers again instead of the stored prices. |
| design_id* | string | The design id returned by create_design or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"tier": {
"enum": [
"economic",
"standard"
],
"type": "string",
"description": "JLCPCB PCBA tier to source for, kept with the design. 'economic' swaps Standard-only parts for Economic-eligible ones that match as well; default 'standard' (no filter). The BOM reports which parts decide the tier either way."
},
"boards": {
"type": "integer",
"maximum": 10000,
"minimum": 1,
"description": "Boards to price for (default 1)."
},
"refresh": {
"type": "boolean",
"description": "Ask the sellers again instead of the stored prices."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
}
}
}Where a design stands: the brief, the schematic (accepted or the last blocking error, ERC, part and net counts, submissions), the board run, the readable files, and the next step.
| Argument | Type | Description |
|---|---|---|
| design_id* | string | The design id returned by create_design or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
}
}
}Download URLs for the design (KiCad project, schematic, netlist, BOM CSV, board file, 3D model, Gerbers, order bundle) and which are available now. They take the same Authorization: Bearer API key; the CLI fetches them with `koppar download <design> <artifact>`.
| Argument | Type | Description |
|---|---|---|
| design_id* | string | The design id returned by create_design or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
}
}
}Whether the board has earned its fab files (zero serious DRC errors, nothing unconnected), and if not, why not.
| Argument | Type | Description |
|---|---|---|
| design_id* | string | The design id returned by create_design or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
}
}
}Return the full pin list (number, name, electrical type) and description for a specific KiCad symbol. For some high-risk power parts it also returns curated topology_constraints from datasheet-style application notes and footprint_suggestions. Use this before writing pin connections (e.g. mcu['VCC'] += vcc) so names, constraints and footprints match the symbol exactly. For a part found in KiCad, the result is ALSO enriched with that part's topology + required external parts from a datasheet database (merged into topology_constraints). For a part NOT in KiCad (search returned nothing), call this with library='custom' and name='<part number>': the component database returns its datasheet link, package and an UNVERIFIED machine-extracted pinout. That is not a symbol: register the part with create_custom_symbol, whose pinout is checked against the datasheet. Pass design_id so the lookup is recorded for the design's dossier and a registered part belongs to it. Give library and name, or up to 12 of them in parts.
| Argument | Type | Description |
|---|---|---|
| name | string | Symbol name, e.g. 'RP2040'. |
| parts | array | Batch form: several (library, name) pairs. |
| library | string | Symbol library, e.g. 'MCU_RaspberryPi', or 'custom' for a database part number. |
| design_id | string | The design id returned by create_design or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"name": {
"type": "string",
"maxLength": 200,
"description": "Symbol name, e.g. 'RP2040'."
},
"parts": {
"type": "array",
"items": {
"type": "object",
"required": [
"library",
"name"
],
"properties": {
"name": {
"type": "string",
"maxLength": 200
},
"library": {
"type": "string",
"maxLength": 120
}
}
},
"maxItems": 12,
"description": "Batch form: several (library, name) pairs."
},
"library": {
"type": "string",
"maxLength": 120,
"description": "Symbol library, e.g. 'MCU_RaspberryPi', or 'custom' for a database part number."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
}
}
}One price for a quantity: parts from the sellers, the board and assembly from the chosen provider's quote, setup fees, and what the total does not include.
| Argument | Type | Description |
|---|---|---|
| boards | integer | Quantity (default 1). |
| provider | string | Provider id from list_order_providers, e.g. "jlcpcb". |
| design_id* | string | The design id returned by create_design or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"boards": {
"type": "integer",
"maximum": 10000,
"minimum": 1,
"description": "Quantity (default 1)."
},
"provider": {
"type": "string",
"maxLength": 40,
"description": "Provider id from list_order_providers, e.g. \"jlcpcb\"."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
}
}
}Everything a design review needs in one text: the brief, the dossier, circuit.py and the compiled connectivity (every net with every pin and its function), with the reviewer instructions. Review it yourself and fix blockers with edit_circuit.
| Argument | Type | Description |
|---|---|---|
| design_id* | string | The design id returned by create_design or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
}
}
}How to drive Koppar end to end, and the instructions for each stage you do yourself: "research" (part research and the dossier), "synthesis" (writing the SKiDL schematic), "review" (design review), "board" (the board plan). Read the stage guide before doing that stage.
| Argument | Type | Description |
|---|---|---|
| stage* | string | overview | research | synthesis | review | board |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"stage"
],
"properties": {
"stage": {
"enum": [
"overview",
"research",
"synthesis",
"review",
"board"
],
"type": "string",
"description": "overview | research | synthesis | review | board"
}
}
}Bring an existing KiCad project in as a board workspace: the project folder as a ZIP (the .kicad_pcb, .kicad_pro, schematics, footprint and 3D-model folders), base64-encoded, up to about 18 MB zipped. The CLI does this with `koppar import <folder>`. Or from_design_id: the KiCad project of a design the pipeline built (its board, rules, schematics and custom footprints) opened as a workspace, to change the design rules, place and route it with the board tools and put the result back with upload_board (workspace_id). Returns the design_id the board tools take and a first get_board_info.
| Argument | Type | Description |
|---|---|---|
| brief | string | What the user wants done with the board, for the design record. |
| title | string | |
| board_file | string | Which .kicad_pcb at the top of the project, when there are several. |
| zip_base64 | string | The zipped project folder, base64. |
| from_design_id | string | A design of yours with a board (start_board or upload_board): its KiCad project becomes the workspace. Instead of zip_base64. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"brief": {
"type": "string",
"maxLength": 20000,
"description": "What the user wants done with the board, for the design record."
},
"title": {
"type": "string",
"maxLength": 120
},
"board_file": {
"type": "string",
"maxLength": 200,
"description": "Which .kicad_pcb at the top of the project, when there are several."
},
"zip_base64": {
"type": "string",
"maxLength": 24000000,
"minLength": 100,
"description": "The zipped project folder, base64."
},
"from_design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "A design of yours with a board (start_board or upload_board): its KiCad project becomes the workspace. Instead of zip_base64."
}
}
}The snapshots of this board, newest first. Revision N is the board as it was before change N (revision 0 is the project as imported); restore_board_revision N goes back to it.
| Argument | Type | Description |
|---|---|---|
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
}
}
}The user's designs, newest first, including ones made in the web app (an agent can continue those too) and board workspaces (kind "board workspace"). With trashed, the designs in the trash instead (deleted, restorable for 7 days).
| Argument | Type | Description |
|---|---|---|
| limit | integer | How many (default 20). |
| trashed | boolean | List the trash instead of the live designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"limit": {
"type": "integer",
"maximum": 100,
"minimum": 1,
"description": "How many (default 20)."
},
"trashed": {
"type": "boolean",
"description": "List the trash instead of the live designs."
}
}
}The PCB and assembly providers, whether each can quote and take this kind of board today, and what a handoff sends them.
No arguments.
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {}
}Put footprints exactly where given: KiCad board coordinates of the footprint origin in mm (y grows downward), rotation in degrees as KiCad shows it, side F or B (changing side flips the footprint, as KiCad does), locked. dx_mm/dy_mm/drot_deg move relative to where it is. Nothing is nudged or legalized: overlaps are for run_drc to report. Unknown references come back in missing.
| Argument | Type | Description |
|---|---|---|
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
| placements* | array |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id",
"placements"
],
"properties": {
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
},
"placements": {
"type": "array",
"items": {
"type": "object",
"required": [
"ref"
],
"properties": {
"ref": {
"type": "string",
"maxLength": 40,
"minLength": 1
},
"side": {
"enum": [
"F",
"B"
],
"type": "string"
},
"x_mm": {
"type": "number"
},
"y_mm": {
"type": "number"
},
"dx_mm": {
"type": "number"
},
"dy_mm": {
"type": "number"
},
"locked": {
"type": "boolean"
},
"rot_deg": {
"type": "number"
},
"drot_deg": {
"type": "number"
}
}
},
"maxItems": 2000,
"minItems": 1
}
}
}After route_board and prune_vias: rip one net at a time, most vias first, route it alone around everything else at a high via price, and keep the new copper only when KiCad counts fewer vias with no new open item or DRC error (a reroute that cuts a pour into islands first gets one via per island, bridge_islands). Run run_drc and get_score afterwards; a second pass sometimes finds more.
| Argument | Type | Description |
|---|---|---|
| nets | array | Net names; * and ? wildcards, e.g. ["USB_D*", "+3V3"]. |
| pairs | boolean | Rip and reroute a differential pair (_H/_L, _P/_N, +/-) together (default true: a leg rerouted alone comes back at its own length; a step that degrades a pair is never kept). |
| pours | boolean | Also polish the poured nets (default false): the pour and its stitch vias stay, the net is routed as a track tree on top, then its redundant stitch vias are pruned. A lottery: the tree that did this by accident (PCBGolf +3V3 53 -> 32) did not repeat in 2 deliberate tries. |
| router | string | |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| workers | integer |
Remove every via the board does not need: groups of vias come out, the zones are refilled and KiCad's unconnected count compared, and a via stays only if removing it disconnects something. nets limits the candidates (GND and the plane rails first: pours already join most of their pads). Runs for minutes on a large board; then fill_zones, run_drc and score_board.
| Argument | Type | Description |
|---|---|---|
| nets | array | |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| workers | integer | |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"nets": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"maxItems": 50
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"workers": {
"type": "integer",
"maximum": 8,
"minimum": 1
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
}
}
}Read a text file of the design: prompt.txt (brief), dossier.md, circuit.py, circuit.net, result.json, circuit.erc.json (KiCad ERC violations), attempt_N_circuit.py / attempt_N_error.txt, board_plan.json, pcb_result.json, pcb_run.log, circuit.drc.json (KiCad DRC), netclasses.resolved.json, dfm.json, harness.log.
| Argument | Type | Description |
|---|---|---|
| path* | string | A file name, e.g. 'circuit.py'. |
| design_id* | string | The design id returned by create_design or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id",
"path"
],
"properties": {
"path": {
"type": "string",
"maxLength": 80,
"minLength": 1,
"description": "A file name, e.g. 'circuit.py'."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
}
}
}An exact 2D picture of the board as an engineer reads it: copper per layer (the facing layer full strength, the others faded), pads, vias, pours, outline, courtyards and refs. side top|bottom, region [x, y, w, h] mm for a crop, drc_markers to circle every DRC violation, ratsnest to draw the open connections, highlight_nets/highlight_refs in magenta. The pixel-per-mm scale and region come back so a follow-up crop is exact. Download workspace.render.png.
| Argument | Type | Description |
|---|---|---|
| refs | boolean | |
| side | string | |
| layers | array | |
| region | array | [x_mm, y_mm, w_mm, h_mm] crop; default the whole board. |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| markers | array | |
| ratsnest | boolean | |
| design_id* | string |
Keep the copper of every net it already connects and route the nets still open around it: route_board with preserve_existing. The learned router service by default; router "ts" for the local router, which also keeps partial copper and runs its last-chance welds and plane-island bridges. Default budget 120 s.
| Argument | Type | Description |
|---|---|---|
| nets | array | Net names; * and ? wildcards, e.g. ["USB_D*", "+3V3"]. |
| pours | string | |
| router | string | |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| compact | boolean | Via choice as on route_board: true for the densest legal via (JLCPCB Kelvin test), false for the Kelvin-free 0.45/0.2. |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
| time_budget_s | integer |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"nets": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"maxItems": 500,
"description": "Net names; * and ? wildcards, e.g. [\"USB_D*\", \"+3V3\"]."
},
"pours": {
"enum": [
"keep",
"engine"
],
"type": "string"
},
"router": {
"enum": [
"ts",
"ml"
],
"type": "string"
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"compact": {
"type": "boolean",
"description": "Via choice as on route_board: true for the densest legal via (JLCPCB Kelvin test), false for the Kelvin-free 0.45/0.2."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
},
"time_budget_s": {
"type": "integer",
"maximum": 900,
"minimum": 10
}
}
}Put the board and its rules back as they were in a revision from list_board_revisions. The current board is saved as a new revision first, so the restore itself can be undone.
| Argument | Type | Description |
|---|---|---|
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| revision* | integer | |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id",
"revision"
],
"properties": {
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"revision": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
}
}
}Put a deleted design back from the trash (within 7 days of delete_design).
| Argument | Type | Description |
|---|---|---|
| design_id* | string | The design id returned by create_design or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
}
}
}Delete tracks and vias: of the given nets, on the given layers (vias are not layer-filtered), with an end inside region, or all. Filters combine. tracks/vias choose which kinds (both by default); zones also deletes the copper zones (pours) the same filters match (a zone inside region), never keepout areas. Locked items stay unless include_locked.
| Argument | Type | Description |
|---|---|---|
| all | boolean | |
| nets | array | Net names; * and ? wildcards, e.g. ["USB_D*", "+3V3"]. |
| vias | boolean | |
| zones | boolean | |
| layers | array | |
| region | object | |
| tracks | boolean | |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| design_id |
Route under the project's rules and net classes. By default (no nets, no router, none of the single-route options below) it runs the full route pipeline Koppar benchmarks: the learned router on the whole board racing the negotiated router on a copy (the board with fewer open items, then fewer DRC errors, goes on), repair rounds on what stays open, the local finish, copper finishing (0/45/90 runs) and one repair round after it, inside one wall-clock cap: time_budget_s is that cap (default 1200, up to 1500), so the job runs up to about 20 minutes: follow it with get_board_job. The result gives the final unconnected items and DRC errors and a pipeline summary: the counts after the route and after each finish, which arm won, whether the copper finishing was kept. preserve_existing unset keeps the copper of a board that has tracks or vias (the negotiated arm then does not run: it routes from scratch) and routes a board without any from scratch; false routes every net again. nets, router, or any single-route option (pours, rule overrides, via_cost, grid_mm, negotiation_rounds, ml_options, seed_existing, fewest_vias, pairs_first, class_vias) runs ONE route with that router instead, for expert control: nets limits it to those nets; preserve_existing (default true) keeps every track and via already on the board and routes only what is still open. pours: "keep" (the default when the board has zones) keeps the board's zones and routes every net as tracks; "engine" plans a GND pour and fans GND to it by via. Rule overrides apply to this run only. via_cost raises the price of a via in the local router (its default is 2), for fewer vias at some completion cost; the learned router takes its via discipline in ml_options. A single route takes time_budget_s (default 120, up to 900).
| Argument | Type | Description |
|---|---|---|
| nets | array | Net names; * and ? wildcards, e.g. ["USB_D*", "+3V3"]. |
| pours | string | |
| router | string | Unset: the full pipeline (above) on the whole board, "ml" for nets. "ml": the learned router service alone, 1 to 8 layers; the time budget is its deadline. Nets outside the nets scope, and with preserve_existing the nets their copper already connects, keep that copper and everything else is routed around it (partial copper of a routed net is replaced). "ts": the local router, also the fallback when the service fails; pours/via_cost/grid_mm/negotiation_rounds apply to it only. "negotiated": PathFinder over every net at once, gridless on a coarse routing graph, the fine grid for the last open nets (the whole board from scratch, nets must be unset; GND routed as a net under its pour, then pruned). Minutes (its budget is 1800 s unless time_budget_s is given) but it closes dense boards the service leaves open. Follow with tidy_copper. |
KiCad's DRC on the board as it is now, with schematic parity when the project has its schematic: error and warning counts by type, shorts, unconnected items, parity items, and the first violations with their items and positions (types filters, max_violations caps; default 40). Also mount_fit: parts reaching through the board (mid-mount jacks, USB-C) checked against their cutouts from their 3D models, with any body area over board material or within the fab's 0.2 mm milling tolerance of the cut.
| Argument | Type | Description |
|---|---|---|
| types | array | |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
| max_violations | integer |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"types": {
"type": "array",
"items": {
"type": "string",
"maxLength": 60
},
"maxItems": 50
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
},
"max_violations": {
"type": "integer",
"maximum": 500,
"minimum": 1
}
}
}Store the research dossier (markdown with ## Parts list, ## Power rails, ## Topology constraints, ## Notes, as the research guide describes). The verified pin tables from your lookups on this design are appended, and verified entries the design already had for parts you did not look up again are kept. Reports every (library, name) in the parts list that does not exist, with catalog candidates.
| Argument | Type | Description |
|---|---|---|
| markdown* | string | The dossier. |
| design_id* | string | The design id returned by create_design or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id",
"markdown"
],
"properties": {
"markdown": {
"type": "string",
"maxLength": 200000,
"minLength": 20,
"description": "The dossier."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
}
}
}Export the assembled board (3D models, DNP parts left out) and measure it: bounding-box size and volume, via count, copper layers, and the PCBGolf score = volume (mm³) + 50 × vias + 5000 × copper layers. Parts whose 3D model is missing are listed, since they are not in the volume.
| Argument | Type | Description |
|---|---|---|
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
}
}
}Search KiCad's standard footprint libraries. Returns 'Library:Footprint' strings suitable for the footprint= argument of Part(...). Query with the package family and pin count ('LGA-14', 'QFN-24', 'SOIC-8'), optionally a body size or pitch. When no name contains every word, near_misses lists footprints of the same package, ranked by body size and pitch. Pass design_id so the lookup is recorded for the design's dossier and a registered part belongs to it.
| Argument | Type | Description |
|---|---|---|
| query* | string | Package to search for, e.g. 'SOIC-8', 'QFN-56 7x7', 'USB_C_Receptacle'. |
| design_id | string | The design id returned by create_design or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"query"
],
"properties": {
"query": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Package to search for, e.g. 'SOIC-8', 'QFN-56 7x7', 'USB_C_Receptacle'."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
}
}
}Search KiCad's standard symbol libraries for parts whose name contains a substring. Use this whenever you are not 100% sure the (library, name) pair you're about to pass to Part(...) exists. Always prefer the package-suffixed variant the search returns over a generic name. If a part returns nothing here, get_kicad_symbol(library='custom', name='<part number>') may find it in the component database (a datasheet link and a pinout lead); register it with create_custom_symbol. Pass design_id so the lookup is recorded for the design's dossier and a registered part belongs to it.
| Argument | Type | Description |
|---|---|---|
| query* | string | Substring to search for, e.g. 'NE555', 'USB-C', 'RP2040'. |
| library | string | Restrict to one symbol library, e.g. 'Timer'. |
| design_id | string | The design id returned by create_design or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"query"
],
"properties": {
"query": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Substring to search for, e.g. 'NE555', 'USB-C', 'RP2040'."
},
"library": {
"type": "string",
"maxLength": 120,
"description": "Restrict to one symbol library, e.g. 'Timer'."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
}
}
}Upload the released board (Gerbers, BOM, placement) to a manufacturer and return the page where the user pays. This publishes the design to a third party: call it only when the user has explicitly asked to order from that provider, and set user_confirmed only then. Some providers need a shipping address.
| Argument | Type | Description |
|---|---|---|
| title | string | Order title at the provider. |
| boards | integer | Quantity (default 1). |
| provider* | string | Provider id from list_order_providers. |
| shipping | object | Delivery address, for providers that need one. |
| design_id* | string | The design id returned by create_design or list_designs. |
| user_confirmed* | boolean | The user explicitly asked to send this design to this provider. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id",
"provider",
"user_confirmed"
],
"properties": {
"title": {
"type": "string",
"maxLength": 120,
"description": "Order title at the provider."
},
"boards": {
"type": "integer",
"maximum": 10000,
"minimum": 1,
"description": "Quantity (default 1)."
},
"provider": {
"type": "string",
"maxLength": 40,
"description": "Provider id from list_order_providers."
},
"shipping": {
"type": "object",
"required": [
"countryCode",
"city",
"postalCode",
"address",
"contactName",
"phone"
],
"properties": {
"city": {
"type": "string",
"maxLength": 80
},
"email": {
"type": "string",
"maxLength": 200
},
"phone": {
"type": "string",
"maxLength": 40
},
"state": {
"type": "string",
"maxLength": 80
},
"address": {
"type": "string",
"maxLength": 300
},
"company": {
"type": "string",
"maxLength": 120
},
"postalCode": {
"type": "string",
"maxLength": 20
},
"contactName": {
"type": "string",
"maxLength": 120
},
"countryCode": {
"type": "string",
"maxLength": 2,
"minLength": 2
}
},
"description": "Delivery address, for providers that need one."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
},
"user_confirmed": {
"type": "boolean",
"const": true,
"description": "The user explicitly asked to send this design to this provider."
}
}
}Replace everything on Edge.Cuts with a new outline: rect (optionally with corner_radius_mm), a polygon of points, or fit_to_parts (the rectangle around every footprint courtyard plus margin_mm). Give exactly one.
| Argument | Type | Description |
|---|---|---|
| rect | object | |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| polygon | array | |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
| fit_to_parts | object | |
| line_width_mm | number |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"rect": {
"type": "object",
"required": [
"x_mm",
"y_mm",
"w_mm",
"h_mm"
],
"properties": {
"h_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"w_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"x_mm": {
"type": "number",
"description": "Left edge, board coordinates (KiCad mm, y grows downward)."
},
"y_mm": {
"type": "number",
"description": "Top edge."
},
"corner_radius_mm": {
"type": "number",
"minimum": 0
}
}
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"polygon": {
"type": "array",
"items": {
"type": "array",
"items": [
{
"type": "number"
},
{
"type": "number"
}
],
"maxItems": 2,
"minItems": 2,
"description": "[x_mm, y_mm]",
"additionalItems": false
},
"maxItems": 2000,
"minItems": 3
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
},
"fit_to_parts": {
"type": "object",
"required": [
"margin_mm"
],
"properties": {
"margin_mm": {
"type": "number",
"maximum": 50,
"minimum": 0
},
"corner_radius_mm": {
"type": "number",
"minimum": 0
}
}
},
"line_width_mm": {
"type": "number",
"maximum": 1,
"exclusiveMinimum": 0
}
}
}Set the project design rules (.kicad_pro) and copper layer count. Works on a board workspace and on a generated design (create_design → start_board). On a generated design the rules go into circuit.kicad_pro/.kicad_dru in place (the previous ones are snapshotted under rules_revisions/), are kept by every later project write (project.zip, a new board run), the copper is not changed and KiCad DRC judges the board against them at once: the reply carries the DRC counts and whether the Gerbers are released; the next start_board routes to the default_* values. copper_layers, stackup and board_thickness_mm are workspace-only (a generated design changes them with a new board). preset "jlcpcb" applies JLCPCB's published minimums for the layer count and writes their per-feature limits (plated rings, pad hole spacing, hole-to-track) as KiCad custom rules (.kicad_dru) that run_drc checks; explicit values override the minimums. Board minimums (min_*), the Default net class (default_*), and named net classes with their net patterns. route_board routes with these rules and run_drc checks against them. Changing copper_layers rebuilds the stackup; tracks on removed layers are reported. copper_layers 1 is a single-sided board (hand etching): the KiCad file keeps F.Cu and B.Cu, and from then on the routers hold to one face (B.Cu as soon as a THT pad exists, else F.Cu) and place no via; copper on the other face is removed.
| Argument | Type | Description |
|---|---|---|
| preset | string | |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| stackup | string | JLCPCB's 4-layer 1.6 mm impedance stackups, written into the board: 7628 (0.21 mm prepreg, their default) or 3313 (0.1 mm prepreg: thinner pairs for the same impedance). Needed before a net class states diff_impedance_ohm. |
Add or remove keepout rule areas. Each keepout is a rect or polygon on the given copper layers (default all) and forbids what it names: no_tracks, no_vias, no_zone_fills (all three default true), no_pads, no_footprints. route_board keeps tracks and vias out of them and KiCad DRC enforces them. remove takes names (wildcards allowed).
| Argument | Type | Description |
|---|---|---|
| add | array | |
| remove | array | |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"add": {
"type": "array",
"items": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"maxLength": 60,
"minLength": 1
},
"rect": {
"type": "object",
"required": [
"x_mm",
"y_mm",
"w_mm",
"h_mm"
],
"properties": {
"h_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"w_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"x_mm": {
"type": "number",
"description": "Left edge, board coordinates (KiCad mm, y grows downward)."
},
"y_mm": {
"type": "number",
"description": "Top edge."
}
}
},
"layers": {
"type": "array",
"items": {
"type": "string",
"pattern": "^(F|B|In\\d{1,2})\\.Cu$"
},
"maxItems": 32
},
"no_pads": {
"type": "boolean"
},
"no_vias": {
"type": "boolean"
},
"polygon": {
"type": "array",
"items": {
"type": "array",
"items": [
{
"type": "number"
},
{
"type": "number"
}
],
"maxItems": 2,
"minItems": 2,
"description": "[x_mm, y_mm]",
"additionalItems": false
},
"maxItems": 500,
"minItems": 3
},
"no_tracks": {
"type": "boolean"
},
"no_footprints": {
"type": "boolean"
},
"no_zone_fills": {
"type": "boolean"
}
}
},
"maxItems": 100
},
"remove": {
"type": "array",
"items": {
"type": "string",
"maxLength": 60,
"minLength": 1
},
"maxItems": 100
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
}
}
}Take clutter off the silkscreen. values "hide" (default) hides value and part-number fields; references "keep" (default), "fab" (moved to the fabrication layer) or "hide"; texts "fab" moves footprint texts off the silkscreen. run_drc's silk_overlap and silk_over_copper warnings count what is left.
| Argument | Type | Description |
|---|---|---|
| texts | string | |
| values | string | |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
| references | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"texts": {
"enum": [
"keep",
"fab"
],
"type": "string"
},
"values": {
"enum": [
"hide",
"show"
],
"type": "string"
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
},
"references": {
"enum": [
"keep",
"fab",
"hide"
],
"type": "string"
}
}
}Add or remove copper zones (pours). Each zone pours its net on the given copper layers over rect or polygon, by default the whole board outline. priority orders overlapping zones (higher fills first); clearance_mm and min_thickness_mm override the rules; thermal false connects pads solid. remove takes zone or net names (wildcards allowed) and never touches keepout areas. Run fill_zones afterwards, then run_drc.
| Argument | Type | Description |
|---|---|---|
| add | array | |
| remove | array | |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"add": {
"type": "array",
"items": {
"type": "object",
"required": [
"net",
"layers"
],
"properties": {
"net": {
"type": "string",
"maxLength": 120,
"minLength": 1
},
"name": {
"type": "string",
"maxLength": 60,
"minLength": 1
},
"rect": {
"type": "object",
"required": [
"x_mm",
"y_mm",
"w_mm",
"h_mm"
],
"properties": {
"h_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"w_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"x_mm": {
"type": "number",
"description": "Left edge, board coordinates (KiCad mm, y grows downward)."
},
"y_mm": {
"type": "number",
"description": "Top edge."
}
}
},
"layers": {
"type": "array",
"items": {
"type": "string",
"pattern": "^(F|B|In\\d{1,2})\\.Cu$"
},
"maxItems": 32,
"minItems": 1
},
"polygon": {
"type": "array",
"items": {
"type": "array",
"items": [
{
"type": "number"
},
{
"type": "number"
}
],
"maxItems": 2,
"minItems": 2,
"description": "[x_mm, y_mm]",
"additionalItems": false
},
"maxItems": 500,
"minItems": 3
},
"thermal": {
"type": "boolean"
},
"priority": {
"type": "integer",
"maximum": 100,
"minimum": 0
},
"clearance_mm": {
"type": "number",
"maximum": 5,
"exclusiveMinimum": 0
},
"min_thickness_mm": {
"type": "number",
"maximum": 5,
"exclusiveMinimum": 0
}
}
},
"maxItems": 50
},
"remove": {
"type": "array",
"items": {
"type": "string",
"maxLength": 120,
"minLength": 1
},
"maxItems": 100
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
}
}
}Silkscreen stamps for release, both off unless asked for: a small spec badge ("routed with Koppar", optionally the title, revision and part count) in the largest free patch of the front or back silk, and JLCPCB's JLCJLCJLCJLC placeholder on the back silk so their order number is printed there, not on the front. Free means clear of pads, mask openings, other silk, courtyards, holes and the edge. KiCad's DRC is run before and after and a stamp that changes any count is taken off again.
| Argument | Type | Description |
|---|---|---|
| badge | boolean | Place the spec badge (default false). |
| parts | integer | Part count for the badge; counted from the board when unset. |
| title | string | Board title for the badge's second line. |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| revision | string | Revision for the badge ("rev B"). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
| badge_side | string | Silk side for the badge; the larger free patch when unset. |
Start place and route with your board plan (the JSON object from the board guide: board, stated, edge, chain, groups, near, side, fixed, keepouts, netClasses). The plan is clamped and returned as applied. Runs for minutes in the background: follow it with get_board_status. Needs an accepted schematic; one board run per design at a time.
| Argument | Type | Description |
|---|---|---|
| plan | object | The board plan object. Omit for the default plan. |
| design_id* | string | The design id returned by create_design or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"plan": {
"type": "object",
"description": "The board plan object. Omit for the default plan.",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
}
}
}Compile and check a complete SKiDL script: the symbol and footprint pre-flight (unambiguous typos are corrected and listed), SKiDL, the ERC score, KiCad ERC, floating subsystems, parts without a footprint, and supplier sourcing. Returns accepted plus blocking findings to fix and warnings. An accepted script becomes the design's circuit.py; one that is sent back is kept as attempt_N_circuit.py and leaves the design as it was. Takes up to a couple of minutes.
| Argument | Type | Description |
|---|---|---|
| code* | string | The complete SKiDL Python script. |
| design_id* | string | The design id returned by create_design or list_designs. |
| check_sourcing | boolean | Check the parts against supplier catalogues (default true). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id",
"code"
],
"properties": {
"code": {
"type": "string",
"maxLength": 400000,
"minLength": 1,
"description": "The complete SKiDL Python script."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
},
"check_sourcing": {
"type": "boolean",
"description": "Check the parts against supplier catalogues (default true)."
}
}
}Replace footprints in place with another footprint from a library in the project's fp-lib-table (library:name): the reference, value, position, rotation (or rot_deg), side, lock and schematic link stay, and nets move pad by pad. pad_map maps a NEW pad number to the OLD pad whose net it takes, for packages numbered differently. The schematic symbols' Footprint fields are updated too. Reports new pads left without a net and old nets left behind.
| Argument | Type | Description |
|---|---|---|
| swaps* | array | |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id",
"swaps"
],
"properties": {
"swaps": {
"type": "array",
"items": {
"type": "object",
"required": [
"refs",
"footprint"
],
"properties": {
"refs": {
"type": "array",
"items": {
"type": "string",
"maxLength": 40,
"minLength": 1
},
"maxItems": 500,
"minItems": 1
},
"pad_map": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string"
}
},
"rot_deg": {
"type": "number"
},
"footprint": {
"type": "string",
"pattern": "^[^:]+:.+$"
}
}
},
"maxItems": 100,
"minItems": 1
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
}
}
}After routing: every run redrawn as the fewest 0/45/90-degree segments that clear, and every track narrower than its net's netclass width widened where it fits (slid sideways, bumped around a lone obstacle, or necked only over the stretch that needs it; a via or thin track of another net moved aside when that is all that is in the way). No via is added or removed; a change that would split a pour is undone, and the board is kept only if KiCad counts nothing worse.
| Argument | Type | Description |
|---|---|---|
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
}
}
}Tie neighbouring same-net SMD pads of the plane nets (GND, the rails with a pour) together on their own layer with short tracks, so a group shares one via to the plane instead of one via per pad, as a designer does. A tie is placed only where it misses every other net's pad, its tracks and vias, and the board edge. Before routing: route afterwards with preserve_existing (the default). After routing and prune_vias: run prune_vias on those nets again.
| Argument | Type | Description |
|---|---|---|
| nets | array | Nets to tie (default: every net that has a pour). |
| layers | array | Copper layers to tie on (default F.Cu and B.Cu). |
| max_mm | number | Longest tie (default 2.5). |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| width_mm | number | Tie track width (default: the board's current track width). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
| avoid_copper | boolean | Treat other nets' tracks and vias as obstacles (default true). |
Replace the design's board with a .kicad_pcb you routed or edited yourself (the file, base64). The board must carry the design's circuit: every schematic part by reference, every pad on the net the netlist gives it; a footprint swap is allowed and recorded. Anything else is refused with the list of differences and nothing changes. The previous board is kept as circuit.before-upload.kicad_pcb. KiCad DRC judges the new board and releases or withholds the Gerbers, and the session chat gets a note of the upload. Not for a board workspace (import_kicad_project): its board tools edit the board in place.
| Argument | Type | Description |
|---|---|---|
| note | string | What was done to the board, for the session chat. |
| design_id* | string | The design id returned by create_design or list_designs. |
| board_base64 | string | The .kicad_pcb file, base64 (or give workspace_id). |
| rules_base64 | string | The .kicad_dru beside the board, base64. |
| workspace_id | string | A board workspace of yours (import_kicad_project, e.g. one made from this design with from_design_id): its board, project rules and .kicad_dru are taken from there, no download and upload. |
| project_base64 | string | The .kicad_pro beside the board, base64: its design rules and net classes judge the board (without it the design keeps its own). |
Grow the tracks (and optionally vias) of the named nets in place, each as wide as its clearance to every other net's copper, holes and the board edge allows, up to the net's target width. Nothing moves and no via is added, so the score does not change. Routers neck power down to the signal width wherever the class width did not fit their grid; most necks have room around them. List the heaviest current first: earlier nets take the room. Pours are refilled after each net and a widening that leaves the board less connected is backed out. The result names what still holds each remaining neck (a neighbour to move or reroute).
| Argument | Type | Description |
|---|---|---|
| nets* | object | Net -> target track width in mm. |
| vias | object | Net -> [diameter_mm, drill_mm] sizes to try, largest first; a via only ever grows. |
| guard | boolean | Refill pours and back out widenings that disconnect anything (default true). |
| necks | integer | How many remaining necks to report per net (default 12). |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
| Parts held at these origin positions; they are moved there on the board first. |
| shove | number | Legaliser: a part may take a spot held only by movable parts under this fraction of its area (default 0.3, 0 off). |
| gap_mm | number |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| grid_mm | number | Placement grid for free parts (0.254 = 10 mil, the designer habit); default off. |
| keepouts | array | Rectangles no part may cover, e.g. a bus corridor. |
| bottom_ok | array | Footprint-id substrings allowed on the bottom side (e.g. "0402"). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
| flip_cost | number |
| rotations | array |
| bottom_any | boolean | Any SMD-only part may go to the back (priced by flip_cost); LEDs, switches, displays and test points stay on top unless bottom_exclude says otherwise. |
| ic_halo_mm | number | Room kept around ICs with 48+ pads (default 1.5). |
| iterations | integer |
| net_weight | object |
| refit_from | object | Outline the current placement was drawn in; it is scaled affinely into the new outline before annealing (with t0 ~0.5: shrink a placement that closed). |
| split_cost | number | Price (mm of wirelength) of an SMD net with pads on both sides, i.e. a via. |
| from_scratch | boolean |
| hole_room_mm | number | Room kept around mounting holes on both sides for the screw head and standoff (default 1). |
| bottom_exclude | string | Regex of refs or footprint ids that stay on top regardless. |
| overlap_weight | number | Overlap price per mm2 at the end of the anneal (default 400; 4000 halves what a dense draw leaves). |
| edge_overhang_mm | object | Per edge ref, how far its body sits past the edge: default 0.5 for a USB/barrel/jack connector (at most its 1.2 mm lip), 0 (flush) for anything else, which may not overhang. |
| connector_room_mm | number | Room kept on the board side of every edge connector (default 2.5). |
| connector_flank_mm | number | Room kept on the flanks of every edge connector (default 1.0). |
| bottom_max_height_mm | number | Tallest part allowed on the back (3D-model height, default 1.0): the assembly box grows by the tallest back-side part. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"t0": {
"type": "number",
"maximum": 100,
"minimum": 0.01,
"description": "Start temperature (default 15). ~0.5 keeps the current placement and only tidies it (refine, or squeeze into a smaller outline)."
},
"edge": {
"type": "object",
"description": "Connector ref to the edge it sits on, optionally @mm: where along that edge its centre goes, from the outline's top-left corner (x on top/bottom, y on left/right) — the same meaning as in auto_place and a board plan. A fixed or locked ref keeps its pin.",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string",
"pattern": "^(left|right|top|bottom)(@\\d+(\\.\\d+)?)?$"
}
},
"halo": {
"type": "object",
"description": "Routing room per ref, mm (a number all round, or footprint-local [left, top, right, bottom]).",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"anyOf": [
{
"type": "number",
"maximum": 10,
"minimum": 0
},
{
"type": "array",
"items": [
{
"type": "number"
},
{
"type": "number"
},
{
"type": "number"
},
{
"type": "number"
}
],
"maxItems": 4,
"minItems": 4,
"additionalItems": false
}
]
}
},
"near": {
"type": "array",
"items": {
"type": "object",
"required": [
"ref",
"anchor"
],
"properties": {
"ref": {
"type": "string",
"maxLength": 40
},
"maxMm": {
"type": "number",
"exclusiveMinimum": 0
},
"anchor": {
"type": "string",
"maxLength": 40
}
}
},
"maxItems": 1000,
"description": "Keep ref at its anchor (a decoupling capacitor at its IC, a crystal at its MCU): the board plan's near constraint, as a strong pull in the anneal."
},
"refs": {
"type": "array",
"items": {
"type": "string",
"maxLength": 40
},
"maxItems": 2000,
"description": "The footprints that may move (default: every unlocked one)."
},
"seed": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991
},
"fixed": {
"type": "object",
"description": "Parts held at these origin positions; they are moved there on the board first.",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "object",
"required": [
"x_mm",
"y_mm"
],
"properties": {
"x_mm": {
"type": "number"
},
"y_mm": {
"type": "number"
},
"rot_deg": {
"type": "number"
}
}
}
},
"shove": {
"type": "number",
"maximum": 1,
"minimum": 0,
"description": "Legaliser: a part may take a spot held only by movable parts under this fraction of its area (default 0.3, 0 off)."
},
"gap_mm": {
"type": "number",
"maximum": 5,
"minimum": 0
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"grid_mm": {
"type": "number",
"maximum": 2,
"minimum": 0,
"description": "Placement grid for free parts (0.254 = 10 mil, the designer habit); default off."
},
"keepouts": {
"type": "array",
"items": {
"type": "object",
"required": [
"x_mm",
"y_mm",
"w_mm",
"h_mm"
],
"properties": {
"h_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"w_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"x_mm": {
"type": "number",
"description": "Left edge, board coordinates (KiCad mm, y grows downward)."
},
"y_mm": {
"type": "number",
"description": "Top edge."
}
}
},
"maxItems": 100,
"description": "Rectangles no part may cover, e.g. a bus corridor."
},
"bottom_ok": {
"type": "array",
"items": {
"type": "string",
"maxLength": 60
},
"maxItems": 50,
"description": "Footprint-id substrings allowed on the bottom side (e.g. \"0402\")."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
},
"flip_cost": {
"type": "number",
"maximum": 100,
"minimum": 0
},
"rotations": {
"type": "array",
"items": {
"type": "number"
},
"maxItems": 8
},
"bottom_any": {
"type": "boolean",
"description": "Any SMD-only part may go to the back (priced by flip_cost); LEDs, switches, displays and test points stay on top unless bottom_exclude says otherwise."
},
"ic_halo_mm": {
"type": "number",
"maximum": 10,
"minimum": 0,
"description": "Room kept around ICs with 48+ pads (default 1.5)."
},
"iterations": {
"type": "integer",
"maximum": 5000000,
"minimum": 1000
},
"net_weight": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "number",
"minimum": 0
}
},
"refit_from": {
"type": "object",
"required": [
"w_mm",
"h_mm"
],
"properties": {
"h_mm": {
"type": "number"
},
"w_mm": {
"type": "number"
},
"x_mm": {
"type": "number"
},
"y_mm": {
"type": "number"
}
},
"description": "Outline the current placement was drawn in; it is scaled affinely into the new outline before annealing (with t0 ~0.5: shrink a placement that closed)."
},
"split_cost": {
"type": "number",
"maximum": 100,
"minimum": 0,
"description": "Price (mm of wirelength) of an SMD net with pads on both sides, i.e. a via."
},
"from_scratch": {
"type": "boolean"
},
"hole_room_mm": {
"type": "number",
"maximum": 10,
"minimum": 0,
"description": "Room kept around mounting holes on both sides for the screw head and standoff (default 1)."
},
"bottom_exclude": {
"type": "string",
"maxLength": 200,
"description": "Regex of refs or footprint ids that stay on top regardless."
},
"overlap_weight": {
"type": "number",
"maximum": 100000,
"minimum": 1,
"description": "Overlap price per mm2 at the end of the anneal (default 400; 4000 halves what a dense draw leaves)."
},
"edge_overhang_mm": {
"type": "object",
"description": "Per edge ref, how far its body sits past the edge: default 0.5 for a USB/barrel/jack connector (at most its 1.2 mm lip), 0 (flush) for anything else, which may not overhang.",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "number",
"maximum": 5,
"minimum": 0
}
},
"connector_room_mm": {
"type": "number",
"maximum": 10,
"minimum": 0,
"description": "Room kept on the board side of every edge connector (default 2.5)."
},
"connector_flank_mm": {
"type": "number",
"maximum": 10,
"minimum": 0,
"description": "Room kept on the flanks of every edge connector (default 1.0)."
},
"bottom_max_height_mm": {
"type": "number",
"maximum": 20,
"minimum": 0,
"description": "Tallest part allowed on the back (3D-model height, default 1.0): the assembly box grows by the tallest back-side part."
}
}
}| "ml": the learned placer service (dense, two-sided when two_sided, honours keepouts); the packer when it is unavailable. |
| refine | string | "anneal": refine the placement by simulated annealing from this seed (wirelength-driven, same edge/fixed/keepouts, holes held) — the ML placer's structure with the annealer's tightness. |
| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| grid_mm | number | Placement grid for the refine step (0.254 = 10 mil); default off. |
| keepouts | array |
| bottom_ok | array | Refine: footprint-id substrings allowed on the back instead of bottom_any. |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
| flip_cost | number | Annealing price per bottom-side pad whose net has top pins (default 3). |
| two_sided | boolean | Small two-pad passives go to the back side. |
| bottom_any | boolean | Refine: any SMD-only part may go to the back, priced by flip_cost (default with two_sided); LEDs, switches, displays and test points stay on top. |
| ic_halo_mm | number | Refine: room kept around ICs with 48+ pads (default 1.5; 16+ pads and fine pitch get two thirds). |
| iterations | integer | Annealing iterations for refine (default 600000). |
| split_cost | number | Refine: price (mm of wirelength) of an SMD net with pads on both sides, i.e. a via. |
| hole_room_mm | number | Refine: room kept around mounting holes, both sides (default 1). |
| bottom_exclude | string | Refine: regex of refs or footprint ids that stay on top. |
| overlap_weight | number | Overlap price per mm2 at the end of the anneal (default 400; 4000 halves what a dense draw leaves). |
| connector_room_mm | number | Refine: room kept on the board side of every edge connector (default 2.5). |
| connector_flank_mm | number | Refine: room kept on the flanks of every edge connector (default 1.0); sets the pitch of connectors sharing an edge. |
| bottom_max_height_mm | number | Refine: tallest part allowed on the back (3D-model height, default 1.0). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"edge": {
"type": "object",
"description": "Ref to the edge it sits on, optionally @mm: where along that edge its centre goes, from the outline's top-left corner (x on top/bottom, y on left/right).",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string",
"pattern": "^(left|right|top|bottom)(@\\d+(\\.\\d+)?)?$"
}
},
"near": {
"type": "array",
"items": {
"type": "object",
"required": [
"ref",
"anchor"
],
"properties": {
"ref": {
"type": "string",
"maxLength": 40
},
"maxMm": {
"type": "number",
"exclusiveMinimum": 0
},
"anchor": {
"type": "string",
"maxLength": 40
}
}
},
"maxItems": 1000
},
"refs": {
"type": "array",
"items": {
"type": "string",
"maxLength": 40
},
"maxItems": 2000,
"description": "The footprints that may move."
},
"side": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"enum": [
"F",
"B"
],
"type": "string"
}
},
"fixed": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "object",
"required": [
"x_mm",
"y_mm"
],
"properties": {
"x_mm": {
"type": "number"
},
"y_mm": {
"type": "number"
},
"rot_deg": {
"type": "number"
}
}
}
},
"shove": {
"type": "number",
"maximum": 1,
"minimum": 0,
"description": "Legaliser: a part may take a spot held only by movable parts under this fraction of its area (default 0.3, 0 off)."
},
"groups": {
"type": "array",
"items": {
"type": "object",
"required": [
"refs"
],
"properties": {
"near": {
"type": "string",
"maxLength": 40
},
"refs": {
"type": "array",
"items": {
"type": "string",
"maxLength": 40
},
"minItems": 2
}
}
},
"maxItems": 100
},
"placer": {
"enum": [
"packer",
"ml"
],
"type": "string",
"description": "\"ml\": the learned placer service (dense, two-sided when two_sided, honours keepouts); the packer when it is unavailable."
},
"refine": {
"enum": [
"anneal"
],
"type": "string",
"description": "\"anneal\": refine the placement by simulated annealing from this seed (wirelength-driven, same edge/fixed/keepouts, holes held) — the ML placer's structure with the annealer's tightness."
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"grid_mm": {
"type": "number",
"maximum": 2,
"minimum": 0,
"description": "Placement grid for the refine step (0.254 = 10 mil); default off."
},
"keepouts": {
"type": "array",
"items": {
"type": "object",
"required": [
"x_mm",
"y_mm",
"w_mm",
"h_mm"
],
"properties": {
"h_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"w_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"x_mm": {
"type": "number",
"description": "Left edge, board coordinates (KiCad mm, y grows downward)."
},
"y_mm": {
"type": "number",
"description": "Top edge."
},
"reason": {
"type": "string",
"maxLength": 200
}
}
},
"maxItems": 100
},
"bottom_ok": {
"type": "array",
"items": {
"type": "string",
"maxLength": 60
},
"maxItems": 50,
"description": "Refine: footprint-id substrings allowed on the back instead of bottom_any."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
},
"flip_cost": {
"type": "number",
"maximum": 100,
"minimum": 0,
"description": "Annealing price per bottom-side pad whose net has top pins (default 3)."
},
"two_sided": {
"type": "boolean",
"description": "Small two-pad passives go to the back side."
},
"bottom_any": {
"type": "boolean",
"description": "Refine: any SMD-only part may go to the back, priced by flip_cost (default with two_sided); LEDs, switches, displays and test points stay on top."
},
"ic_halo_mm": {
"type": "number",
"maximum": 10,
"minimum": 0,
"description": "Refine: room kept around ICs with 48+ pads (default 1.5; 16+ pads and fine pitch get two thirds)."
},
"iterations": {
"type": "integer",
"maximum": 5000000,
"minimum": 1000,
"description": "Annealing iterations for refine (default 600000)."
},
"split_cost": {
"type": "number",
"maximum": 100,
"minimum": 0,
"description": "Refine: price (mm of wirelength) of an SMD net with pads on both sides, i.e. a via."
},
"hole_room_mm": {
"type": "number",
"maximum": 10,
"minimum": 0,
"description": "Refine: room kept around mounting holes, both sides (default 1)."
},
"bottom_exclude": {
"type": "string",
"maxLength": 200,
"description": "Refine: regex of refs or footprint ids that stay on top."
},
"overlap_weight": {
"type": "number",
"maximum": 100000,
"minimum": 1,
"description": "Overlap price per mm2 at the end of the anneal (default 400; 4000 halves what a dense draw leaves)."
},
"connector_room_mm": {
"type": "number",
"maximum": 10,
"minimum": 0,
"description": "Refine: room kept on the board side of every edge connector (default 2.5)."
},
"connector_flank_mm": {
"type": "number",
"maximum": 10,
"minimum": 0,
"description": "Refine: room kept on the flanks of every edge connector (default 1.0); sets the pitch of connectors sharing an edge."
},
"bottom_max_height_mm": {
"type": "number",
"maximum": 20,
"minimum": 0,
"description": "Refine: tallest part allowed on the back (3D-model height, default 1.0)."
}
}
}| unconnected_vias | boolean |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"refill": {
"type": "boolean"
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
},
"list_removed": {
"type": "boolean"
},
"trim_overhangs": {
"type": "boolean"
},
"dangling_tracks": {
"type": "boolean"
},
"duplicate_tracks": {
"type": "boolean"
},
"unconnected_vias": {
"type": "boolean"
}
}
}| max_skew_mm |
| number |
| Largest length mismatch kept (default: the pair's current skew, at least 1 mm). |
| min_gain_pct | number | Coupling points a reroute must gain to be kept (default 10). |
| time_budget_s | integer | Router budget per try (default 90). |
| bridge_islands | boolean |
| max_extra_vias | integer | Vias a kept reroute may add to the board (default 2). |
| total_budget_s | integer | Stop starting pairs after this (default 1800). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"pairs": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"maxItems": 500,
"description": "Only pairs with a leg matching these (default every pair under target_pct)."
},
"tries": {
"type": "integer",
"maximum": 6,
"minimum": 1,
"description": "Router seeds per pair; the best acceptable one is kept (default 2)."
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
},
"ml_options": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"target_pct": {
"type": "number",
"maximum": 100,
"minimum": 1,
"description": "Pairs coupled below this are tried (default 70)."
},
"max_skew_mm": {
"type": "number",
"description": "Largest length mismatch kept (default: the pair's current skew, at least 1 mm).",
"exclusiveMinimum": 0
},
"min_gain_pct": {
"type": "number",
"maximum": 100,
"minimum": 1,
"description": "Coupling points a reroute must gain to be kept (default 10)."
},
"time_budget_s": {
"type": "integer",
"maximum": 600,
"minimum": 10,
"description": "Router budget per try (default 90)."
},
"bridge_islands": {
"type": "boolean"
},
"max_extra_vias": {
"type": "integer",
"maximum": 20,
"minimum": 0,
"description": "Vias a kept reroute may add to the board (default 2)."
},
"total_budget_s": {
"type": "integer",
"maximum": 7200,
"minimum": 60,
"description": "Stop starting pairs after this (default 1800)."
}
}
}| The design id returned by create_design or list_designs. |
| footprint | string | A 'Library:Footprint' from search_kicad_footprint. Required for 3+ pins unless footprint_mod is given. |
| reference | string | Reference prefix, e.g. 'U'. |
| description | string |
| footprint_mod | string | Your own footprint: the full text of a .kicad_mod file, starting with '(footprint'. Its pad numbers must match the pin numbers. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id",
"name",
"pins"
],
"properties": {
"name": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "Part number, used as the symbol name (letters, digits, _ . + -)."
},
"pins": {
"type": "array",
"items": {
"type": "object",
"required": [
"number",
"name",
"type"
],
"properties": {
"name": {
"type": "string",
"maxLength": 60
},
"type": {
"type": "string",
"maxLength": 20,
"description": "input | output | bidirectional | power_in | power_out | passive | open_collector | tri_state | no_connect | unspecified"
},
"number": {
"type": "string",
"maxLength": 10
}
}
},
"maxItems": 2000,
"minItems": 1,
"description": "Every pin from the datasheet."
},
"datasheet": {
"type": "string",
"maxLength": 500
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
},
"footprint": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "A 'Library:Footprint' from search_kicad_footprint. Required for 3+ pins unless footprint_mod is given."
},
"reference": {
"type": "string",
"maxLength": 10,
"description": "Reference prefix, e.g. 'U'."
},
"description": {
"type": "string",
"maxLength": 500
},
"footprint_mod": {
"type": "string",
"maxLength": 1000000,
"minLength": 20,
"description": "Your own footprint: the full text of a .kicad_mod file, starting with '(footprint'. Its pad numbers must match the pin numbers."
}
}
}| vias_in_pads | string | 'allow': vias may sit in pin pads (the board must be ordered with filled and capped vias). |
| time_budget_s | integer | Router budget per routing call (default 120). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"rounds": {
"type": "integer",
"maximum": 10,
"minimum": 1,
"description": "Rip-and-reroute rounds (default 3)."
},
"router": {
"enum": [
"ml",
"ts"
],
"type": "string"
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"reach_mm": {
"type": "number",
"maximum": 5,
"minimum": 0.5,
"description": "Radius cleared of tracks and vias around a pad with no way out (default 1.5)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
},
"class_vias": {
"type": "boolean",
"description": "Route with the Default class's via instead of the board's smallest legal one."
},
"ml_options": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"vias_in_pads": {
"enum": [
"forbid",
"allow"
],
"type": "string",
"description": "'allow': vias may sit in pin pads (the board must be ordered with filled and capped vias)."
},
"time_budget_s": {
"type": "integer",
"maximum": 1800,
"minimum": 10,
"description": "Router budget per routing call (default 120)."
}
}
}| prune workers for a poured net (default 4). |
| max_nets | integer | Nets to try, most vias first (default 40). |
| min_vias | integer | Only nets with at least this many vias (default 2). |
| via_cost | number | Via price for the lone reroute (default 60). |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
| ml_options | object |
| time_budget_s | integer | Router budget per net (default 120). |
| bridge_islands | boolean |
| total_budget_s | integer | Stop starting nets after this (default 1800). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"nets": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"maxItems": 500,
"description": "Net names; * and ? wildcards, e.g. [\"USB_D*\", \"+3V3\"]."
},
"pairs": {
"type": "boolean",
"description": "Rip and reroute a differential pair (_H/_L, _P/_N, +/-) together (default true: a leg rerouted alone comes back at its own length; a step that degrades a pair is never kept)."
},
"pours": {
"type": "boolean",
"description": "Also polish the poured nets (default false): the pour and its stitch vias stay, the net is routed as a track tree on top, then its redundant stitch vias are pruned. A lottery: the tree that did this by accident (PCBGolf +3V3 53 -> 32) did not repeat in 2 deliberate tries."
},
"router": {
"enum": [
"ml",
"ts"
],
"type": "string"
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"workers": {
"type": "integer",
"maximum": 8,
"minimum": 1,
"description": "prune workers for a poured net (default 4)."
},
"max_nets": {
"type": "integer",
"maximum": 300,
"minimum": 1,
"description": "Nets to try, most vias first (default 40)."
},
"min_vias": {
"type": "integer",
"maximum": 50,
"minimum": 1,
"description": "Only nets with at least this many vias (default 2)."
},
"via_cost": {
"type": "number",
"maximum": 1000,
"minimum": 1,
"description": "Via price for the lone reroute (default 60)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
},
"ml_options": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"time_budget_s": {
"type": "integer",
"maximum": 600,
"minimum": 10,
"description": "Router budget per net (default 120)."
},
"bridge_islands": {
"type": "boolean"
},
"total_budget_s": {
"type": "integer",
"maximum": 7200,
"minimum": 60,
"description": "Stop starting nets after this (default 1800)."
}
}
}| The design id returned by import_kicad_project or list_designs. |
| max_width | integer |
| px_per_mm | number |
| courtyards | boolean |
| drc_markers | boolean |
| highlight_nets | array |
| highlight_refs | array |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"refs": {
"type": "boolean"
},
"side": {
"enum": [
"top",
"bottom"
],
"type": "string"
},
"layers": {
"type": "array",
"items": {
"type": "string",
"maxLength": 20
},
"maxItems": 16
},
"region": {
"type": "array",
"items": {
"type": "number"
},
"maxItems": 4,
"minItems": 4,
"description": "[x_mm, y_mm, w_mm, h_mm] crop; default the whole board."
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"markers": {
"type": "array",
"items": {
"type": "object",
"required": [
"x",
"y"
],
"properties": {
"x": {
"type": "number"
},
"y": {
"type": "number"
},
"label": {
"type": "string",
"maxLength": 80
}
}
},
"maxItems": 200
},
"ratsnest": {
"type": "boolean"
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
},
"max_width": {
"type": "integer",
"maximum": 4000,
"minimum": 200
},
"px_per_mm": {
"type": "number",
"maximum": 400,
"minimum": 1
},
"courtyards": {
"type": "boolean"
},
"drc_markers": {
"type": "boolean"
},
"highlight_nets": {
"type": "array",
"items": {
"type": "string",
"maxLength": 80
},
"maxItems": 50
},
"highlight_refs": {
"type": "array",
"items": {
"type": "string",
"maxLength": 40
},
"maxItems": 50
}
}
}| string |
| The design id returned by import_kicad_project or list_designs. |
| include_locked | boolean |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"all": {
"type": "boolean"
},
"nets": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"maxItems": 500,
"description": "Net names; * and ? wildcards, e.g. [\"USB_D*\", \"+3V3\"]."
},
"vias": {
"type": "boolean"
},
"zones": {
"type": "boolean"
},
"layers": {
"type": "array",
"items": {
"type": "string",
"pattern": "^(F|B|In\\d{1,2})\\.Cu$"
},
"maxItems": 32
},
"region": {
"type": "object",
"required": [
"x_mm",
"y_mm",
"w_mm",
"h_mm"
],
"properties": {
"h_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"w_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"x_mm": {
"type": "number",
"description": "Left edge, board coordinates (KiCad mm, y grows downward)."
},
"y_mm": {
"type": "number",
"description": "Top edge."
}
}
},
"tracks": {
"type": "boolean"
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
},
"include_locked": {
"type": "boolean"
}
}
}| wait_s | integer | Seconds to wait for the job (default 55). A job still running comes back with status "running": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot). |
| compact | boolean | true: the densest via the rules allow (0.4/0.2), which JLCPCB prices with a mandatory 4-wire Kelvin test (~$40 per order); false: never below the Kelvin-free 0.45/0.2. Unset: compact only on a board with an area-array package or vias in pads. |
| grid_mm | number |
| via_cost | number |
| design_id* | string | The design id returned by import_kicad_project or list_designs. |
| class_vias | boolean | Route with the Default class's via. Without it (and without via_diameter_mm) a route uses the board's smallest legal via where the class's is larger. |
| ml_options | object | Fields passed to the learned router service as they are (router "ml"): via_cost and via_cost_hi (prices in lattice cells; a move costs 1 and the served default via is 8, 12 while a net is on the quality ladder), ql_release (rejected rip trades before a net drops to via_cost, 0 never), endgame_release (false keeps failing nets at via_cost_hi), economy_via_mm (a via counts as this many mm in the economy pass, default 2), guide_via_w (per-cell via price from the model's via channel), plane_cost (signal copper on a poured layer, per cell), pair_w, guide_w, ripup, seed_offset, via_economy_victims (default 4; 8 trades harder), first_nets (globs routed before everything else: buses that span several connectors), draws (client-side: route this many seeded draws and keep the one that connects most then uses fewest vias; the tie-breaks alone move a 500-via board by about 8 vias), stitch_poured (false: no stitch via for a pad already on a layer poured with its net, GND pads on F/B), stitch_cluster_mm (join same-layer pads of a poured net within this reach by short traces and via once per cluster; 4 wins, 8 loses), stitch_cluster_nets (globs: which poured nets cluster), draw_open_penalty (client-side: vias an open net costs when draws are compared, default 0 = the most-connected draw always wins), layer_cost (per-cell price on named layers, {"F.Cu": 2}: the pour polish prices every layer but the plane's). |
| fewest_vias | boolean | Router "negotiated": the fine-grid router alone with its via phase (every net rerouted at 3x the via price and settled again): fewer vias, 2-3x the time. |
| pairs_first | boolean | Route the differential pairs (USB D+/D-, CAN H/L, X_P/X_N) alone first, then everything else around them: a port pad row only lets a pair out before the neighbours take its lane. |
| clearance_mm | number |
| via_drill_mm | number |
| vias_in_pads | string | 'forbid' (default): no via inside an SMD pad under 2 mm. 'allow': vias may sit in pin pads, for a board ordered with filled and capped vias (JLCPCB POFV); dense connector rows close that otherwise stay open. |
| seed_existing | boolean | ML router: the connected nets in scope are sent as their own routes (seed_copper) and the service reworks the finished board with its rip-up and via-economy passes; kept only when KiCad counts fewer vias. Scope nets to the routed signal nets (pour nets stay). |
| time_budget_s | integer | The full pipeline's wall-clock cap (default 1200), or a single route's budget (default 120, up to 900). |
| track_width_mm | number |
| via_diameter_mm | number |
| edge_clearance_mm | number |
| preserve_existing | boolean |
| negotiation_rounds | integer |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"nets": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"maxItems": 500,
"description": "Net names; * and ? wildcards, e.g. [\"USB_D*\", \"+3V3\"]."
},
"pours": {
"enum": [
"keep",
"engine"
],
"type": "string"
},
"router": {
"enum": [
"ts",
"ml",
"negotiated"
],
"type": "string",
"description": "Unset: the full pipeline (above) on the whole board, \"ml\" for nets. \"ml\": the learned router service alone, 1 to 8 layers; the time budget is its deadline. Nets outside the nets scope, and with preserve_existing the nets their copper already connects, keep that copper and everything else is routed around it (partial copper of a routed net is replaced). \"ts\": the local router, also the fallback when the service fails; pours/via_cost/grid_mm/negotiation_rounds apply to it only. \"negotiated\": PathFinder over every net at once, gridless on a coarse routing graph, the fine grid for the last open nets (the whole board from scratch, nets must be unset; GND routed as a net under its pour, then pruned). Minutes (its budget is 1800 s unless time_budget_s is given) but it closes dense boards the service leaves open. Follow with tidy_copper."
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"compact": {
"type": "boolean",
"description": "true: the densest via the rules allow (0.4/0.2), which JLCPCB prices with a mandatory 4-wire Kelvin test (~$40 per order); false: never below the Kelvin-free 0.45/0.2. Unset: compact only on a board with an area-array package or vias in pads."
},
"grid_mm": {
"type": "number",
"maximum": 0.5,
"minimum": 0.025
},
"via_cost": {
"type": "number",
"maximum": 50,
"minimum": 0
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
},
"class_vias": {
"type": "boolean",
"description": "Route with the Default class's via. Without it (and without via_diameter_mm) a route uses the board's smallest legal via where the class's is larger."
},
"ml_options": {
"type": "object",
"description": "Fields passed to the learned router service as they are (router \"ml\"): via_cost and via_cost_hi (prices in lattice cells; a move costs 1 and the served default via is 8, 12 while a net is on the quality ladder), ql_release (rejected rip trades before a net drops to via_cost, 0 never), endgame_release (false keeps failing nets at via_cost_hi), economy_via_mm (a via counts as this many mm in the economy pass, default 2), guide_via_w (per-cell via price from the model's via channel), plane_cost (signal copper on a poured layer, per cell), pair_w, guide_w, ripup, seed_offset, via_economy_victims (default 4; 8 trades harder), first_nets (globs routed before everything else: buses that span several connectors), draws (client-side: route this many seeded draws and keep the one that connects most then uses fewest vias; the tie-breaks alone move a 500-via board by about 8 vias), stitch_poured (false: no stitch via for a pad already on a layer poured with its net, GND pads on F/B), stitch_cluster_mm (join same-layer pads of a poured net within this reach by short traces and via once per cluster; 4 wins, 8 loses), stitch_cluster_nets (globs: which poured nets cluster), draw_open_penalty (client-side: vias an open net costs when draws are compared, default 0 = the most-connected draw always wins), layer_cost (per-cell price on named layers, {\"F.Cu\": 2}: the pour polish prices every layer but the plane's).",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"anyOf": [
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "string"
},
{
"type": "array",
"items": {
"type": "string",
"maxLength": 80
},
"maxItems": 64
},
{
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "number"
}
}
]
}
},
"fewest_vias": {
"type": "boolean",
"description": "Router \"negotiated\": the fine-grid router alone with its via phase (every net rerouted at 3x the via price and settled again): fewer vias, 2-3x the time."
},
"pairs_first": {
"type": "boolean",
"description": "Route the differential pairs (USB D+/D-, CAN H/L, X_P/X_N) alone first, then everything else around them: a port pad row only lets a pair out before the neighbours take its lane."
},
"clearance_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"via_drill_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"vias_in_pads": {
"enum": [
"forbid",
"allow"
],
"type": "string",
"description": "'forbid' (default): no via inside an SMD pad under 2 mm. 'allow': vias may sit in pin pads, for a board ordered with filled and capped vias (JLCPCB POFV); dense connector rows close that otherwise stay open."
},
"seed_existing": {
"type": "boolean",
"description": "ML router: the connected nets in scope are sent as their own routes (seed_copper) and the service reworks the finished board with its rip-up and via-economy passes; kept only when KiCad counts fewer vias. Scope nets to the routed signal nets (pour nets stay)."
},
"time_budget_s": {
"type": "integer",
"maximum": 1500,
"minimum": 10,
"description": "The full pipeline's wall-clock cap (default 1200), or a single route's budget (default 120, up to 900)."
},
"track_width_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"via_diameter_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"edge_clearance_mm": {
"type": "number",
"minimum": 0
},
"preserve_existing": {
"type": "boolean"
},
"negotiation_rounds": {
"type": "integer",
"maximum": 6,
"minimum": 1
}
}
}| design_id* | string | The design id returned by import_kicad_project or list_designs. |
| net_classes | array |
| min_track_mm | number |
| copper_layers | any |
| hole_to_hole_mm | number |
| default_track_mm | number |
| min_clearance_mm | number |
| hole_clearance_mm | number |
| board_thickness_mm | number | Finished board thickness; the stackup is rebuilt to it. JLCPCB FR4: 0.4, 0.6, 0.8, 1.0, 1.2, 1.6, 2.0 mm. |
| min_via_annular_mm | number |
| min_via_diameter_mm | number |
| default_clearance_mm | number |
| default_via_drill_mm | number |
| min_through_drill_mm | number |
| default_via_diameter_mm | number |
| copper_edge_clearance_mm | number |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"preset": {
"enum": [
"jlcpcb"
],
"type": "string"
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"stackup": {
"enum": [
"JLC04161H-7628",
"JLC04161H-3313"
],
"type": "string",
"description": "JLCPCB's 4-layer 1.6 mm impedance stackups, written into the board: 7628 (0.21 mm prepreg, their default) or 3313 (0.1 mm prepreg: thinner pairs for the same impedance). Needed before a net class states diff_impedance_ohm."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
},
"net_classes": {
"type": "array",
"items": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"maxLength": 60,
"minLength": 1
},
"nets": {
"type": "array",
"items": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"maxItems": 500,
"minItems": 1,
"description": "Net names; * and ? wildcards, e.g. [\"USB_D*\", \"+3V3\"]."
},
"track_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"clearance_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"via_drill_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"via_diameter_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"diff_pair_gap_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"diff_impedance_ohm": {
"type": "number",
"maximum": 200,
"minimum": 40,
"description": "Differential impedance (90 USB, 100 Ethernet/HDMI, 120 CAN): the pair width is derived from the gap and the stackup."
},
"diff_pair_width_mm": {
"type": "number",
"exclusiveMinimum": 0
}
}
},
"maxItems": 50
},
"min_track_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"copper_layers": {
"anyOf": [
{
"type": "number",
"const": 1
},
{
"type": "number",
"const": 2
},
{
"type": "number",
"const": 4
},
{
"type": "number",
"const": 6
},
{
"type": "number",
"const": 8
}
]
},
"hole_to_hole_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"default_track_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"min_clearance_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"hole_clearance_mm": {
"type": "number",
"minimum": 0
},
"board_thickness_mm": {
"type": "number",
"maximum": 3.2,
"minimum": 0.2,
"description": "Finished board thickness; the stackup is rebuilt to it. JLCPCB FR4: 0.4, 0.6, 0.8, 1.0, 1.2, 1.6, 2.0 mm."
},
"min_via_annular_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"min_via_diameter_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"default_clearance_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"default_via_drill_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"min_through_drill_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"default_via_diameter_mm": {
"type": "number",
"exclusiveMinimum": 0
},
"copper_edge_clearance_mm": {
"type": "number",
"minimum": 0
}
}
}| jlc_order_number | boolean | Place JLCJLCJLCJLC on the back silk (default false). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"badge": {
"type": "boolean",
"description": "Place the spec badge (default false)."
},
"parts": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0,
"description": "Part count for the badge; counted from the board when unset."
},
"title": {
"type": "string",
"maxLength": 60,
"description": "Board title for the badge's second line."
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"revision": {
"type": "string",
"maxLength": 20,
"description": "Revision for the badge (\"rev B\")."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
},
"badge_side": {
"enum": [
"front",
"back"
],
"type": "string",
"description": "Silk side for the badge; the larger free patch when unset."
},
"jlc_order_number": {
"type": "boolean",
"description": "Place JLCJLCJLCJLC on the back silk (default false)."
}
}
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"nets": {
"type": "array",
"items": {
"type": "string",
"maxLength": 80
},
"maxItems": 20,
"description": "Nets to tie (default: every net that has a pour)."
},
"layers": {
"type": "array",
"items": {
"type": "string",
"maxLength": 8
},
"maxItems": 4,
"description": "Copper layers to tie on (default F.Cu and B.Cu)."
},
"max_mm": {
"type": "number",
"maximum": 10,
"minimum": 0.3,
"description": "Longest tie (default 2.5)."
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"width_mm": {
"type": "number",
"maximum": 2,
"minimum": 0.05,
"description": "Tie track width (default: the board's current track width)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
},
"avoid_copper": {
"type": "boolean",
"description": "Treat other nets' tracks and vias as obstacles (default true)."
}
}
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id"
],
"properties": {
"note": {
"type": "string",
"maxLength": 400,
"description": "What was done to the board, for the session chat."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by create_design or list_designs."
},
"board_base64": {
"type": "string",
"maxLength": 24000000,
"minLength": 16,
"description": "The .kicad_pcb file, base64 (or give workspace_id)."
},
"rules_base64": {
"type": "string",
"maxLength": 24000000,
"description": "The .kicad_dru beside the board, base64."
},
"workspace_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "A board workspace of yours (import_kicad_project, e.g. one made from this design with from_design_id): its board, project rules and .kicad_dru are taken from there, no download and upload."
},
"project_base64": {
"type": "string",
"maxLength": 24000000,
"description": "The .kicad_pro beside the board, base64: its design rules and net classes judge the board (without it the design keeps its own)."
}
}
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"design_id",
"nets"
],
"properties": {
"nets": {
"type": "object",
"description": "Net -> target track width in mm.",
"propertyNames": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"additionalProperties": {
"type": "number",
"maximum": 10,
"exclusiveMinimum": 0
}
},
"vias": {
"type": "object",
"description": "Net -> [diameter_mm, drill_mm] sizes to try, largest first; a via only ever grows.",
"propertyNames": {
"type": "string",
"maxLength": 200,
"minLength": 1
},
"additionalProperties": {
"type": "array",
"items": {
"type": "array",
"items": [
{
"type": "number",
"maximum": 5,
"exclusiveMinimum": 0
},
{
"type": "number",
"maximum": 5,
"exclusiveMinimum": 0
}
],
"maxItems": 2,
"minItems": 2,
"additionalItems": false
},
"maxItems": 8,
"minItems": 1
}
},
"guard": {
"type": "boolean",
"description": "Refill pours and back out widenings that disconnect anything (default true)."
},
"necks": {
"type": "integer",
"maximum": 200,
"minimum": 0,
"description": "How many remaining necks to report per net (default 12)."
},
"wait_s": {
"type": "integer",
"maximum": 55,
"minimum": 0,
"description": "Seconds to wait for the job (default 55). A job still running comes back with status \"running\": follow it with get_board_job. A job is allowed the time its budget asks for (time_budget_s, total_budget_s, rounds), and survives a server restart (the op starts over from its snapshot)."
},
"design_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{8,80}$",
"description": "The design id returned by import_kicad_project or list_designs."
}
}
}