---
url: https://ora.ai/docs/api/schemas
title: "Schemas - Docs"
description: "Every response and request schema in ora's OpenAPI spec, field by field."
crawled_at: 2026-10-18T19:27:05Z
ask: https://ora-ai.ora.run/ask
docs: https://ora-ai.ora.run/.well-known/ora/docs
lang: en
---
# Schemas

### NlwebAskRequest

object · query · object · required · context · object · prefer · object · meta · object

### AuditCheck

object · id · string · required

Stable check identifier (e.g. 'api-error-model'). Route fixes and dedupe by this - names are for display, ids are stable.

name · string · required · Human-readable check title · status · string · required

One of: pass | fail | warning | error | pending | na. Act on 'fail'/'warning'; skip 'na'; 'pending' means the scan has not finished.

score · number · required

Points earned WITHIN this layer. Not 0-100 score points - layers are normalized to a weight before they count, so do NOT read maxScore-score as score uplift. Use estScoreGain for that.

maxScore · number · required

Points available within this layer for this check (the within-layer denominator, not the 0-100 scale).

estScoreGain

number

Estimated points this fix would add to the overall 0-100 score, already normalized to the layer weight. THIS is the uplift signal - rank fixes by it. Present on actionable (fail/warning) checks; an estimate, not exact.

bonus

boolean

Upside-only check: passing it raises the score, failing it never lowers the score. Build it only if the surface genuinely exists.

maturity

string

verified (counts toward the 0-100 score) or emerging (forward-looking, excluded from the denominator - a lower priority)

tier

string

How strongly ora expects this check: required (the baseline every product is measured against), recommended (scored, outside the baseline), or emerging (excluded from the score). Display metadata - rank fixes by estScoreGain, not by tier.

specUrl

string

Canonical spec / standard URL this check evaluates against, when one exists. Advisory - the link may change on any release.

mcpKind

string

When the check ran against a specific MCP server within a multi-MCP bundle: that server's kind (currently product | docs | other; advisory - new kinds may appear on any release). Absent for non-MCP checks and single-MCP scans.

mcpUrl

string

The URL of the MCP server this check scored against. Present only alongside mcpKind.

details

string

What the scan observed for this check

recommendation

string

Concrete fix that would make this check pass. The primary thing to act on.

naReason

string

Why this check does not apply to this product - it is skipped, not a deduction

### AuditLayer

object · id · string · required

Layer id: discovery | accessibility | usability | payments (historical scans may carry retired ids)

name · string · required · score · number · required · maxScore · number · required · checks · array · required

### AuditScanResult

object · domain · string · required · name · string · required · score · integer · required · scoreMax · number · required · 100 · essentials · object

Present only when the caller passed ?include=essentials. Carries its own `score` - there is no separate top-level essentials score field.

grade · string · required · gradeColor · string · required · ctaMessage · string | null · required · scannedAt · string · required · durationMs · integer | null · required · analysisStatus · string

complete = all checks resolved; partial/stuck = still running - re-scan before acting complete | partial | stuck

pendingChecks

array

Ids of checks still resolving (empty/absent when analysisStatus is complete)

layers · array · required · topFixes · array · required

Actionable (fail/warning) checks ranked by ora: non-bonus first, then estimated uplift descending, capped at 6. Render verbatim - do not re-rank.

url · string · required

Canonical ora.ai deep link for the domain

generatedAt · string · required · source · string · required · ora.ai · contractVersion · string · required

The contract version this payload conforms to. SemVer: a major means a response-envelope break - a stable field removed, renamed, or changed in meaning, or the default response format flipping - and is safe to pin. Additive changes and check-catalog membership changes ship on a minor. See docs/api.md -> Contract and versioning. 1.32.0

servedFromCache

boolean

Present only when this body is a stored result served by the freshness gate instead of a fresh scan. Absent on a live scan. true

resultAgeSeconds

integer

Age of the served stored result in seconds (also sent as the Age response header). Present with servedFromCache.

mcpAuthRequired

boolean

Legacy marker retained for compatibility with stored results. New authentication-required scans return an MCP_AUTH_REQUIRED error without score or grade; public reads of a historical marked result return the same error. true

urlKind

string

How the scanned input was classified and stored. 'ephemeral' = disposable result (tunnel host, or ephemeral: true) that is excluded from rankings and deleted after a few days. Absent on older stored results. domain | mcp | mcp-app | ephemeral

category

string

Canonical market category ora classified the domain into (e.g. 'Infrastructure & DevOps'). Advisory; absent when the domain is unclassified.

agenticSummary

string

One-sentence natural-language verdict on the domain's agent-readiness, generated after analysis completes. Advisory; absent on partial results and on older stored results.

finalUrl

string

The URL the scan actually fetched after following redirects. Distinct from `url`, which is the canonical ora.ai deep link for the domain.

nextAction

object

Present only when the scan is stuck (partial for over 30 minutes; the worker likely failed) or on the score route's 404 miss - the HTTP request that recovers the score. A plain partial resolves on its own: poll the 202's Location URL instead of re-scanning.

competitors

object | null

Experimental (no stability guarantee): competitive context drawn from the leaderboard, present only when the request carries ?competitors=1. Null when the domain is unranked or the leaderboard read failed. Shape may change on any release.

siteType

object | null

Experimental (no stability guarantee): the scan scored against what the site is, present only when the request carries ?include=siteType. Null when the scan has no layers to score. Shape may change on any release.

### AuditScoreResult

object · domain · string · required · name · string · required · score · integer · required · scoreMax · number · required · 100 · essentials · object

Present only when the caller passed ?include=essentials. Carries its own `score` - there is no separate top-level essentials score field.

grade · string · required · gradeColor · string · required · scannedAt · string | null · required · analysisStatus · string

complete = all checks resolved; partial/stuck = still running - re-scan before acting complete | partial | stuck

pendingChecks

array

Ids of checks still resolving (empty/absent when analysisStatus is complete)

layers · array · required · topFixes · array · required

Actionable (fail/warning) checks ranked by ora: non-bonus first, then estimated uplift descending, capped at 6. Render verbatim - do not re-rank.

url · string · required

Canonical ora.ai deep link for the domain

generatedAt · string · required · source · string · required · ora.ai · contractVersion · string · required

The contract version this payload conforms to. SemVer: a major means a response-envelope break - a stable field removed, renamed, or changed in meaning, or the default response format flipping - and is safe to pin. Additive changes and check-catalog membership changes ship on a minor. See docs/api.md -> Contract and versioning. 1.32.0

durationMs · integer | null · required

Wall-clock duration of the scan that produced this stored result

mcpAuthRequired

boolean

Legacy marker retained for compatibility with stored results. New authentication-required scans return an MCP_AUTH_REQUIRED error without score or grade; public reads of a historical marked result return the same error. true

urlKind

string

How the scanned input was classified and stored. 'ephemeral' = disposable result (tunnel host, or ephemeral: true) that is excluded from rankings and deleted after a few days. Absent on older stored results. domain | mcp | mcp-app | ephemeral

category

string

Canonical market category ora classified the domain into (e.g. 'Infrastructure & DevOps'). Advisory; absent when the domain is unclassified.

agenticSummary

string

One-sentence natural-language verdict on the domain's agent-readiness, generated after analysis completes. Advisory; absent on partial results and on older stored results.

finalUrl

string

The URL the scan actually fetched after following redirects. Distinct from `url`, which is the canonical ora.ai deep link for the domain.

nextAction

object

Present only when the scan is stuck (partial for over 30 minutes; the worker likely failed) or on the score route's 404 miss - the HTTP request that recovers the score. A plain partial resolves on its own: poll the 202's Location URL instead of re-scanning.

competitors

object | null

Experimental (no stability guarantee): competitive context drawn from the leaderboard, present only when the request carries ?competitors=1. Null when the domain is unranked or the leaderboard read failed. Shape may change on any release.

siteType

object | null

Experimental (no stability guarantee): the scan scored against what the site is, present only when the request carries ?include=siteType. Null when the scan has no layers to score. Shape may change on any release.

### CheckCatalog

object · contractVersion · string · required

The contract version this catalog conforms to - identical to the OpenAPI info.version and the MCP server version. SemVer: a major means a response-envelope break (a stable field, or a layer id, removed or renamed or changed in meaning, or the default response format flipping) and is safe to pin; check-catalog membership changes ship on a minor. The full versioning policy is published in the API description at /api/openapi.json. 1.32.0

layers · array · required

The four scored layers in scoring order, with display name and current weight.

checks · array · required

All catalogued checks. Array order is not contractual: key by id.

### CatalogCheck

object · id · string · required

Stable check identifier, safe to persist, to gate CI on, and to pass in POST /api/scan/checks. An id never changes meaning while it exists. Catalog membership is not frozen: an id can be retired or renamed on a MINOR version, always with a contract changelog entry and a deprecation window. Check ids identify catalog entries rather than response-envelope fields, so a client parsing responses keeps working when one disappears; a client gating on an explicit id list reads the changelog.

name · string · required

Human-readable check title. Advisory display prose.

description · string · required

What the check verifies and why it matters to agents. Advisory display prose.

layer · string · required

The check's scored layer id, always one of the ids in layers[]. A check can move to a different layer on a minor version with a changelog entry.

maxScore · number · required

The check's maximum contribution to its layer. Do not sum maxScore into a score denominator: emerging checks sit outside scoring, a bonus counts only the points it earned (it can raise a score, never lower it), and N/A results drop out. Rebalances land on a minor version with a changelog entry.

bonus · boolean · required

Always present. A bonus check can only add score: a site that lacks the surface is never penalised for failing it.

applicability · string · required

The check's declared applicability rule. One of: all | domain-only | mcp | mcp-app | api. A value change lands on a minor version with a changelog entry.

protocol

string

Present only when applicability is 'api'. One of: rest | graphql | either - the API surface the check evaluates.

appliesTo · array · required

The scan kinds this check can run for - a subset of: domain | mcp | mcp-app. Eligibility, not a guarantee: MCP checks run once per MCP surface detected on the target and report N/A when none is present, and 'api' checks report N/A when the target has no REST or GraphQL surface.

tier · string · required

One of: required | recommended | emerging. Advisory: the required set may grow on a minor version, and every tier change carries a changelog entry. Gate CI on explicit check ids, not on tiers.

maturity · string · required

One of: verified | emerging. Emerging checks are shown on score pages but excluded from scoring, so do not treat them as score-affecting when selecting checks.

draft · boolean · required

Always present. True when the check's underlying spec is a draft or emerging standard.

beta · boolean · required

Always present. True marks a beta placeholder held at not-applicable - it runs but cannot affect any score; do not offer it as fixable.

specUrl

string

Canonical spec or standard URL. Omitted when the check has none.

recommendation

string

Generic, target-independent fix guidance. Omitted for the few checks that have none.

### CatalogLayer

object · id · string · required

Stable layer id: discovery, accessibility, usability, or payments. Removing or renaming a layer id is a major version change. Note one intentional divergence: the id 'accessibility' carries the display name 'Access'.

name · string · required

Display name for the layer. Advisory: it may change on a minor version.

weight · number · required

The layer's weight in the overall 0-100 score. Weights sum to 100 across the four layers. Advisory: a rebalance lands on a minor version with a changelog entry.

### RunChecksRequest

object · url · string · required

The website, MCP server, or API URL to run checks against. A bare domain like example.com is accepted.

checkIds · array · required

Array of check ids from GET /api/checks - one id minimum, up to the catalogued check count. Duplicate ids are deduplicated; ids the catalog does not list are rejected with error code UNKNOWN_CHECK_IDS.

mcpUrl

string

Optional URL of the target's MCP server, matching the same field on POST /api/scan. It pins the MCP endpoint; a failed handshake never substitutes a discovered server. When omitted, ora auto-discovers MCP endpoints. An empty string is treated as absent.

### RunChecksResponse

object · contractVersion · string · required

The contract version this response conforms to - identical to the OpenAPI info.version and the MCP server version. The full versioning policy is published in the API description at /api/openapi.json. 1.32.0

domain · string · required

The apex domain derived from the requested URL.

url · string · required

The normalized URL the run targeted.

urlKind · string · required

The execution kind detected for the target - domain, mcp, or mcp-app. Detected server-side; requested ids that cannot apply to this kind resolve as 'na' entries instead of executing. domain | mcp | mcp-app

storedScanUpdated · boolean · required

Whether these results were patched into the target's current stored scan. Patching is available to scan API key callers today - keyless runs are stateless and always report false. When true, GET /api/score/{domain} and the public score page reflect the re-verified checks, recomputed over the full stored check set. When false, no public surface changed; a full POST /api/scan is the way to establish a stored scan.

results · array · required

One entry per executed check slot, plus one 'na' entry for each requested id that cannot apply to the detected kind. Every requested id yields at least one entry, and MCP fan-out can yield several entries per id, keyed by (id, mcpUrl). -> RunChecksResultEntry

### RunChecksResultEntry

object · id · string · required

The check id, as listed in GET /api/checks.

name · string · required

Human-readable check title.

status · string · required

One of: pass | fail | warning | na | error. 'error' means ora could not complete the probe - retry it. A failed fix reads 'fail', never 'error'. 'pending' cannot appear: selective runs resolve synchronously. pass | fail | warning | na | error

score · number · required

Points the check earned on this run.

maxScore · number · required

The check's maximum points. Do not sum maxScore values into an aggregate - a selective response deliberately carries no overall score.

details · string · required

What was observed on the target.

recommendation

string

How to fix the finding. Omitted when no guidance applies.

naReason

string

Why the check did not apply. Present on 'na' results, including requested ids that cannot apply to the detected kind.

mcpKind

string

The classification of the MCP surface this entry scored against - one of: product | docs | other | app. Present on MCP fan-out entries. product | docs | other | app

mcpUrl

string

The URL of the MCP server this entry scored against. Present on MCP fan-out entries.

### ScanResult

object · domain · string

The scanned domain (pre-redirect). Compare with new URL(finalUrl).hostname to detect cross-domain redirects.

url · string · The normalized URL · finalUrl · string

The final URL after redirects. If the host differs from domain, the score reflects a redirected site.

score · integer · Overall score (0-100) · maxScore · integer · Maximum possible score · grade · string

Letter grade (A+ >= 95, A >= 86, B >= 70, C >= 48, D >= 28, F < 28) A+ | A | B | C | D | F

analysisStatus

string

Completeness of the score. 'partial' = analysis still in progress (deep checks, relevance assessment, or summary generation); 'complete' = all post-processing done, score is final; 'stuck' = scan got stuck in partial for >30 minutes (worker likely failed) - the score will not advance on its own and the response will also include a `next_action` envelope pointing at POST /api/scan. complete | partial | stuck

pendingChecks

array

IDs of checks not yet resolved. Empty when analysisStatus is 'complete'. Poll GET /api/score/{domain} until this is empty for a final score.

ctaMessage

string

Call-to-action message based on score

ctaTier

string

CTA tier top | high | mid | low

layers

array

Breakdown by scoring layer -> LayerResult

scannedAt

string (date-time)

When the scan was performed

durationMs · integer · Scan duration in milliseconds · agenticSummary · string

Optional. A one-sentence natural-language verdict generated after analysis completes (e.g. "Stripe offers excellent developer resource discoverability and SDK availability, but lacks a published OpenAPI specification for agent integration."). Absent on older cached results or when the summary generation step did not run.

urlKind

string

Optional. How the scan is stored. 'domain' for a regular website, 'mcp' for an MCP server endpoint (handshake succeeded but no Apps support detected; also returned for catalog pages where we resolved a validated embedded MCP server URL), 'mcp-app' for an MCP server that negotiates the MCP Apps extension `io.modelcontextprotocol/ui` (or exposes `ui://` resources or tool `_meta.ui.resourceUri`), 'ephemeral' for a disposable scan (requested with `ephemeral: true`, or a public tunnel hostname) which is excluded from the leaderboard, coverage counts, research statistics, and score history and is deleted after a few days. The first three are detected; 'ephemeral' describes storage, and an ephemeral scan still runs the full check set for the kind it was detected as. Absent on older cached results. domain | mcp | mcp-app | ephemeral

mcpAuthRequired

boolean

Legacy marker retained for compatibility. New authentication-required scans and reads of historical marked results return HTTP 422 MCP_AUTH_REQUIRED without score or grade.

servedFromCache

boolean

Present (and always true) only when POST /api/scan answered from the freshness window with a stored result instead of running a scan. Absent on a live scan and on GET /api/score/{domain}, which is always a cached read. true

resultAgeSeconds

integer

Age of the served stored result in seconds. Sent with servedFromCache, and mirrored in the Age response header.

### LayerResult

object · id · string · Layer identifier · name · string · Layer display name · description · string · Layer description · checks · array · -> CheckResult · score · integer · Layer score · maxScore · integer · Layer maximum possible score

### CheckResult

object · id · string · Check identifier · name · string · Check display name · description · string · What this check tests · status · string

Check result status. 'pending' = deep scan not yet resolved; 'na' = not applicable for this product. pass | fail | warning | error | pending | na

score · integer · Points earned · maxScore · integer

Maximum points for this check

details

string

Human-readable explanation of the result

recommendation

string

Optional. Concrete fix that would make this check pass. Absent on passing checks and on some N/A rows.

bonus

boolean

Optional. Upside-only check: earning it raises the score, missing it never lowers it. An unearned bonus is excluded from the denominator entirely, so it reports score 0 without costing points.

maturity

string

Optional. 'verified' = evidence that agents rely on this signal, counts toward the 0-100 score. 'emerging' = early or low-adoption signal, shown but excluded from the denominator. Absent on older cached results. verified | emerging

tier

string

Optional. How strongly ora expects the check: 'required' = the baseline every product is measured against, 'recommended' = scored but outside the baseline, 'emerging' = excluded from the score. Display metadata derived from maturity plus the baseline - it never changes the score. Rank fixes by estScoreGain, not by tier. required | recommended | emerging

naReason

string

Optional. Why the check does not apply to this product. Present on 'na' rows; the check is skipped, not deducted.

estScoreGain

number

Optional. Estimated points fully fixing this check would add to the overall 0-100 score, already normalized to the layer weight. Present on actionable (fail/warning) checks only; an estimate, not exact. This is the uplift signal - do not read maxScore minus score as score uplift.

### CompetitorSet

object · category · string

The market category the competitors are drawn from. Always a real market category: for unclassified domains (Community, or no leaderboard row) the endpoint returns `competitors: null` instead of a set.

leaders

array

Top 5 of the category by score, descending. -> Competitor

neighbors

array

Up to 5 rows centred on the queried domain: 2 above, self, 2 below, within the same category pool. Always contains the `isSelf` row. -> Competitor

### Competitor

object · rank · integer

1-based position on the category board the slices are drawn from.

domain · string · Competitor domain · name · string · Competitor display name · score · integer · Agent-readiness score (0-100) · grade · string

Letter grade A+ | A | B | C | D | F

isSelf

boolean

True for the row representing the queried domain. Subdomains share their company's leaderboard row, so querying a subdomain marks the company's row as self.

### NextAction

object · method · string · required · HTTP method POST · endpoint · string · required

API path to call (e.g. /api/scan)

body · object · required

Body to POST. For /api/scan this is { url }.

description · string · required

Human-readable explanation of the recovery step

### NotScannedResponse

object · error · string · required · Human-readable error message · code · string · required · Machine-readable error code DOMAIN_NOT_SCANNED · domain · string · required

Normalized domain that was looked up

next_action · object · nextAction · object

Present instead of `next_action` when the request passed `?format=audit`. Same recovery step, camelCase and versioned, matching the `nextAction` on AuditScanResult / AuditScoreResult.

### ArdErrorResponse

object · errorCode · string · required

Machine-readable ARD error code (spec Appendix B). INVALID_ARGUMENT | UNAUTHENTICATED | NOT_FOUND | RATE_LIMIT_EXCEEDED | INTERNAL_ERROR

message · string · required

Human-readable error explanation.

details

object

Optional structured validation detail (Zod flatten) on INVALID_ARGUMENT.

next

string

Optional recovery hint (e.g. /api/scan on NOT_FOUND).

### AgentFilesBundle

object · domain · string · required

The domain the files speak for (leading www. dropped).

productName · string · required

The product name used in the files; the domain itself when ora knows no name.

scannedAt · string | null (date-time) · required

When ora last scanned the domain; null when it never has, in which case the files carry only what the domain alone implies.

files · array · required · -> AgentFile · notes · array · required

Why an included file is absent (the site already publishes it, Ora never read the original, nothing to list), in plain sentences. Empty without ?include=.

### AgentFile

object · path · string · required

Where the file is served, as a path on its host, e.g. /.well-known/ard.json.

spec · object · required

The standard the file follows.

content · object · required

The JSON document to publish at path; an empty object for a text file (llms.txt, robots.txt), whose bytes are in body.

notes · array · required

What to review or add before publishing, in plain sentences.

mediaType · string · required

Content-Type to serve the file with, e.g. application/json, application/linkset+json, text/markdown, text/plain.

body · string · required

The exact bytes to publish (JSON files pretty-printed with a trailing newline).

url · string · required

The full address the file is served at: https://<domain><path>, except an MCP server card, which lives on its server's host (possibly a subdomain).

### McpAuthRequiredResponse

object · error · string · required

Why the MCP server could not be inspected.

code · string · required · mcpAuthRequired · boolean · required · mcpUrl · string · required

The MCP endpoint that required authentication.

urlKind · string · required · mcp | mcp-app

### ErrorResponse

object · error · string · required

Error type or human-readable message (e.g. 'Not found', 'Rate limited')

message

string

Optional longer explanation with recovery steps

code

string

Optional machine-readable error code (e.g. EPHEMERAL_CLOBBER, ENDPOINT_NOT_FOUND, RATE_LIMITED, INVALID_DOMAIN)

retry_after_ms

integer

Present on a 429 from the durable daily scan budget: milliseconds until a slot frees, the same interval the Retry-After header carries in seconds. Every rate-limited ora endpoint sends the same deny body, so one client handler covers them all.

details

object

Optional structured validation detail (Zod flatten) on a schema rejection.

### DiscoverResult

object · domain · string · Product domain · name · string · Product name · category · string · Product category · score · integer · Agent-readiness score (0-100) · grade · string

A | B | C | D | F

tags · array · Product tags · matchScore · number · Relevance to your query

### AgentFeedback

object · id · integer · domain · string · agent_id · string · Unique agent identifier · user_intent · string

Original user request that led to this interaction

task_description

string

What the agent was trying to do

outcome

string

success | partial_failure | failure

content · string · Detailed feedback · friction_points · array · recommendation · string

recommend | neutral | not_recommend

layer_scores

object

Per-stage scores (1-5). Current funnel stages: discovery, identity, access, payments, experience. Legacy keys (integration, in-agent-experience) are still accepted for backward compatibility.

created_at

string (date-time)

### FeedbackStats

object · total · integer · Total feedback count · success_rate · number

Proportion of successful outcomes (0-1)

recommend_rate · number · Proportion recommending (0-1) · outcomes · object · recommendations · object

# Footer

The standard for agent experience.

© 2026 [era labs](https://eralabs.ai/)

Product

- Scan a site

- [Journey](https://journey.ora.ai/)

- [WebMCP audit](https://webmcp.ora.ai/)

- [Directory](https://directory.ora.ai/)

Resources

- Methodology

- Research

- Blog

- API Docs

Company

- About

- Contact

- Privacy

- [@oradotai](https://x.com/oradotai)
