API v1
Base URL https://motari.io/api/v1. Responses are JSON; an error is { "error": { "code": "...", "message": "..." } } with a matching HTTP status. Robots are addressed by the slug in their page URL: /r/so-101 is so-101.
| Endpoint | Returns | Auth |
|---|---|---|
GET /api/v1/robots | List and filter robots, with the atlas filters; 12 per page | none |
GET /api/v1/robots/{slug} | One robot: catalog record, bill of materials, rubric, files, sources, build steps | none |
GET /api/v1/robots/{slug}/bom | Bill of materials with source evidence and costs | none |
GET /api/v1/robots/{slug}/score | Reproducibility rubric, score and pinned commit | none |
GET /api/v1/robots/{slug}/export/{format} | Kinematic model as urdf, kinematics, mjcf or sdf, with a loss report | none, rate limited |
GET /api/v1/badge/{slug} | Reproducibility badge (SVG) for a README | none |
POST /api/v1/push | Analyze a repository and save it as a draft you maintain | GitHub token |
POST /api/v1/claim | Claim a robot whose repository you can administer or push to | GitHub token |
POST /api/v1/robots/{slug}/attest | Report that you built a robot, with an evidence link (counts once reviewed) | GitHub token |
Filtering the list
/api/v1/robots takes the same parameters as the atlas URL. Multi-value parameters are comma-separated or repeated.
q: text search over name and summaryembodiment:arm,bimanual,humanoid,quadruped,mobile,gripper,dronelicenseClass:open(commercial use OK),non-commercial,unknownhas:sim(URDF or MJCF published),cost(a sourced cost),bom(a BOM with prices on at least half its rows)lifecycle,morphology,score(strong,partial,early),price(lt100,100to500,500to2k,gt2k, US dollars)q: search text, matched against names in any spacing (so101finds SO-101), robot types, simulation formats and software (urdf,ros2,mujoco), parts and build textsort:relevance(default withq),score(default otherwise; ties go to the BOM, then CAD, then build criterion),price,name;page: 1 and upretired: the API lists defunct and paper-only robots unlessretired=hide
# Arms that publish a URDF or MJCF model, cheapest first
curl "https://motari.io/api/v1/robots?embodiment=arm&has=sim&sort=price"
# One robot's bill of materials, with source evidence and costs
curl https://motari.io/api/v1/robots/so-101/bom
# Its kinematic model as URDF (the file is in "output")
curl https://motari.io/api/v1/robots/so-101/export/urdfCosts keep the currency the source states and carry their basis (source total, estimate, vendor kit) and source URL; nothing is converted. An export answers with a status (ok, lossy, refused or unsupported) and a report of what the format could not carry. It allows 60 requests per IP per minute, and at most 10 of them may need a fresh conversion.
README badge
Every robot has a reproducibility badge at https://motari.io/api/v1/badge/{slug}. Wrap it in a link to the robot's page so readers can see how the score was reached. An unknown slug answers 404, so a broken badge is visible rather than misleading.
[](https://motari.io/r/so-101)<a href="https://motari.io/r/so-101"><img src="https://motari.io/api/v1/badge/so-101" alt="Motari reproducibility score"></a>Command-line tool
motari runs the ingest engine on your machine: analyze a repository, show its score and parsed bill of materials, convert its kinematic model, or verify it in CI with a minimum score.
@motari/cli is not on npm yet. From a checkout of the repository (Node 20 or later):
npm ci
npm run build --workspace @motari/cli
alias motari="node $PWD/packages/cli/dist/cli.js"
motari robot ingest https://github.com/TheRobotStudio/SO-ARM100
motari robot list
motari score show therobotstudio-so-arm100
motari verify https://github.com/TheRobotStudio/SO-ARM100 --fail-under 60robot ingest caches its result under ./.motari, keyed by a local slug built from the repository (therobotstudio-so-arm100). motari --help lists every command.
TypeScript SDK
@motari/sdk is a typed client for the API above, with the catalog types. It is not on npm yet and ships TypeScript source, so from a checkout use it inside the repository's workspace (after npm ci) with a TypeScript runtime such as tsx.
import { MotariClient } from "@motari/sdk";
const motari = new MotariClient({ baseUrl: "https://motari.io" });
const { robots, total } = await motari.listRobots({ embodiment: ["arm"], has: ["sim"] });
const bom = await motari.getBom("so-101");
console.log(total, robots[0]?.name, bom.costs);Python client
motari is a thin client on the Python standard library (3.9 or later). It is not on PyPI yet; from a checkout, install it from its folder:
pip install ./clients/python
from motari import MotariClient
client = MotariClient() # https://motari.io
page = client.list_robots(embodiment=["arm"], has=["sim"])
for robot in page["robots"]:
print(robot["slug"], robot["score"])
print(client.badge_url("so-101"))GitHub Action
The score action scores a repository on its head commit in CI, writes a summary, uploads an attestation and a badge as artifacts, and can fail the job below a threshold (fail-under). GitHub runs a reusable workflow only from a repository the caller can read, so this snippet works once the Motari repository is public; until then it documents the interface:
# .github/workflows/reproducibility.yml
name: reproducibility
on:
pull_request:
push:
branches: [main]
jobs:
motari:
uses: motarihq/motari/.github/workflows/motari-reproducibility.yml@main
with:
repo-url: "" # empty: score this repository
fail-under: 60 # 0 only reportsPin @main to a tag or commit in real use. The same check runs locally with motari verify <repo-url> --fail-under 60.
Last updated 2026-10-01.