A score is a number, and a number is not an explanation. The part of a Heatrail response worth reading is the list beside it: the reasons that fired, in words, in the same JSON, on the same round trip. This article is about why those sentences exist, why nobody at Heatrail can change the rules behind them without shipping code, and why the last step is a person rather than a rule.
The property
Every score comes from a rule that can be named, and the response names it. There is no model in the scoring path. The rules cannot be changed through the API. A person in the shop decides what to do.
Why it holds
What actually arrives at the shop
An order comes in. The shop's own server calls the check endpoint while the basket is still on screen, and what comes back is a small object: a score, a short list of reasons, an opaque handle for the matched trail. Nothing else happens. Heatrail does not touch the order or the payment and has no way to (see advisory by construction). What follows is the shop's decision, taken in the shop's own code.
In practice the response lands in a queue. The shop's rule sends this order somewhere a human will look at it, and the human reads the reasons. That is where the design pressure comes from: if a person is going to read the output, the useful artefact is the sentence rather than the number. A score of 72 tells a fulfilment clerk nothing they can argue with. A line saying that the same customer identifier matched a network confirmed fraud trail, with how many shops it touched and how recently, is something a person can weigh against the order in front of them, agree with, or reject.
So the reasons are not a debugging aid bolted onto a scoring service. The number is a convenience for routing. The sentences are what gets a decision made, and what gets it defended later if anyone asks how it was reached.
Figure 1
The rules ship as code, not as settings
Scoring configuration lives versioned in the repository. It changes when someone writes a commit and deploys it, and every such change writes an event into the append only ledger, so what the rules were on any given day is evidence rather than a memory. There is no settings screen for it, no toggle in the operator console, no field an administrator can nudge before lunch.
The rules endpoint follows from that. It exists so an operator can read the configuration and the log of its changes, and it is read only by construction: there is no write route to reach. Claims like that are usually made about intentions rather than about shape, and this one is about shape. A complete takeover of an operator account, full credentials, full session, every step up passed, still cannot change how anyone is scored. The attacker in that scenario is looking for a write path that was never built. Changing scoring means a commit, a deploy, and a ledger entry naming the moment.
What a reason is allowed to say
A reason is a category about the order in front of this shop. It says that something matched, roughly how widely and roughly how recently. It never carries another shop's evidence, never names another merchant, never returns an identifier or a hash, and never carries enough detail to let somebody map the shared signal by sending checks at it and reading the answers back. That last constraint is why the response is categorical in the first place, and it is worked through properly in why the network cannot be enumerated.
A reason that explained more would help the person in the queue, and it would help somebody probing the network just as much. The response resolves that one way: the shop is told what is relevant to its own order, in categories, and no further.
Rules, and what they are not called
Scoring is rule based. The thing that decides a score is a rule, and a shop can be told which one fired. That is the whole claim, and the vocabulary matches it: the phrase machine learning does a great deal of unearned work in this industry, and a rule engine described in that vocabulary would be a lie that happens to sell better.
The commitment about vocabulary is as firm as the one about code. If a model ever enters the scoring path, this page says so on the day it does, and says what it changed about the reasons a shop receives.
Rules are legible and deliberately simple. Simple rules work here because the signal comes from shops labelling harm they confirmed, not from cleverness at the scoring step. A denser network improves the answer more than a better model would.
Verify it
The reasons a check can return are published, so start by reading them. They sit in the API reference beside the two hundred response for POST /v1/check, with the rule about what they may and may not contain, and the enumerated reason_code values a shop sends back when it labels an order.
curl -s https://heatrail.eu/docs/api/ | grep -i reasonsThen check the second half of the property, that the rules cannot be moved through the API. Reading the rules view needs an operator session. The half that needs no session is about which routes exist at all:
curl -si -X POST https://api.heatrail.eu/dashboard/rules | head -1
# HTTP/1.1 405 Method Not AllowedThat answer arrives before any credential is looked at: it is the router saying no such route was ever defined, not an authorisation layer saying no. There is no version of that request, with any key, at any privilege level, that becomes a two hundred. The read route answers with the configuration and the ledger entries recording every time it changed.
Last, and this is the one a merchant can check on their own orders: a shop can always be told which rule fired, because the response already says so. The same score and reasons for the most recent check on an order can be fetched again through the explain endpoint, for a details view in your admin. You do not have to ask us. You have it.
Legal footing
Machine readable reasons are what make Article 13(2)(f) and Article 15(1)(h) answerable if a shop ever has to explain the logic involved: the logic is a named rule, recorded, with the reason it produced attached to the order. They are also part of why a Heatrail score is not a solely automated decision under Article 22. A person reads the reason before anything follows, and the service holds no power to act on the order in any case. The shop remains the controller of that decision. See advisory by construction for why the capability to act was removed rather than withheld.
Related
- Advisory by construction, on why nothing follows from a score until a person in the shop makes it follow.
- Why the network cannot be enumerated, on why a reason is a category and never a record.
- The API reference, for the response shape and the published reason codes.