# POST /v1/read-and-score

> Markdown + AIO score + hallucination risk in one request.

Source: https://docs.buildonto.dev/api/read-and-score
Section: Read API

---

POST /v1/read-and-score\[01\]

## POST /v1/read-and-score

Markdown + AIO score + hallucination risk in one request.

**Path note:** the PRD originally called this `/v1/read+score`, but the literal `+` URL-decodes to a space in many HTTP clients, so the canonical path is `/v1/read-and-score`.

### When to use it

\[02\]

Use this when you need both the clean Markdown _and_ the AIO score in a single call — typical for agents that want to decide whether to trust a page before feeding it to the LLM. Costs 1 credit (`/v1/score` on its own is free). Cached for 1 hour just like `/v1/read`; a cache hit still costs 1 credit. Always returns JSON — the `Accept` header is ignored.

### Endpoint

\[03\]


```
POST https://api.buildonto.dev/v1/read-and-score
Authorization: Bearer onto_sk_live_YOUR_KEY
Content-Type: application/json
```

Request body matches [/v1/read](/api/read):

urlstringreq

Public URL to fetch + clean + score.

freshboolean

Skip the cache lookup and fetch again. The result is still written to the cache.

### Response

\[04\]

The [/v1/read](/api/read) response plus the scoring fields from [/v1/score](/api/score). It is not a literal union: the `bot_preview` and `note` fields returned by `/v1/score` are not included here, and `stats` uses the `/v1/read` shape. There is no `warnings` field.


```
{
  "status": "success",
  "url": "https://stripe.com",
  "markdown": "# Stripe — Online payments…",
  "metadata": { "title": "...", "description": "...", "language": "en" },

  "aio_score": 90,
  "grade": "Excellent",
  "hallucination_risk": "low",

  "insights": {
    "robots_allowed": true,
    "waf_blocked": false,
    "markdown_supported": true,
    "json_ld_present": true,
    "semantic_hierarchy": true
  },
  "penalties": [
    "Warning: Unmanaged AI Payload. Native Markdown is present but lacks Onto-specific brand controls, versioning, and agent analytics."
  ],
  "benefits": [
    "Native Markdown Support: This site natively serves Markdown to agents, which improves extraction but lacks the Onto-optimized management layer.",
    "Payload Optimization: Native Markdown reduced the agent payload to 14.8KB, eliminating ~98% of visual noise."
  ],
  "recommendations": [
    {
      "priority": "Medium",
      "title": "Migrate to Onto SDK",
      "description": "Native Markdown detected but lacks agent analytics and policy controls. Upgrade to the Onto layer."
    }
  ],

  "stats": {
    "raw_html_size_kb": 605.0,
    "markdown_size_kb": 14.8,
    "reduction_percent": 97.6,
    "extraction_time_ms": 412
  },
  "cache": { "hit": false, "ttl_seconds": 3600 }
}
```

**PDF and text URLs are not scored.** The AIO scorer is HTML-only, so a URL that resolves to a PDF or a text format (JSON, CSV, XML, plain text) still returns extracted text in `markdown`, but `aio_score`, `grade` and `hallucination_risk` come back as `null`, `insights` is replaced by `{ "pdf_text_extracted": true }`, and `penalties`, `benefits` and `recommendations` are empty arrays.

As on [/v1/score](/api/score), the `penalties`, `benefits` and `recommendations` strings come from a fixed scorer set and are forwarded unchanged.

### Response headers

\[05\]

Header · Description

`X-Onto-Cache`

HIT or MISS — whether the response came from the 1-hour cache.

`X-RateLimit-Remaining`

Monthly plan credits left. Stays 0 while you are billed from bought credits.

`X-RateLimit-Reset`

When monthly plan credits reset (end of the UTC month).

`X-Onto-Billed`

“plan” or “credit” — which balance paid for this call.

`X-Concurrent-Remaining`

Concurrency slots still free on your account.

`X-Credits-Remaining`

Bought-credit balance after the call. Sent only when the call was billed to credits.

### Example

\[06\]


```
curl -X POST https://api.buildonto.dev/v1/read-and-score \
  -H "Authorization: Bearer $ONTO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://stripe.com"}'
```

Copy as Markdown[](/api/read-and-score.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"
  }
}
```