Skill: pick the engine¶
For: an AI agent deciding which MagicON AI engine answers the question in front of it.
There are four design engines. Choosing the wrong one is the most common and most expensive mistake, because every one of them returns a confident, well-formed result — so a wrong choice does not fail, it succeeds at answering a question nobody asked.
Every path and rate limit below was verified against the production API on
2026-09-09. Base URL https://api.pcbgenerator.com, every route POST,
anonymous, Content-Type: application/json, no Authorization header.
Decide in one table¶
| Your user's question | Engine | Endpoint | Limit |
|---|---|---|---|
| "Design a transmitter / power amplifier chain to N dBm" | design_rf_chain |
/api/rf-chain/design-sync |
5/min |
| "Design a receiver / how sensitive can I get at this frequency" | design_rf_receiver |
/api/receiver/design |
30/min |
| "Design a radar / transceiver / T/R front end that shares one antenna" | design_tr_module |
/api/tr-module/design |
15/min |
| "What is the gain / NF / OIP3 of these stages" | run_link_budget |
/api/link-budget/compute |
120/min |
If two of these look right, the tie-breaker is at the bottom of this page.
The four engines¶
design_rf_chain — a transmit chain¶
POST /api/rf-chain/design-sync — 5 requests/minute. The tightest limit on
the platform; it does the most work.
Picks and cascades VCO → driver → attenuator pads → power amplifier → filtering → isolator → connector → substrate, converges on your output target, and returns a power flow, a power tree, a priced BOM and a power verdict.
curl -X POST https://api.pcbgenerator.com/api/rf-chain/design-sync \
-H "Content-Type: application/json" \
-d '{"params": {"frequency": 2.4, "targetOutputPower": 30, "application": "wifi"}}'
Note the nesting: the design point goes inside params. Frequency is in GHz
here.
⚠ This route enforces no required field, and that is a trap. Measured: {}
returns 200, "status": "success", a selected PA (CG2H40010F) and a 1.0 dBm
output. It answered a design point you did not state, so a 200 from this route
is not evidence that you asked a meaningful question.
The response tells you, if you look: chain.params echoes the design point it
actually used, and on that empty call it reads
{"frequency": null, "target_output_power": 0, "application": null, …}.
Compare chain.params against what you sent before you report anything. On a
real call it echoes your values back —
{"frequency": 2.4, "target_output_power": 30, "application": "wifi", …}.
Two siblings:
| Variant | Endpoint | Limit | Use when |
|---|---|---|---|
| Streaming | /api/rf-chain/design |
5/min | You want progress events. Returns Server-Sent Events, not a JSON body |
| Compare alternatives | /api/rf-chain/design-multi |
30/min | Your user asked for options or trade-offs rather than one answer |
design_rf_receiver — a superheterodyne receiver¶
POST /api/receiver/design — 30 requests/minute.
Picks limiter → LNA → image filter → mixer → local oscillator → IF filter → IF amp → digital step attenuator, plus connector and substrate, then computes the frequency plan, cascade NF, sensitivity, ADC interface and interference products.
curl -X POST https://api.pcbgenerator.com/api/receiver/design \
-H "Content-Type: application/json" \
-d '{"rfFrequencyHz": 9400000000, "bandwidthHz": 10000000, "requiredSnrDb": 12}'
Frequency is in hertz here. Required field: rfFrequencyHz — omit it and you
get 422 {"detail": "rfFrequencyHz is required to choose parts for a receiver"}.
design_tr_module — a shared-antenna front end¶
POST /api/tr-module/design — 15 requests/minute.
Designs a transmit chain and a receive chain and the shared element between them (T/R switch or circulator + limiter), then computes isolation, leakage and stress budgets across the junction.
curl -X POST https://api.pcbgenerator.com/api/tr-module/design \
-H "Content-Type: application/json" \
-d '{"frequencyGhz": 9.4, "targetOutputPowerDbm": 40,
"application": "radar", "transmitDutyCyclePercent": 10}'
Frequency is in gigahertz here. Required: frequencyGhz and
targetOutputPowerDbm.
Reach for this whenever one antenna is shared, even if your user only described one direction. Designing the transmitter and the receiver as two separate calls gives you two chains with nothing joining them — no isolation budget, no leakage budget, no stress check on the part that carries full transmit power, and no shared-path insertion loss. Those budgets are the reason this engine exists. See Design a module.
run_link_budget — cascade maths on stages you already have¶
POST /api/link-budget/compute — 120 requests/minute. The cheapest call
here, by an order of magnitude, and the right one for what-ifs.
Takes an ordered list of stages you supply and returns cascaded gain, Friis noise figure, reciprocal-sum OIP3 and P1dB headroom. It selects nothing.
curl -X POST https://api.pcbgenerator.com/api/link-budget/compute \
-H "Content-Type: application/json" \
-d '{"stages": [{"name": "LNA", "gainDB": 15, "nfDB": 1.2},
{"name": "IF filter", "gainDB": -1.5, "nfDB": 1.5}],
"inputPowerDbm": -80}'
Measured: totalGainDB 13.5, cascadedNfDB 1.2428, finalOutputDbm −66.5.
Required: stages — omit it and you get 422 {"detail": "missing_stages"}.
⚠ The stage keys are gainDB and nfDB — capital DB. Spell them gainDb
/ nfDb and the same request still returns 200, with totalGainDB: 0.0 and
cascadedNfDB: null, because the stages parsed as stages with no figures in them.
Measured, both spellings, on the same two stages. A zero cascade from a chain that
obviously has gain is the signature; check your key casing before you report it.
Use it when your user brought their own parts, when they want to know what one change does, or when you would otherwise burn a 5/min design call to answer "what if the LNA had 2 dB more gain".
⚠ Every number in a link budget is a number you supplied. Nothing in it is grounded in the catalogue, so the result is exactly as good as its inputs. If the stage figures did not come from your user or from a design result you already have, do not present the answer as a computed fact about real hardware.
The compute / design split¶
The receiver and the T/R module each exist twice: a compute-only route that does maths on stages you supply, and a design route that picks catalogue parts first and then computes. This is the most common wrong turn agents take.
| Engine | Compute only | Limit | Picks parts and computes | Limit |
|---|---|---|---|---|
| Receiver | /api/receiver |
60/min | /api/receiver/design |
30/min |
| T/R module | /api/tr-module |
60/min | /api/tr-module/design |
15/min |
| Cascade | /api/link-budget/compute |
120/min | (none — it never selects) | — |
| Transmit chain | (none — it always selects) | — | /api/rf-chain/design-sync |
5/min |
Rule: if your user described an intent ("X-band, 10 MHz bandwidth, 12 dB
SNR"), you have no stages to give, so you want the /design route. If they
described hardware ("here are my four stages"), you want the compute-only route.
⚠ The compute-only routes are cheaper and faster, which makes them tempting. They
are the wrong tool for an intent, and they will not tell you so:
POST /api/receiver refuses without stages (422), but POST /api/tr-module
answers {} with a 200 — an empty question with a confident-looking shape
around it.
Units and names differ per route. Read the field name.¶
| Route | Frequency field | Unit |
|---|---|---|
/api/rf-chain/design-sync |
params.frequency |
GHz |
/api/receiver/design |
rfFrequencyHz |
Hz |
/api/tr-module/design |
frequencyGhz |
GHz |
9400000000 and 9.4 are the same frequency. A route that wanted GHz and got
9400000000 will not correct you.
Tie-breakers¶
- "Design a radar." →
design_tr_module. A radar shares one antenna, and the isolation, leakage and stress budgets are the point. - "Design a transmitter" but they mentioned receiving too. →
design_tr_module. Two independent chains are not a module. - "How good is this receiver?" with parts named. →
run_link_budgetif you have the stage figures;/api/receiverif you have full cascade stages and want the frequency plan and ADC interface too. - "What are my options?" →
/api/rf-chain/design-multi(30/min) rather than five separate 5/min design calls. - You are iterating on one variable. →
run_link_budgetat 120/min, then one design call to confirm. - You are unsure between two engines. → Ask your user one question. It costs less than a design call and far less than a confident answer to the wrong question.
Limits, errors and state¶
- Limits are per calling IP, and exceeding one returns
429. Anything without its own limit falls back to 1000 requests/hour. 422means your request is missing or has a malformed field. Thedetailnames the field — for example"frequencyGhz is required to design a T/R module". Ask your user for it. Do not invent it.500is our fault. Retry once, then report it. A malformed design point is a422, never a500.- Nothing persists. No session, no project id, no result to fetch later, and nothing to poll. If a second call needs a figure from the first, carry it yourself.
Related¶
- Read a design result — what the fields mean once a result arrives.
- Design a module — the end-to-end procedure.
- API reference for LLMs — every public route, including the stackup solver, thermal, PDN, compliance and the component catalogue.
- OpenAPI schema — field-level request and response detail, generated from the running code.