---
url: https://ora.ai/docs/partners
title: "Partner integration - Docs"
description: "Build ora scores into your product with a scan API key: stream a scan, read the stored score, render the response as-is."
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
---
# Partner integration

Building ora scores into your own product takes two endpoints: one runs a scan, one reads the latest stored result. Call both from your server with a scan API key, and render the response as ora returns it.

Get a key

Keys are issued manually, one per partner.

Contact us

for one. Send it as

Authorization: Bearer <key>

from your server only. Never ship it to browser code.

1. Run a scan. Stream it, and forward the events to your UI. Add force=1 to rescan a result younger than the 6-hour freshness window.

Run a scan

curl -N "https://ora.ai/api/scan/stream?domain=example.com&format=audit&include=siteType" \ -H "Authorization: Bearer $ORA_API_KEY"

scan_complete carries the audit in result and the site-type reading beside it in siteType . A live scan may then send relevance_assessed (checks marked not applicable, plus the corrected score and grade) and summary_ready ; both are optional. Read events until the stream closes, then go to step 2. A closed stream is not always a final score: when deep checks are still running, ora finishes the analysis in the background. If you cannot hold a stream open, POST /api/scan returns the same audit in one response, and a 202 points you at the score endpoint to poll.

2. Read the stored score. This never starts a scan. While analysisStatus is partial , the score can still change: poll until it reads complete . Add &siteType=store (or content , business , app ) to read the scan as that type. The siteType reading is experimental: its shape can change without a contract version bump.

Read the stored score

curl "https://ora.ai/api/score/example.com?format=audit&include=siteType" \ -H "Authorization: Bearer $ORA_API_KEY"

It reads by hostname, so a path such as example.com/mcp returns the scan for example.com . A 404 means the site has not been scanned yet: run step 1.

Render the response as-is · Show · score · , · grade · , every check in · layers[].checks[] · , and · topFixes

in the order ora sends them. Do not recompute scores, drop checks, or rewrite statuses. Accept

contractVersion

major 1 and ignore fields you do not recognize: minor releases add them. The

versioning policy

lists which fields are stable.

## Agent journeys

A journey sends a real agent at the site and records every step it takes. Your key unlocks one call that returns a domain's journey, starting one only when none exists.

1. Get the domain's journey. Send no body: ora picks the task and the agent. A 201 means a new run started. A 200 means nothing new ran: you get the stored run, with its result and run_age_seconds once status is succeeded . A succeeded journey is kept indefinitely and serving it costs nothing, so call this on every page view. A failed run carries no result and is not kept: the next call starts a new run, so back off after a failure instead of retrying at once.

Get the domain's journey

curl -X POST "https://ora.ai/api/journey/domains/example.com" \ -H "Authorization: Bearer $ORA_API_KEY"

The response is a compact view with what drawing the journey needs: verdict , the steps in result.trajectory.steps , and result.insight.summary . Add ? view=full for the full payload, including key_observations .

2. Stream a running journey to the end. While status is running , open stream_url (a path on ora.ai) and read it until result or error . Hold it open: the stream is what saves the finished run, so calling step 1 again only reads what a stream has saved. If the connection drops, open it again; it picks up the same run without restarting the agent. A run can take up to 10 minutes. Open it from your server with your key: it has no CORS headers, and the key lifts the per-IP limit your viewers would otherwise share.

The stream sends run_id , then trajectory snapshots (each one carries every step so far), then result . A live run also sends processing while insights are written; reopening a finished run does not. error can arrive at any point and ends the stream. A running 200 from step 1 carries retry_after_ms ; more than three calls for one domain within two seconds return 429 POLL_TOO_FAST . Every 429 carries a Retry-After header.

Your own tasks. To run a task you write, send it as free text (4 to 300 characters) with an agent from GET /api/journey/agents . This starts a new run on every call, up to 1,000 per key per 24 hours. Stream the stream_url it returns to the end, as in step 2. Afterwards, GET /api/journey/runs/ {id} reads the saved run.

Run your own task

curl -X POST "https://ora.ai/api/journey/runs" \ -H "Authorization: Bearer $ORA_API_KEY" \ -H "Content-Type: application/json" \ -d '{"intent":{"custom":"Find the pricing for the team plan","domain":"example.com"},"harness":"claude-agent-sdk","model":"claude-haiku-5-5"}'

Render the journey as-is

Show the steps in order with the

verdict · ora assigns ( · satisfied · , · partial · , · unsatisfied · , or · not_gradable

). A journey records what an agent did. It has no score and does not map to the scan's layers. The request and response schemas are in the

OpenAPI spec · under · /api/journey

.

# 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)
