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.