One endpoint. Post a target Pal on its own and it returns the breeding route to that Pal — the parent combinations that produce it, generation by generation. Add the passive or active skills you want and the Pals you already own that carry them, and the route also passes those skills down. Either way the answer is a tree plus an ordered list of breeding steps.
POST /api/solveJSON in, JSON out. Public, no key, no rate limit beyond ordinary abuse protection. Please send a descriptive User-Agent.
POST /api/solve
Content-Type: application/json
{
"target": "139.0", // Pal id. Required.
"want": ["legend", "movespeed_up_3"], // target passives, max 4
"act": "", // one active (combat) skill, optional
"groups": [ // the Pals you already own
{"passives": ["legend"], "pals": ["33.0"], "waza": "", "off": false},
{"passives": ["movespeed_up_3"], "pals": ["22.0"], "waza": "", "off": false}
],
"exclude": [], // Pal ids the plan may not use
"lang": "en" // language of names and messages
}
A group is a set of Pals that all carry the same passives. Put the
skills in passives (and at most one active in waza),
put the Pal ids in pals. Set off to true to keep a
group in the payload but leave it out of the search.
For the plain “how do I breed this Pal” question, send only
target (optionally with groups for Pals you own). The
answer comes back with "mode": "free" and up to three routes
trading fewer generations against fewer wild catches.
{
"ok": true,
"url": "https://paltree.app/calc/5tzx0hzy19zx0kzy0t", // opens this same plan on screen
"results": [{
"gens": 3, // generations deep
"breeds": 5, // breeding operations
"wild": ["121.0", "184.0"], // Pals you must catch
"totalEggs": 28.0, // expected eggs over the whole plan
"steps": [{
"i": 1, "a": "184.0", "b": "22.0", "c": "91.0",
"p": ["movespeed_up_3"], // passives held at this point
"prob": 28.57, // worst-case inheritance chance, %
"bestProb": 32.0, // with junk passives cleared
"eggsMin": 4, "eggsMax": 4
}],
"tree": { "id": "139.0", "children": [ ... ], "leaf": false }
}],
"unknown": [], // Pal ids we did not recognise
"unknownSkills": [] // skill keys we did not recognise
}
Unrecognised skill keys are dropped, not rejected, and listed in
unknownSkills. Check it: if every key in want is
dropped, the request silently becomes the plain “how do I breed this
Pal” question and comes back with "mode": "free".
That is the real answer to the request above. Leaves of the tree carry
kind: wild for a Pal you must catch,
carrier or owned for one you supplied.
A failure is "ok": false with a machine-readable
code and a translated error sentence.
noPathNo plan exists with the Pals allowed. A
partial list shows which subsets of the passives are reachable.
ownedA Pal you already listed has every target passive, so no breeding is needed.
needTargetThe target id was missing or not a breedable Pal.
The warning selfOnly on a success means the target only breeds
with itself, so wild catches were assumed.
Pal ids look like "139.0"; the part after the dot separates
variants, so "33.0" is Direhowl. Passive and active skills use
string keys such as "legend" (Legend) and
"movespeed_up_3" (Swift) — not their display names. The
calculator page ships the full list of both in its bootstrap payload, so the
simplest way to look an id up is to open https://paltree.app/ and read
window.BOOT.
The url in every successful response opens the same calculation
already filled in, with the tree drawn and every step's probability shown. If
you are answering someone with this data, give them that link too.