# For software and AI agents

New on Record serves the records Ohio's governments post online, as each office published them: bids, meeting agendas, building permits, liquor permits, licenses, business filings, food-service inspections, public notices and motor carrier registrations. Each record names its office and links to where the office posted it.

Software reads them through an HTTP API at `https://api.newonrecord.com`. AI agents read them through an MCP server at `https://api.newonrecord.com/mcp`. Both serve the same records, under the same limit.

## The records

The checker reads most sources once a night, starting at 2 a.m. Eastern time, or 3 a.m. during daylight saving time. Some are updated by hand on a set schedule instead: every week, every month or every three months. A record is new the night it is first seen, and has a new version each time a change to it is seen.

Each kind of record has its own fields, described by a JSON Schema. `GET https://api.newonrecord.com/v1/kinds` lists the kinds, each with its schema and how many records it holds.

A record comes with its `id`, its `kind`, its `place`, its `office`, its `source`, a `url` at the office, its `fields`, when it was first seen and last changed, its own date, how many versions it has, and the `terms` its source posts. Records about private people are never kept. A person's name appears only where a record names them in a public or business role: an official, an appointee, a license holder or a company's owner.

## Connect an AI agent

Claude Code:

```
claude mcp add --transport http newonrecord https://api.newonrecord.com/mcp
```

With a key, so the agent reads under your account's limit:

```
claude mcp add --transport http newonrecord https://api.newonrecord.com/mcp --header "Authorization: Bearer YOUR_KEY"
```

Codex, in `~/.codex/config.toml`, with the key in the environment variable it names:

```
[mcp_servers.newonrecord]
url = "https://api.newonrecord.com/mcp"
bearer_token_env_var = "NEW_ON_RECORD_KEY"
```

Cursor, in `~/.cursor/mcp.json`:

```
{"mcpServers": {"newonrecord": {"url": "https://api.newonrecord.com/mcp", "headers": {"Authorization": "Bearer YOUR_KEY"}}}}
```

The server's tools are `list_kinds`, `find_place`, `search_records`, `get_record`, `list_changes` and `ask_for_data`. Each says what it returns and what it counts.

## In Claude and ChatGPT

Claude, on the web, the desktop and a phone, and ChatGPT can't send a key, so the person using them signs in instead, and their reads count on that account, free or paid.

- In Claude: add a custom connector, under Connectors in Claude's settings, with the address `https://api.newonrecord.com/mcp`.
- In ChatGPT: turn on developer mode in ChatGPT's settings, then add an app with the address `https://api.newonrecord.com/mcp`.

Looking up the kinds of record and the places needs no sign-in. The first time the app reads records, it asks you to sign in: give your email, type the six-digit code sent to it and choose Sign in, then choose Allow. A browser already signed in to New on Record goes straight to Allow. The app then reads as your account. To stop it, choose Disconnect on the account page.

## Keys

A key lets a program read under an account's own limit instead of its address's. [Make a key](https://newonrecord.com/sign-in?next=/account) after signing in with your email: the account page shows each new key once, and an account holds up to five. A key starts `nor_`, and goes in the `Authorization` header after `Bearer`. A key that was revoked, or isn't one, answers `401` and no records. The MCP server answers it, and every refusal below, as a tool error with the same body.

## Call the API

Every call is a `GET` but one, and answers JSON. The OpenAPI document is at `https://api.newonrecord.com/v1/openapi.json`.

- `GET /v1/kinds`: the kinds of record, with their schemas and counts, the fields that hold an office's own number, the statuses in our words, how many sources were read this week, and how many records fill each field.
- `GET /v1/places?q=Franklin`: places whose name holds the words, each with the `id` the other calls take. A county covers the cities, villages and townships in it, and its health district.
- `GET /v1/records`: records, newest first by their own date. Narrow them by `kind`, `place` or `source`, by `since` and `until` (times with a time zone), by `q`, words in the record's text, by `match`, the office's own number exactly (`match=license_number:12345`), and by `state`, a status in our words (`active`, `issued`). `limit` is at most 100, and `cursor` is the `next_cursor` the last page gave. Each record says its status beside the office's word, and how fresh its source is.
- `GET /v1/records/<id>`: one record, by the `id` a list gave.
- `GET /v1/changes`: what happened to records after `since` or after the `cursor`, oldest first, each change with its record as it is now: records new on their source's list, never older ones read later, so a program that keeps the cursor it was given misses none.
- `POST /v1/asks` with `{"text": "...", "kind": "...", "place": "..."}`: what you wanted and didn't find, up to 20 an hour. The people who run the directory read every one.
- `/v1/states/oh`, `/v1/jurisdictions`, `/v1/sources`, `/v1/platforms`, `/v1/families` and `/v1/runs`: the directory itself, the sources and what each night's check found.

For a script, a key goes in the `Authorization` header:

```
curl -H "Authorization: Bearer $NEW_ON_RECORD_KEY" "https://api.newonrecord.com/v1/records?kind=procurement.solicitation&place=us/oh/county/franklin"
```

## The daily limit

The limit counts records. A call costs one for each record it returns, and one when it finds none, a record asked for by an `id` that isn't there among them. A call refused at the limit, the burst or for what it asked, `/v1/kinds`, `/v1/places`, the directory's reads and `/v1/asks` cost nothing. The day starts at midnight UTC.

- With no key: 500 records a day for each address. Calls with no key also share a daily ceiling, all addresses together. Past it they answer `503` until midnight UTC, and calls with a key go on.
- With a free account's key: 500 records a day of its own, however many people share your address. An account's keys share one count.

A records call over HTTP that succeeds says where the count stands, in `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` (seconds until the day starts again). Past the limit, a call answers `402` with a JSON problem body (RFC 9457). Its `detail` is a few plain sentences to pass on to the person behind the agent. It also carries `limit`, `resets_at` and `docs_url`, a link to this section. For a caller not on the paid plan, it carries the `plan`, and the ways to read more that are open: `key_url` to make a free key, for a caller with none, and `pay_url` while the paid plan can be bought. A connection from an app whose directory bars a price, as ChatGPT's does, gets the limit and the link only.

More than 10 calls a second from one caller may answer `429`, with `Retry-After`.

## Using the records

Each record is a public record as its office published it. Keep its office's name and link with it. The records may not be used to decide on anyone's credit, employment, housing or insurance. An office's own site is the record of what it posted: the directory reads it on a schedule and may miss a change. The rest is in [the terms](https://newonrecord.com/terms).

## Ask for what's missing

When a call finds nothing, say what you wanted with `POST /v1/asks` or the `ask_for_data` tool. [Ask for a source](https://newonrecord.com/request-coverage) on the site, or write to frankie@newonrecord.com.
