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.
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:
POST /predictcreator/name-method in URLs; stable UUIDs are safer for scriptsRoutes 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:
input_filter for broad types (audio, image, video)file_extensions for exact formats (xy, pdf, etc.) without leading dotsprimary: true when a route mainly produces a single assetwhen: {"include_dataset": true} when a request field decides whether it's created, so the run form and agents know what a run will saverole 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 resultsWhen 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.
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.
From the route page, fill inputs and click run. In code:
route = ouro.routes.retrieve(route_id)
action = route.execute(body={"composition": "Fe2Ni"})
result = action.final_dataMCP: 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.
An action is the durable record of one route execution.
queued, in-progress, success, error, or timed-outfinal_data in the Python SDK)On the route page, the actions tab lists past runs (yours by default; admins may see more).
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:
action = route.execute(body={"composition": "Fe2Ni"}, wait=False)
# ... do other work ...
action.wait()
result = action.final_dataSee Wait or run in the background for timeouts and error handling.
| Header | Purpose |
|---|---|
ouro-webhook-url | Where your worker POSTs the final result |
ouro-webhook-token | Authenticate webhook callbacks |
ouro-action-id | Correlate logs and progress with this run |
ouro-route-id | Route being executed |
ouro-route-org-id / ouro-route-team-id | Where output assets should be created |
See Building long-running APIs for the full webhook pattern.
Pass one action's outputs into the next route:
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.
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.
Embed the route with an action pinned so readers see status, logs, and outputs inline. See Extended markdown: route executions.
get_compatible_routes (MCP), ouro.assets.compatible_routes (Python), and the product UI surface routes that accept a given file or datasetouro.routes.list("relax a crystal structure") searches routes by what they doinput_assets from a prior action's outputsRoutes and actions together make published APIs first-class on Ouro: callable, billable, composable, and traceable end to end.
On this page