# How it works

> One cleaning engine, three trips through it: a read, your build, and an agent's visit to your site.

Source: https://docs.buildonto.dev/how-it-works
Section: Start

---

How it works\[01\]

## How it works

One cleaning engine, three trips through it. Pick one and watch it go — click a stage to stop on it.

### Three trips

\[02\]

Read APIA readServe · buildYour buildServe · requestAn agent visit

api.buildonto.dev · Vercel, Node

Your code or agent — POST /v1/read { url }

1.  01Check the key
    
    Looked up by its SHA-256 hash — Onto keeps the hash, never the key. Calls from the MCP connector carry a short-lived token Onto minted after your OAuth sign-in instead.
    
2.  02Take a credit and a slot
    
    From your account's month, which resets at 00:00 UTC on the 1st, plus one of your concurrent slots. It's taken before the cache, so a cached read still counts; a failed read is refunded. Numbers per plan on [Rate limits](/api/limits).
    
3.  03Look in the cache
    
    One hour, keyed on the deploy, the endpoint and the exact URL — so every deploy starts empty. `"fresh": true` skips the lookup.
    
    *   `hit`→answer from the cache and stop here
    *   `miss`→carry on
    
4.  04Check the address
    
    The host must resolve to a public address — checked again on every redirect. GitHub file links are rewritten to their raw version.
    
5.  05Read robots.txt
    
    Fetched with a 5-second limit. If it can't be fetched, the read goes ahead; reading your own verified site skips the check.
    
    *   `Disallow: /`→for GPTBot or \* → ROBOTS\_BLOCKED, before the page is fetched
    
6.  06Fetch the page
    
    15 seconds for the whole fetch, up to 5 redirects, 10 MB at most, no JavaScript run. HTML pages also get two quick probes for a Markdown version the site already serves.
    
7.  07Clean it
    
    HTML goes through `@ontosdk/core`, after tables are normalised. PDFs are read as text; JSON, CSV and plain text pass through.
    
8.  08Score it
    
    Every HTML read gets an AIO score. [/v1/score](/api/score) and [/v1/read-and-score](/api/read-and-score) return it; `/v1/read` doesn't.
    
9.  09Cache, log, answer
    
    The result is cached, usage is logged without waiting on it, and the slot is freed.
    

JSON — or raw Markdown with Accept: text/markdown

your build · @ontosdk/next

Your CI — next build && onto-next

1.  01Find the pages
    
    Every prerendered page under `.next/server/app`. Routes rendered per request get no `.md`.
    
2.  02Clean each one
    
    The same `@ontosdk/core` cleaner the Read API uses — once per build, not once per request.
    
3.  03Write the files
    
    One `.md` per route in `public/.onto/`, and `llms.txt` from your `onto.config.ts`.
    
4.  04Send the list to your dashboard
    
    Posted to `api.buildonto.dev/api/files` with your site key — only when `ONTO_API_KEY` is set. That's what fills Serve → Routes.
    

public/.onto/\*.md, public/llms.txt, and your dashboard's route list

your edge · @ontosdk/next middleware

Someone asks yoursite.com for /pricing

1.  01Who's asking
    
    A known AI crawler's User-Agent, an `Accept: text/markdown` header, or `?onto` on the URL.
    
    *   `anyone else`→straight through to your page — the middleware does nothing
    *   `agent`→carry on
    
2.  02Note the visit
    
    Sent to Onto without waiting on the reply, so it never slows the answer. Skipped when no site key is set.
    
3.  03Hand over the Markdown
    
    The prebuilt `/.onto/pricing.md`, fetched from your own site — nothing is extracted now.
    
4.  04Add your context
    
    Only if you've written some for the route, and only on Serve Pro and above. This step does wait for Onto's reply.
    

Markdown for agents, your page for everyone else

### One engine

\[03\]

Both products clean pages with `@ontosdk/core`. The Read API runs it per request on the URL you send; the SDK runs it once per build on your own pages. The same service at `api.buildonto.dev` also answers [batch](/api/batch), [map](/api/map) and [extract](/api/extract), and hosts the [MCP server](/mcp) at `/mcp`.

[@ontosdk/coreThe cleaner and scorer, under both products.\[01\]](/sdk/extractor)[@ontosdk/nextThe build CLI and middleware for Next.js 14+ App Router sites.\[02\]](/sdk/installation)[api.buildonto.devThe Read API and the hosted MCP server.\[03\]](/api/read)

**Two kinds of key, not interchangeable.** Read keys (`onto_sk_…`) are for the API and MCP. Site keys (`onto_live_…`) are for the SDK, which sends them as `ONTO_API_KEY`.

### Where data lives

\[04\]

SupabasePostgres + Auth

*   Your accountSign-in with email and password, GitHub or Google (Supabase Auth)
*   Read keysapi\_keys — the SHA-256 hash and first 12 characters
*   Sites and their keyssites — what the SDK authenticates with
*   Route listonto\_files — a copy for Serve → Routes; agents are served from your own site
*   Agent visitsagent\_events — Serve analytics
*   Read usageusage\_events — the Usage page
*   Plans and creditssubscriptions, one per account and product; profiles.credit\_balance with a ledger

Vercel KVRedis

*   Monthly counter and concurrent slotsChecked on every call
*   Markdown cacheOne hour
*   MCP sign-insRegistered clients, one-time codes and refresh tokens for Onto's own OAuth

PolarPayments

*   Checkout and billingWebhooks keep the plans above in step

Your siteYour hosting

*   public/.onto/\*.mdWhat agents are actually served

**One account, two products, two plans.** An account can hold a Read plan and a Serve plan at once: `subscriptions` is keyed on `(user_id, kind)`, where kind is `read` or `serve`.

Copy as Markdown[](/how-it-works.md "Open the raw Markdown")

---
## Structured Data (JSON-LD)
```json
{
  "@context": "https://schema.org",
  "@type": "WebSite",
  "name": "Onto Docs",
  "url": "https://docs.buildonto.dev",
  "description": "How to use Onto: serve AI agents Markdown from your Next.js site, call the Read API, connect over MCP, and read the AIO score.",
  "inLanguage": "en",
  "publisher": {
    "@type": "Organization",
    "name": "Onto",
    "url": "https://buildonto.dev"
  }
}
```