Two changes to how you can charge for work on Ouro, both live now.
Until now, a monetized asset had one currency. You picked USD or BTC, and anyone holding the other one couldn't buy.
Now you can accept both on the same asset, each at its own price. This works for posts, files, datasets, and API routes.
You set both prices. A post can cost $0.50 or 500 sats. Ouro doesn't convert one into the other, so the sats price is whatever you decide.
Buyers choose. When an asset has both prices, a toggle lets the buyer pick which wallet to pay from. A buyer who doesn't pick pays in your primary currency.
You're paid in what they paid. Dollars land in your USD balance, sats in your Bitcoin wallet.
The practical upshot: people can pay by card and agents can pay in sats, on the same route, without you publishing it twice.
From code, give a price per currency:
ouro.posts.update(post_id, visibility="monetized", monetization="pay-to-unlock", price_usd=0.50, price_sats=500) ouro.routes.update(route_id, unit_cost_usd=0.10, unit_cost_sats=100) # Buyers pick with `currency` ouro.routes.execute(route_id, body={...}, currency="btc")
A fixed price per run works badly for jobs whose length depends on the input. Price a DFT relaxation for the big cells and small ones overpay. Price it for the small cells and you lose money on the big ones.
Routes can now charge per second of runtime, up to a maximum you set per run:
Before the run, Ouro holds the rate times your maximum from the caller's balance. If they can't afford the full maximum, it holds what they can afford, with a 60-second floor.
Your service gets that budget in the ouro-max-billable-seconds header, so it can stop in time or reject a job that won't fit.
When the run finishes, the caller is charged for the seconds used and the rest of the hold comes back.
Failed and timed-out runs are free. You run your own routes for free, and so does anyone with edit access to them.
Callers see the rate and the most a run can cost before they start, and a receipt with the billed seconds after. Here's one priced this way:
Variable-cell DFT relaxation with ABACUS (ions + cell). Evaluates energy, forces, and stress after the first SCF and only takes ionic steps when thresholds are exceeded. Returns a relaxed CIF plus convergence diagnostics. Spin defaults to auto (collinear for magnetic elements) so the geometry matches the magnetic ground state used by MAE and magnetization density. Pass the relaxed CIF into downstream property routes.
You can set all of this on the route's page, or declare it next to the endpoint so the price lives with the code:
from ouro.utils import ouro_pricing `{@app}`.post("/relax") `{@ouro_pricing}`(per_second={"usd": 0.0003, "btc": 3}, max_seconds=3600) async def relax(...): ...
How to monetize APIs: pricing models and how per-second billing works
Building long-running APIs: the budget header, reporting your own billable time, pricing in code
Economics: currencies, fees, and payouts
Both features need ouro-py 2.1.2 or later. If something about either one is confusing or missing, reply here.
Two pricing updates: one asset can now accept both USD and sats at independent prices, and API routes can bill per second of runtime up to a cap.