# Craton: SOV coder

You are reading the machine twin of https://oncraton.com/sov-coder/, the
page where a person pastes a messy schedule of values and gets OED codes
back.

The page says, in short: messy rows in, OED codes out. Each line of text
describes one building. For every line, Craton returns an OED 5.0.0
`OccupancyCode` and `ConstructionCode`, the model's confidence in each, and
whether each cleared the confidence gate. A code below the gate is left
blank for a person, with the model's suggestion and up to two alternatives
beside it. Nothing is coded silently. The result downloads as a CSV. A
code the person picks is marked "Chosen by you" there, and its
confidence column holds the model's probability for the code picked.

- The model: Jev, TypeSafe's decision model, reached through Vercel's AI
  Gateway. It picks one answer from a fixed list for each code; it writes
  no text. Craton keeps an answer only when it maps to a real OED code and
  the confidence is at or above the gate the API reports.
- The route behind the page: `POST https://api.oncraton.com/exposure-codes`
  with a sandbox key. Documentation:
  https://docs.oncraton.com/exposure-codes
- Response schema: https://docs.oncraton.com/schema/exposure-codes.v0.schema.json
- The sibling tool, for rows that describe more than one building (split
  those first): https://oncraton.com/multi-building-detector/ (machine twin
  /multi-building-detector.md)

## The call

Get a free sandbox key first (one call, no card), then send up to 50 rows
of at most 1,000 characters each. The body is the rows and nothing else: the
questions each row is asked are Craton's, fixed, never the caller's.

```bash
curl -sS -X POST https://api.oncraton.com/signup \
  -H 'Content-Type: application/json' -d '{"label": "my-agent"}'
# keep api_key.secret from the answer as CRATON_KEY

curl -sS -X POST https://api.oncraton.com/exposure-codes \
  -H "Authorization: Bearer $CRATON_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"rows": ["Houston TX, 2 sty wd frm garden apts, blt 1978", "Tampa FL, CMU block warehouse, wood truss roof"]}'
```

Each entry in `rows` of the answer has a `status` (`coded`,
`needs_review` or `unanswered`) and, per OED field, `code` (null unless
it cleared the gate), `proposed`, `name`, `confidence`, `cleared`, `why`
and `alternatives`, and the provider's `generation_id` for that row. The
answer also names the model, the question set's SHA-256, the gates and a
`run_id`.

The provider sets the pace: Craton codes about 25 rows a minute, spaced
evenly across everyone using it, so a 25-row paste takes about a minute. The
page sends ten rows a request and up to 250 rows in one go; a row the
provider did not get to comes back `unanswered`, and a button on the page
sends just those rows again.

When the service is switched off, over its daily budget or cannot reach
the model, the answer is `503 exposure_coding_unavailable` and nothing is
coded. Over a limit, `429 rate_limited` with `Retry-After`.

## Where the rows go

The text of each row goes to an AI provider to be coded: Jev by TypeSafe,
through Vercel's AI Gateway. Craton does not store the rows or the answers.
Leave out personal data, such as people's names. The page itself keeps one
thing in the browser: a free sandbox key, so it does not sign up again on
every visit.
