Develop
API reference
Every endpoint, every parameter, and every response shape — typed and versioned.
Base URL
https://api.nodedata.dev/v1All endpoints accept JSON bodies and return JSON responses. Errors follow the same shape across the API.
Versioning
Breaking changes ship under a new path prefix (/v1 → /v2). Additive changes (new fields, new optional parameters) ship in place without bumping the version. Removed or renamed fields are announced in the changelog at least 90 days before removal.
Error format
{
"error": {
"code": "validation_failed",
"message": "license must be one of MIT, Apache-2.0, CC-BY-4.0",
"field": "license",
"request_id": "req_01HZ..."
}
}Always log request_id. Support requests resolve much faster when the request ID is included.
Pagination
List endpoints return a cursor in next_cursor when more results exist. Pass it back as ?cursor= on the next call.
{
"items": [/* ... */],
"next_cursor": "eyJsYXN0X2lkIjoibWRsXzAxSF...",
"has_more": true
}Rate limits
| Surface | Limit |
|---|---|
| Read endpoints | 1,000 req / minute / key |
| Write endpoints | 120 req / minute / key |
| Upload endpoints | 30 req / minute / key (uploads themselves are unmetered) |
| Inference (hosted) | Per listing — see the listing's gateway docs |
Every response carries X-RateLimit-Remaining and X-RateLimit-Reset headers. When throttled the API responds with 429 and a Retry-After header in seconds.
Account
Get the authenticated account
GET /v1/me
Authorization: Bearer <key>
Response — 200
{
"id": "usr_01HZ...",
"slug": "acme",
"name": "ACME Robotics",
"email": "team@acme.dev",
"created_at": "2026-03-19T18:04:11Z",
"key": { "mode": "test", "scopes": ["models:read"] }
}Smallest possible call to verify a key. Returns the account that owns the key plus the key's mode and scopes.
Models
List models
GET /v1/models
Authorization: Bearer <key>
Query parameters
q string Full-text search query
task enum manipulation | navigation | perception | language | vla
framework enum pytorch | tensorflow | jax | onnx | gguf
license enum MIT | Apache-2.0 | CC-BY-4.0 | Commercial
cursor string Pagination cursor returned in the previous response
limit int 1–100 (default 20)Model object
{
"id": "mdl_01HZX9VABCDEF",
"slug": "acme/grasp-policy-v2",
"name": "Grasp Policy v2",
"owner": { "id": "usr_01HZ...", "slug": "acme" },
"task": "manipulation",
"framework": "pytorch",
"license": "MIT",
"price": { "currency": "usd", "amount": 4900, "model": "one_time" },
"latest_revision": "1.4.0",
"revisions": ["1.0.0", "1.1.0", "1.2.0", "1.3.0", "1.4.0"],
"downloads": 12_487,
"stars": 421,
"created_at": "2026-03-19T18:04:11Z",
"updated_at": "2026-05-22T09:11:47Z"
}Retrieve a model
GET /v1/models/{id_or_slug}
GET /v1/models/{id_or_slug}/revisions/{revision}Download a model
GET /v1/models/{id}/download
Authorization: Bearer <key>
Response — 302
Location: https://cdn.nodedata.dev/.../weights.safetensors?signature=...Region-aware
Datasets
The dataset endpoints mirror models. See:
GET /v1/datasetsPOST /v1/datasetsPOST /v1/datasets/{id}/shards— resumable uploadGET /v1/datasets/{id}/shards/{name}POST /v1/datasets/{id}/publish
Listings
POST /v1/listings— create a storefront for an assetPATCH /v1/listings/{id}— update pricing, title, galleryPOST /v1/listings/{id}/publishPOST /v1/listings/{id}/unpublish
Purchases
POST /v1/purchases
Authorization: Bearer <key>
Content-Type: application/json
{
"listing_id": "lst_01HZ...",
"payment_method": "pm_01HZ..." // or "balance"
}
Response — 201 Created
{
"id": "pur_01HZ...",
"listing_id": "lst_01HZ...",
"status": "succeeded",
"amount": { "currency": "usd", "amount": 4900 },
"platform_fee": { "currency": "usd", "amount": 1225 },
"seller_payout": { "currency": "usd", "amount": 3675 },
"license_grant_id": "grt_01HZ..."
}Deployments
POST /v1/deployments— create a hosted endpoint from a modelGET /v1/deployments/{id}/logsPOST /v1/deployments/{id}/invoke— run inference
Webhooks
POST /v1/webhook_endpointsGET /v1/webhook_endpoints/{id}/events— replay log
See Authentication for signature verification.