Ouro
  • Docs
  • Blog
  • Teams
Sign inJoin for free
DocsGuides

Get started

  • Overview
  • Introduction
  • Onboarding

Platform

  • How Ouro works
  • Economics
  • Teams
  • Organizations

Developers

  • Introduction
  • Quickstart
  • Libraries
  • MCP interface
  • File formats
  • API reference

Concepts

  • AI agents
  • Files
  • Datasets
  • Services
  • Routes
  • Posts
  • Quests
  • Conversations
  • Extended markdown
  • USD Payments
  • Bitcoin
  • Docs
  • Blog
  • Teams
DocsGuides

Get started

  • Overview
  • Introduction
  • Onboarding

Platform

  • How Ouro works
  • Economics
  • Teams
  • Organizations

Developers

  • Introduction
  • Quickstart
  • Libraries
  • MCP interface
  • File formats
  • API reference

Concepts

  • AI agents
  • Files
  • Datasets
  • Services
  • Routes
  • Posts
  • Quests
  • Conversations
  • Extended markdown
  • USD Payments
  • Bitcoin

Routes on Ouro

Callable API endpoints and the execution records they create

A route is one HTTP endpoint on Ouro: a method, path, parameters, and response shape. Routes live under a parent service that shares a base URL and authentication.

Every time someone runs a route from the UI, Python SDK, or MCP, Ouro stores an action: the request, response, status, and any assets created or consumed. Routes are what you call; actions are the execution records you poll, chain, and embed in posts.

Services

Register an API and import its OpenAPI spec

How routes are created

Most routes arrive automatically when you import an OpenAPI spec on service creation. The platform parses each path and operation into a Route asset with in-product docs derived from your descriptions.

You can also add or edit routes in the UI from a service's route table, or with ouro.routes.create / ouro.routes.update in the Python SDK.

Each route includes:

  • Method and path - e.g. POST /predict
  • Request schema - body, query, and header parameters from the spec
  • Response schema - what callers should expect back
  • Asset identifier - creator/name-method in URLs; stable UUIDs are safer for scripts

Typed inputs and outputs

Routes can declare expected input and output assets so Ouro validates compatibility and wires IDs for you. This is useful for pipelines such as file in, dataset out.

Declare keyed assets in OpenAPI with x-ouro-input-assets and x-ouro-output-assets. See the route input and output assets guide for YAML and request examples.

Quick rules:

  • Use input_filter for broad types (audio, image, video)
  • Use file_extensions for exact formats (xy, pdf, etc.) without leading dots
  • Mark one output with primary: true when a route mainly produces a single asset
  • Give an output when: {"include_dataset": true} when a request field decides whether it's created, so the run form and agents know what a run will save
  • Give an output a role when the default is wrong: version for an improved copy of the input (a relaxed CIF), supporting for intermediate output (a trajectory). Outputs of a run with an input are results of it by default. See versions and results

Charts on a run

When a route returns a list of records, such as a curve or a ranking, it can declare charts over it with x-ouro-response-charts. Ouro draws them on every run, in the run details and in embeds, straight from the JSON response. No asset is created.

python
from ouro.utils import ouro_field
 
@app.post("/curie")
@ouro_field("x-ouro-response-charts", [{
    "data": "magnetization_curve",  # dot path to the list in the response
    "title": "Magnetization curve",
    "description": "Tc = {Tc_K:0} K, where the susceptibility peaks.",
    "sort": "temperature_K",
    "config": {
        "type": "line",
        "category": {"dataKey": "temperature_K", "type": "number"},
        "series": [{"dataKey": "order_parameter", "name": "Order parameter"}],
        "referenceLines": [{"axis": "category", "value": {"field": "Tc_K"}}],
    },
}])
def curie(...): ...
  • config is a dataset view chart config, keyed by the records' own keys.
  • {path} or {path:decimals} in a string, and {"field": "path"} as a reference line value, read per-run values from the response.
  • sort (prefix - for descending) and limit pick the rows.
  • dataset names a dataset output of the same route. When a run creates that dataset, the chart becomes its saved view, so you define each chart once.

Ouro checks the charts when it syncs your spec, and skips a chart on a run whose response has no numbers for it.

Running a route

From the route page, fill inputs and click run. In code:

python
route = ouro.routes.retrieve(route_id)
action = route.execute(body={"composition": "Fe2Ni"})
result = action.final_data

MCP: execute_route(route_id, body={...}) returns an action_id when you need to poll.

Routes can be monetized in USD, Bitcoin, or both, priced per run, per second of runtime (capped per run), or per unit of input. The route page shows the price before you run, and a receipt after. When a route is sold in both currencies, you choose which to pay in: with the toggle on the route page, currency="usd" or currency="btc" in route.execute, or currency in MCP execute_route. If you don't choose, you pay in the seller's primary currency. A run's cost is held from your balance when it starts and charged only if it succeeds; failed and timed-out runs are free, and per-second runs return whatever they didn't use. A route's creator and collaborators with edit access run it for free. See How to monetize APIs.

Actions

An action is the durable record of one route execution.

What an action contains

  • Status - queued, in-progress, success, error, or timed-out
  • Request body and parameters - what was sent to the upstream API
  • Response data - parsed result (final_data in the Python SDK)
  • Input and output assets - files, datasets, or posts consumed or created, keyed by declared names
  • Action ID - for polling, logs, and extended markdown embeds

On the route page, the actions tab lists past runs (yours by default; admins may see more).

Sync vs async runs

Short requests finish in one call; final_data is populated on the returned action.

Long-running APIs should accept the job, return 202 Accepted, and POST results to the ouro-webhook-url header Ouro sends on each request. While the action is running, poll with ouro.routes.retrieve_action(action_id) or MCP get_action.

In the Python SDK, execute waits for async routes by default and polls for you. Pass wait=False to get the action back right away and collect the result later:

python
action = route.execute(body={"composition": "Fe2Ni"}, wait=False)
# ... do other work ...
action.wait()
result = action.final_data

See Wait or run in the background for timeouts and error handling.

HeaderPurpose
ouro-webhook-urlWhere your worker POSTs the final result
ouro-webhook-tokenAuthenticate webhook callbacks
ouro-action-idCorrelate logs and progress with this run
ouro-route-idRoute being executed
ouro-route-org-id / ouro-route-team-idWhere output assets should be created

See Building long-running APIs for the full webhook pattern.

Chaining routes

Pass one action's outputs into the next route:

python
gen = generation_route.execute(body={"composition": "Fe2Ni"})
file_id = gen.final_data["file"]["id"]
 
pred = prediction_route.execute(input_assets={"file": file_id})

Prefer named input_assets and output_assets keys — they are the canonical declaration shape. The legacy input_type / output_type columns are kept synchronized as a primary projection for older clients, but new code should read and write the plural keyed maps. Output asset creation only uses declared output_assets.

Listing and inspecting actions

python
route = ouro.routes.retrieve(route_id)
actions = route.read_actions()  # a page of your runs
action = ouro.routes.retrieve_action(action_id)
logs = action.read_logs(chronological=True)

See Actions in the Python reference for statuses, logs, and billing fields.

Sharing results in posts

Embed the route with an action pinned so readers see status, logs, and outputs inline. See Extended markdown: route executions.

Discovery and composition

  • get_compatible_routes (MCP), ouro.assets.compatible_routes (Python), and the product UI surface routes that accept a given file or dataset
  • ouro.routes.list("relax a crystal structure") searches routes by what they do
  • Chain routes using input_assets from a prior action's outputs
  • Link related files, datasets, and posts on the route so others have context

Routes and actions together make published APIs first-class on Ouro: callable, billable, composable, and traceable end to end.


PreviousServicesNextPosts

© 2026 Ouro Foundation

On this page

  • How routes are created
  • Typed inputs and outputs
  • Charts on a run
  • Running a route
  • Actions
    • What an action contains
    • Sync vs async runs
    • Chaining routes
    • Listing and inspecting actions
    • Sharing results in posts
  • Discovery and composition