# Verdicts

> valid · invalid · error — what each means, which ones you pay for, and which are worth retrying.

Every answer carries a `status`. There are exactly three, and the difference
between them is the difference between three different things you should do next.

## `valid`

The answer passed the check.

`result` holds the artifact. `verified_by` identifies the version of the rules that accepted it.
**Billable.**

`valid` is a statement about the artifact, not about the world: it passed its
format's checks. A chart's `data` says whether its values came from your request
(`supplied`) or were illustrative values you allowed (`generated`).

## `invalid`

The check refused the answer. There is no `result`; `reason` says why as a
code you can branch on, and `detail` says it in plain language:

| `reason` | Meaning |
|---|---|
| `unsupported_feature` | The request needs something this oracle cannot draw |
| `chart_type_mismatch` | The request names a kind of chart, and no chart of that kind passed in this format |
| `no_valid_answer` | Nothing that passed could be produced for this request; say more concretely what it should contain |

**Billable, and that is not a technicality.** The work was done, and a reliable
"no" is the thing you are buying. An API that charged only for
answers it liked would have every incentive to loosen the rules until
everything passed — which is precisely the failure mode a verdict exists to
prevent.

Retrying an identical intent may produce a different verdict, because the same
intent can return a different artifact. Retrying it many times is a way to spend
credits.

An `invalid` can also mean the request needs something the oracle's language
cannot express — a colour gradient in a figure, say. Rather than return an
approximation that looks like an answer, the oracle declines at once and
`detail` names what was missing. It is billed like any `invalid`, and it is
worth retrying: describe the figure without that feature.

## `error`

Something on our side failed. `credits` is `0`, `retryable` is `true`, and
nothing was charged.

It still appears in your [usage log](https://app.formalogic.io/usage), with `0` credits, because an outage
you cannot see afterwards is one you cannot hold us to.

Note that `error` arrives with HTTP **200**. The request was understood and
processed; the oracle could not complete it. Branch on `status`, not on the
status line — see [Errors](https://docs.formalogic.io/errors) for the failures that do change it.

## In one table

| `status` | `result` | Billed | Retry |
|---|---|---|---|
| `valid` | yes | yes | no need |
| `invalid` | no | yes | only with a different intent |
| `error` | no | no | yes, with backoff |

## Why not a score

A confidence number would let a caller pick their own threshold, and every caller
would pick a different one — at which point the guarantee is theirs, not ours,
and "verified" means nothing across two integrations. A verdict is a commitment.

See [Handle every verdict](https://docs.formalogic.io/handling-verdicts) for what this looks like in
client code.
