API documentation
Full reference for the NeuroHub REST API: auth, catalog, chat, billing.
Overview
Control-plane API (account, catalog, wallet)
https://novastep.tech/api/v1OpenAI-compatible API (inference with an nh_* key)
https://novastep.tech/v1All endpoints are served by a single API gateway at https://novastep.tech. Data is JSON. Error responses always include an error.code that the client maps to a localized message.
NeuroHub API — REST, JSON. All requests (except public and auth) require an Authorization: Bearer token header.
Access tokens live 15 minutes; refresh tokens live 30 days in an httpOnly cookie scoped to /api.
On 401 the client transparently refreshes and retries. Server-rendered pages never send tokens — refresh is scoped to /api.
curl https://novastep.tech/v1/chat/completions \
-H "Authorization: Bearer nh_xxx" \
-H "Content-Type: application/json" \
-d '{"model":"tiny-llama-1b","messages":[{"role":"user","content":"hi"}],"stream":true}'SDKs & collections
Official Python and JavaScript clients (dependency-free, built on httpx/fetch), plus a machine-readable OpenAPI 3.1 spec and a ready-made Postman collection.
from neurohub import NeuroHub
client = NeuroHub(api_key="nh_xxx")
out = client.chat.completions.create(
model="tiny-llama-1b",
messages=[{"role": "user", "content": "hi"}],
)
print(out["choices"][0]["message"]["content"])import { NeuroHub } from "neurohub";
const client = new NeuroHub({ apiKey: "nh_xxx" });
const out = await client.chat.completions.create({
model: "tiny-llama-1b",
messages: [{ role: "user", content: "hi" }],
});
console.log(out.choices[0].message.content);Authentication
The access token lives 15 minutes, refresh — 30 days in an httpOnly cookie. On 401 the client refreshes and retries automatically.
- POST
/api/v1/auth/registerRegister a user
- POST
/api/v1/auth/confirm-emailConfirm email
- POST
/api/v1/auth/loginSign in, returns access+refresh
- POST
/api/v1/auth/refreshRefresh the access token
- GET
/api/v1/auth/meCurrent user
- PATCH
/api/v1/users/meUpdate profile
curl -X POST https://novastep.tech/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"you@example.com","password":"your-password"}'Models
- GET
/api/v1/models?q=&sort=popular&type=llmList models with filters and pagination
- GET
/api/v1/models/{slug}Model detail card
- GET
/api/v1/models/{slug}/versionsModel versions
- GET
/api/v1/models/{slug}/cost-estimateRequest cost estimate
curl https://novastep.tech/api/v1/models/tiny-llama-1b \
-H "Authorization: Bearer nh_xxx"Chat
Streaming responses via Server-Sent Events. Each frame is a JSON object with a type field: message.start → message.delta → usage → message.end.
- GET
/api/v1/chat/sessionsList chat sessions
- POST
/api/v1/chat/sessionsCreate a session
- POST
/api/v1/chat/sessions/{id}/messagesSend a message (SSE stream)
- POST
/api/v1/chat/stopCancel generation
- GET
/api/v1/chat/sessions/{id}/exportExport session history
data: {"type":"message.start","request_id":"req_1a2b","model_id":"..."}
data: {"type":"message.delta","request_id":"req_1a2b","delta":"Hello"}
data: {"type":"usage","request_id":"req_1a2b","usage":{"prompt_tokens":18,"completion_tokens":42},"cost_credits":0.42,"balance_credits":3011.58}
data: {"type":"message.end","request_id":"req_1a2b","message_id":"..."}OpenAI API
The same inference through the familiar OpenAI contract. Authorized with an nh_* key in the Authorization header. Drop-in for the official OpenAI SDKs, LangChain and LlamaIndex.
- GET
/v1/modelsList available models (OpenAI format)
- POST
/v1/chat/completionsChat completions; stream=true → SSE
from openai import OpenAI
client = OpenAI(base_url="https://novastep.tech/v1", api_key="nh_xxx")
for chunk in client.chat.completions.create(
model="tiny-llama-1b",
messages=[{"role": "user", "content": "hi"}],
stream=True,
):
print(chunk.choices[0].delta.content or "", end="")MCP
Wire Model Context Protocol tools (files, databases, GitHub, HTTP, messengers) into your agents and use NeuroHub models as a tool. Ready-made configs live in the API section.
Billing
- GET
/api/v1/walletWallet balance
- GET
/api/v1/transactionsTransaction ledger
- POST
/api/v1/topupsCreate a top-up invoice
- POST
/api/v1/me/payoutsRequest an author payout
- GET
/api/v1/me/earningsAuthor earnings by model
- GET
/api/v1/me/usageDaily usage
API keys
nh_* keys with scope limits, spend limits and RPS.
- POST
/api/v1/me/api-keysnh_* keys with scope limits, spend limits and RPS.
- GET
/api/v1/me/api-keysnh_* keys with scope limits, spend limits and RPS.
- PATCH
/api/v1/me/api-keys/{key_id}nh_* keys with scope limits, spend limits and RPS.
- DELETE
/api/v1/me/api-keys/{key_id}nh_* keys with scope limits, spend limits and RPS.
Publishing
Draft creation, editing, versions and publishing. The owner controls visibility and pricing.
- GET
/api/v1/models/mineList my models
- POST
/api/v1/modelsCreate a model draft
- PATCH
/api/v1/models/{id}Update a draft
- POST
/api/v1/models/{id}/versionsCreate a version
- POST
/api/v1/models/{id}/versions/{vid}/publishPublish a version
- POST
/api/v1/models/{id}/hideHide / show a model
File uploads
Multipart upload: chunked SHA-256, PUT to presigned URLs, resume from confirmed parts, extension and banned-artifact validation.
- POST
/api/v1/uploadsMultipart upload: chunked SHA-256, PUT to presigned URLs, resume from confirmed parts, extension and banned-artifact validation.
- POST
/api/v1/uploads/{upload_id}/parts/{part_number}Multipart upload: chunked SHA-256, PUT to presigned URLs, resume from confirmed parts, extension and banned-artifact validation.
- POST
/api/v1/uploads/{upload_id}/parts/{part_number}/confirmMultipart upload: chunked SHA-256, PUT to presigned URLs, resume from confirmed parts, extension and banned-artifact validation.
- POST
/api/v1/uploads/{upload_id}/completeMultipart upload: chunked SHA-256, PUT to presigned URLs, resume from confirmed parts, extension and banned-artifact validation.
- GET
/api/v1/uploads/{upload_id}/statusMultipart upload: chunked SHA-256, PUT to presigned URLs, resume from confirmed parts, extension and banned-artifact validation.
Errors
Error format: an error object with code, message and optionally param fields. HTTP statuses: 4xx client, 5xx server.
{
"error": {
"code": "validation_failed",
"message": "Invalid input",
"param": "input_chars"
}
}