ouro-py
The official Python SDK for Ouro.
Use it to work with datasets and files, publish results, collaborate with teams, and run APIs shared on Ouro.
Install
pip install ouro-py
ouro-py requires Python 3.10 or later.
Quickstart
Create a Personal Access Token in your Ouro settings, then export it:
export OURO_API_KEY="your-api-key"
Create a client and start using the API:
from ouro import Ouro
ouro = Ouro()
dataset = ouro.datasets.create(
name="experiment-results",
visibility="private",
data=[
{"sample": "A", "score": 0.82},
{"sample": "B", "score": 0.91},
],
)
results = ouro.datasets.query(dataset.id)
print(results)
The client reads OURO_API_KEY from your environment or a .env file. You can also pass it
directly with Ouro(api_key="...").
Common workflows
Find assets
Datasets, posts, files, services, routes, and quests are all assets. Search across them with
ouro.assets:
results = ouro.assets.search(
"battery materials",
asset_type="dataset",
scope="global",
limit=10,
)
asset = ouro.assets.retrieve(results[0]["id"])
Search scope can be personal, org, global, or all.
Query a dataset
Dataset queries return pandas DataFrames by default:
df = ouro.datasets.query(dataset_id)
summary = ouro.datasets.query(
dataset_id,
"""
select category, avg(score) as mean_score
from {{table}}
group by category
""",
)
SQL queries are read-only. Use {{table}} as the dataset table placeholder.
Save a dataset view
A view is a saved chart. Pass a prompt and the API generates the SQL and chart config — you rarely write those by hand:
view = ouro.datasets.create_view(
dataset.id,
name="Score by sample",
prompt="Bar chart of mean `score` by `sample`, highest first.",
)
You can still pass sql_query and config if you already have them. List,
update, and delete with list_views, update_view, and delete_view. Embed
the chart in a post with
display_config={"visualizationId": view["id"]} on new_inline_asset.
Upload a file
file = ouro.files.create(
name="Crystal structure",
file_path="./structure.cif",
visibility="private",
)
Download any supported asset through the shared asset interface:
download = ouro.assets.download(file.id, output_path="./downloads")
print(download["path"])
Publish a post
Pass markdown directly or build richer content with the editor:
editor = ouro.posts.Editor()
editor.new_header(level=1, text="Experiment summary")
editor.new_paragraph(text="The best sample reached a score of 0.91.")
editor.new_inline_asset(dataset.id, asset_type="dataset", view_mode="preview")
post = ouro.posts.create(
name="Experiment summary",
content=editor,
visibility="private",
)
You can also use content_markdown="..." or content_path="./report.md".
Run an API
Ouro services expose individual endpoints as routes:
action = ouro.routes.execute(
"organization/route-name", # a route slug or UUID
body={"text": "hello"},
)
print(action.status)
print(action.final_data)
Routes can take Ouro assets directly:
action = ouro.routes.execute(
route_id,
input_assets={"structure": file.id},
)
Synchronous and asynchronous routes use the same interface. Pass wait=False to return
immediately, then use ouro.routes.poll_action(action.id) when you are ready for the result.
API overview
Resources are organized under one client:
| Namespace | Use it for |
|---|---|
ouro.assets |
Search, retrieve, share, download, and inspect lineage |
ouro.datasets |
Create, query, update, and visualize tabular data |
ouro.files |
Upload, retrieve, update, and search files |
ouro.posts |
Publish markdown and embedded assets |
ouro.routes |
Execute APIs and inspect actions |
ouro.services |
Publish an API from an OpenAPI specification |
ouro.quests |
Create work, submit entries, and review results |
ouro.organizations / ouro.teams |
Manage workspaces, channels, and membership |
ouro.comments / ouro.conversations |
Discuss assets and send messages |
ouro.users / ouro.notifications |
Work with profiles and notifications |
ouro.money |
Check balances, transactions, and paid access |
See the REST API reference for the underlying API.
Organizations, teams, and visibility
Every asset belongs to an organization and a team. When creating one, pass org_id and team_id
to choose where it appears:
dataset = ouro.datasets.create(
name="shared-results",
data=rows,
visibility="public",
org_id=org_id,
team_id=team_id,
)
If you omit them, Ouro uses your global organization's catch-all team.
Visibility can be public, private, or monetized. Private assets remain private until you
share them explicitly:
ouro.assets.share(asset_id, user_id, role="read")
Licensing and attribution
Set an asset's reuse terms with license_id, and record where the work came from with
the top-level attribution field. These fields are consistent across asset types and separate
from type-specific metadata:
attribution = {
"originality": "derivative",
"github_url": "https://github.com/example/project",
"doi_url": "https://doi.org/10.1234/example",
"relation_type": "IsDerivedFrom",
}
dataset = ouro.datasets.create(
name="published-results",
visibility="public",
data=rows,
license_id="CC-BY-4.0",
attribution=attribution,
)
originality can be original, derivative, or third-party. Attribution can also include
paper_url and external_url. Use relation_type to describe how the Ouro asset relates to the
linked work: IsSupplementTo, IsDerivedFrom, References, IsVariantFormOf, or
IsIdenticalTo.
Pass the same top-level fields when creating another asset type:
service = ouro.services.create(
name="published-model-api",
base_url="https://api.example.com",
license_id="Apache-2.0",
attribution={
"originality": "third-party",
"github_url": "https://github.com/example/model",
"paper_url": "https://arxiv.org/abs/0000.00000",
},
)
Use the license that applies to the asset type and only publish third-party or derivative work when its terms permit redistribution.
Configuration
| Variable | Default | Purpose |
|---|---|---|
OURO_API_KEY |
required | Personal Access Token |
OURO_BACKEND_URL |
https://api.ouro.foundation |
Ouro API base URL |
For local development:
export OURO_BACKEND_URL="http://localhost:8003"
You can also pass api_key and base_url directly to Ouro(...).
Error handling
All SDK exceptions inherit from OuroError:
from ouro import NotFoundError, OuroError
try:
asset = ouro.assets.retrieve(asset_id)
except NotFoundError:
print("Asset not found")
except OuroError as exc:
print(f"Ouro request failed: {exc}")
Development
git clone git@github.com:ourofoundation/ouro-py.git
cd ouro-py
pip install -e .
pytest
Questions and ideas are welcome in GitHub Discussions.
License
MIT
Release files for ouro-py 0.11.17
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ouro_py-0.11.17.tar.gz | 72.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ouro_py-0.11.17-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 165.6 kB
Release files / ouro_py-0.11.17.tar.gz
| Download URL | ouro_py-0.11.17.tar.gz |
|---|---|
| Size | 72.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e2a192ad52c7e97e82de046f4ece93cb771a8cb1179c829e323b62eb5dad3a89
|
|
BLAKE2b-256 checksum How to use checksums |
d1e884885ad8bdf37daab9412b30a2f3fd42ca0d3e999c196d067b57ade9a3f4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / ouro_py-0.11.17-py3-none-any.whl
| Download URL | ouro_py-0.11.17-py3-none-any.whl |
|---|---|
| Size | 93.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
85bd85291b5a76e5a507c6f54b113cd3c563893241a8e9fdf6064c97cd36d7f5
|
|
BLAKE2b-256 checksum How to use checksums |
c5258dfc4f6e0b0cc5151c3e5ab32d3aa27400b9dfbdd9f3c94a89a1d9c61be0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|