| ids | Yes | Every identifier established: cik, ticker, company_name, lei, figi, isin, cusip, register_id, register_country. A key absent here appears in `unresolved` with a reason — never silently dropped. | |
| type | Yes | | |
| brand | No | | |
| notes | No | | |
| query | Yes | | |
| related | No | Entities that collapsed INTO the match, each carrying `collapsed_by`. | |
| sources | Yes | Per-identifier provenance. Every key in `ids` has a matching key here. | |
| resolved | Yes | At least one identifier was established. Read `match_status` and `unresolved` for WHICH — a company can be resolved in a national register with no CIK at all. | |
| searched | No | EVERY register asked, with its own as-of date and row count. A register that could not be reached carries `error` — 0 rows with an error is "we could not ask", 0 rows without one is "nothing is there", and they are different answers. | |
| registers | No | The matched entity as every register that carries it — the match (flagged `matched: true`) plus anything that collapsed into it. A Companies House number AND the LEI that crosswalks to it are the SAME answer, not rivals. | |
| resources | No | | |
| candidates | No | Rivals, best first. Populated on "ambiguous" and on "matched" alike. | |
| ingredient | No | | |
| unresolved | Yes | Per-identifier reason an id could NOT be established — the honest twin of `ids`. | |
| cik_withheld | No | A CIK that came back from a FUZZY SEC name match and is NOT asserted, because the spine matched a stronger non-US candidate. The number is here so a caller who wanted the US filer can still use it; what changed is that we no longer claim it IS the answer. See `unresolved.cik` for the reason. | |
| match_status | No | The headline to branch on. "ambiguous" is an ANSWER, not a failure: two companies matched the name equally well and both are in `candidates`. "no_match" means every register in `searched` was asked and none carried it. "incomplete" means one of them could NOT be asked (it carries an `error` in `searched[]`), so the candidate set is short by an unknown amount and no id is asserted — distinct from "ambiguous" because a RETRY is what resolves it, not a narrower query; `fanout_incomplete` names the unreachable registers and carries, under `withheld_match`, the candidate that would have been returned on a complete fan-out. | |
| figi_withheld | No | A FIGI that matched this name in OpenFIGI (`figi_match: "name_search"`) and is NOT asserted, because `match_status` is "incomplete": a name search cannot tell a company apart from a security carrying its name, and the registers that would have settled it are the ones we could not ask. A `ticker_map` FIGI is never withheld this way — it is corroborated by the resolved ticker it came from. Carried so a caller who accepts the caveat can use it; see `unresolved.figi`, and retry, since a transiently rate-limited register completes on the next call. | |
| match_scoring | No | The margin rule's own inputs, so a caller can see WHY it fell where it did. | |
| sec_alternatives | No | EDGAR's own discarded near-misses on a name match, surfaced instead of dropped. | |
| fanout_incomplete | No | Present IFF at least one register in `searched[]` carried an `error` — set even when `match_status` stayed "ambiguous". `withheld_match` is the candidate this call declined to ASSERT because a register was missing, carried rather than discarded so a caller who accepts the caveat can still use it. | |
| match_explanation | No | Plain words. Always present when the spine ran, and required on "ambiguous" and "no_match". | |