Score semantics
The numbers the API returns are not probabilities: each one carries a class that says what it measures, what it can be compared with and what it cannot.
The API returns around twenty numbers between 0 and 1, under three names: confidence, strength and value. They look like confidence levels; none of them is one. This page explains what each number measures, what it may be compared with, and what to read instead when you need to decide.
What these numbers are not
No number returned by the API is a probability. A confidence.entity of 0.85 does not mean "an 85 % chance that the entity is right"; a match_strength.value of 0.5 does not mean "one chance in two". The contract says so in two ways:
- the
calibrationfield, carried by every score object (confidence,match_strength,provenance,cadence_detail,calendar_pattern,lifecycle), is alwaysnon_calibree: none of these values has been related to an observed frequency on a reference corpus; - the
x-noryo-scoreextension, carried by every number in the contract that looks like a confidence, always declares itsclass,calibration: non_calibreeandis_probability: false, and depending on the numbercomparable_within,not_comparable_with,formula,sourceorduplicate_of.
non_calibree is the only value the contract admits in this version, and that is a constraint, not a convention. These annotations can be read at https://api.noryo.app/openapi.json or in the generated reference.
The six classes
The classes are described under components.x-noryo-score-classes in the contract, exactly as served:
| Class | Meaning | Monotonic | Use |
|---|---|---|---|
declared_constantconstante declaree | Une valeur POSEE par la personne qui a ecrit le motif ou la regle, lue telle quelle. Elle ne resulte d'aucun calcul sur la transaction : toute transaction qui touche le meme motif recoit le meme nombre. Mesure sur 644 libelles : la precision n'est PAS monotone en ce nombre (0,85 -> 0,86 ; 0,88 -> 0,33 ; 0,92 -> 0,25 ; 0,97 -> 0,79). | false | Ne l'utilisez ni comme seuil ni comme rang. Utilisez `policy.outcome`. |
evidence_ratiopart des signaux corroborants | `present / possible` : combien de signaux corroborants ce TYPE sait produire, et combien sont effectivement la. Le denominateur DEPEND du type — 5 pour `refund_of`, 4 pour `reversal_of`, 2 pour `transfer_pair`, 5 criteres heterogenes pour une serie — et `corroborations` le rend a cote, parce que sans lui le nombre ne se lit pas. | within_type | Comparable entre deux objets du MEME type et de la meme `detector_version`. Jamais entre un `refund_of` et un `transfer_pair`, jamais entre une relation et une serie. |
calendar_filltaux de remplissage calendaire | La part des periodes calendaires de l'etendue observee qui portent au moins une occurrence, pour l'hypothese de cadence retenue. ★ `0` signifie « aucune hypothese calendaire n'a ete retenue » (cadence `irregular_recurring`), pas « faible ». | within_cadence | Comparable entre deux series de MEME cadence. Une hebdomadaire sur 8 semaines et une annuelle sur 2 ans ne se comparent pas. |
anchor_stabilitystabilite de l'ancrage | Un jeu de constantes par TYPE d'ancrage (1,0 pour un jour fixe de semaine, 0,9 pour un jour ajuste au jour ouvre) et deux formules lineaires sur l'etendue des jours pour `fixed_day_of_month` et `flexible_calendar_window`. `0` pour `unknown`. ★ `flexible_calendar_window` a DEUX regles selon la cadence : une constante 0,3 sans `day_range` en cadence `weekly`/`biweekly`, et `1 - etendue/10` (plancher 0,1) avec `day_range` en cadence mensuelle ou plus longue. | within_anchor_type_and_cadence | Comparable entre deux series de MEME type d'ancrage ET de MEME cadence. Un 0,33 `fixed_day_of_month` et un 0,3 `flexible_calendar_window` ne disent pas la meme chose ; un 0,3 `flexible_calendar_window` hebdomadaire et un 0,3 mensuel non plus. |
authority_tiebreakdepartage a autorite egale | La confiance declaree de la source d'une activite. Elle n'entre en jeu qu'APRES la nature d'autorite (`curated` > `deterministic` > `provider` > `inferred` > `participant`), pour departager deux sources de meme nature. | within_nature | Ne compare jamais deux natures : un 0,95 `inferred` ne l'emporte pas sur un 0,90 `curated`. |
text_coveragecouverture textuelle | Un rapport de longueurs : la part du libelle utile que le motif apparie couvre, ou la part d'un motif compact qu'un fragment tronque recouvre. C'est une propriete du TEXTE, pas une preuve d'identite : un seuil dessus couterait 61 justes pour ecarter 17 faux. | true | Comparable entre libelles. N'en faites pas un seuil d'identite. |
Where each class applies
| Field | Class | Comparable with | Never comparable with |
|---|---|---|---|
resolution.confidence.entity, .counterparty, .transaction_type, .category, .location | declared_constant | nothing | any other score |
relationships[].match_strength.value | evidence_ratio | a relationship of the same type and the same detector_version | a relationship of another type, series[].match_strength |
series[].match_strength.value | evidence_ratio | a series of the same detector_version | relationships[].match_strength, cadence_detail.strength |
series[].cadence_detail.strength (repeated in lifecycle.cadence_strength) | calendar_fill | a series of the same cadence | another cadence, match_strength, calendar_pattern.strength |
series[].calendar_pattern.strength (repeated in lifecycle.calendar_anchor) | anchor_stability | a series of the same anchor type and the same cadence | another anchor type, another cadence, cadence_detail.strength, match_strength |
resolution.counterparty.semantics.provenance.strength | authority_tiebreak | a source of the same nature | another nature of authority, any other score |
resolution.counterparty.evidence.coverage, .covered | text_coverage | other descriptors (coverage), other truncated cases (covered) | any identity or series score (coverage); any other score (covered) |
lifecycle.cadence_strength and lifecycle.calendar_anchor are not additional scores: they are copies (duplicate_of in the contract), returned so that the lifecycle can be read on its own. The name confidence under resolution is kept for ti_v1 compatibility: read it as "declared strength of the pattern", never as a confidence.
Comparing: only within a class and a type
A number may only be compared with another number of the same class, produced for the same kind of object, by the same detector version. Take evidence_ratio: the value is present / possible, and the denominator depends on the type (5 possible signals for refund_of, 4 for reversal_of, 2 for transfer_pair, 5 heterogeneous criteria for a series). The same 0.5 is therefore one signal out of two for a transfer pair and two out of four for a reversal:
{
"type": "transfer_pair",
"match_strength": {
"value": 0.5,
"calibration": "non_calibree",
"corroborations": { "present": 1, "possible": 2 }
}
}JSON{
"type": "reversal_of",
"match_strength": {
"value": 0.5,
"calibration": "non_calibree",
"corroborations": { "present": 2, "possible": 4 }
}
}JSONThis is why corroborations is returned next to value: without present and possible, the number cannot be read. A series match_strength counts five criteria (calendar cadence, fixed or narrow amount, at least three occurrences, known entity, specialised type): same name, different measure.
The other classes follow the same logic:
calendar_fill: between series of the same cadence. A weekly series over eight weeks and a yearly one over two years cannot be compared.0means "no calendar hypothesis was retained" (cadenceirregular_recurring), not "weak".anchor_stability: between series of the same anchor type and the same cadence. A0.33onfixed_day_of_monthand a0.3onflexible_calendar_windowdo not say the same thing, andflexible_calendar_windowchanges its rule with the cadence.0corresponds to theunknowntype.authority_tiebreak: only after the nature of authority. The ordercurated,deterministic,provider,inferred,participantis declared, not derived from a number: a0.95of natureinferreddoes not beat a0.90of naturecurated.strengthonly separates two sources of the samenature.text_coverage: a property of the text, the share of the useful descriptor covered by the pattern (coverage) or the share of a compact pattern covered by a truncated fragment (covered, thetronqueroute). Comparable between descriptors, it is not proof of identity.
Never rank two objects of different types by their score, and never add up scores of different classes.
Decide with policy.outcome, not with a threshold
The declared_constant class is the most tempting one to use as a threshold. The five numbers under resolution.confidence are constants set by the person who wrote the pattern or the rule: every transaction that hits the same pattern receives the same number. Their class is marked monotonic: false in the contract: the measured precision, documented in the class description, is not monotone in this number, and a threshold on it does not separate right from wrong.
Read resolution.policy instead:
outcomeisresolved(every dimension the archetype requires is present),partial(the nature is known, a required dimension is missing, or signals contradict each other) orunresolved(even the nature of the transaction is unknown);missingnames the absent dimensions:counterparty_entity,counterparty_type,transaction_typeorresolution_policy;archetypesays what "resolved" requires here: a transfer to a person isresolvedwithout any entity, a cash withdrawal without a merchant, a card purchase requires its counterparty.
{
"policy": {
"outcome": "partial",
"archetype": "achat_carte",
"missing": ["counterparty_entity"],
"policy_version": "ti_resolution_v1"
},
"counterparty": null,
"transaction_type": { "canonical": "card_purchase", "evidence": "rail_rule", "contradiction": null },
"confidence": {
"entity": 0,
"counterparty": 0,
"transaction_type": 0.95,
"category": 0,
"location": 0,
"calibration": "non_calibree"
}
}JSONHere confidence.transaction_type is 0.95 even though the transaction is not resolved: the type is known from a rail rule, the counterparty is not. It is policy.outcome and policy.missing that tell you so, not the numbers.
0 has a precise meaning per field: abstention for entity, unknown role for counterparty, conflict with no common ancestor for transaction_type; location is always 0 in this version. When signal_conflicts is not empty, outcome is partial: the engine declines to conclude. An identity abstention (identity_abstention), by contrast, leaves outcome at resolved if the archetype did not require an entity.
Keeping a number: keep the version with it
If you store a value, store the version that produced it: resolution.versions (engine, resolution_policy, calibration) for the resolution, detector_version for a relationship or a series. The same value, under another version, may no longer measure the same thing.
Statistical calibration: not available
No statistical calibration is available in this version. When a real calibration exists, it will enter through a declared migration, together with the corpus that supports it. Until then, the confidence and strength values are deterministic evidence strengths: the same pattern, signals and version always give the same number. Decide on policy.outcome, on the enums (status, lifecycle.state, identity.status) and on the evidence (evidence, corroborations, signals.used).
Further reading
- Enrich a transaction
- Relationships
- Recurring series
- Counterparties and entities
- Generated reference, every field with its
x-noryo-score
Published on 2026-09-17 11:19 UTC (version 1).