Skip to content
NeuroHub

API documentation

Full reference for the NeuroHub REST API: auth, catalog, chat, billing.

Overview

Control-plane API (account, catalog, wallet)

https://novastep.tech/api/v1

OpenAI-compatible API (inference with an nh_* key)

https://novastep.tech/v1

All 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
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

v1.0

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.

pip install neurohub
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"])
npm install neurohub
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/register

    Register a user

  • POST
    /api/v1/auth/confirm-email

    Confirm email

  • POST
    /api/v1/auth/login

    Sign in, returns access+refresh

  • POST
    /api/v1/auth/refresh

    Refresh the access token

  • GET
    /api/v1/auth/me

    Current user

  • PATCH
    /api/v1/users/me

    Update profile

POST /api/v1/auth/login
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=llm

    List models with filters and pagination

  • GET
    /api/v1/models/{slug}

    Model detail card

  • GET
    /api/v1/models/{slug}/versions

    Model versions

  • GET
    /api/v1/models/{slug}/cost-estimate

    Request cost estimate

GET /api/v1/models/{slug}
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/sessions

    List chat sessions

  • POST
    /api/v1/chat/sessions

    Create a session

  • POST
    /api/v1/chat/sessions/{id}/messages

    Send a message (SSE stream)

  • POST
    /api/v1/chat/stop

    Cancel generation

  • GET
    /api/v1/chat/sessions/{id}/export

    Export session history

text/event-stream — one JSON object per frame
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/models

    List available models (OpenAI format)

  • POST
    /v1/chat/completions

    Chat completions; stream=true → SSE

Python (openai SDK)
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/wallet

    Wallet balance

  • GET
    /api/v1/transactions

    Transaction ledger

  • POST
    /api/v1/topups

    Create a top-up invoice

  • POST
    /api/v1/me/payouts

    Request an author payout

  • GET
    /api/v1/me/earnings

    Author earnings by model

  • GET
    /api/v1/me/usage

    Daily usage

API keys

nh_* keys with scope limits, spend limits and RPS.

  • POST
    /api/v1/me/api-keys

    nh_* keys with scope limits, spend limits and RPS.

  • GET
    /api/v1/me/api-keys

    nh_* 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.

chat
embeddings
images
audio

Publishing

Draft creation, editing, versions and publishing. The owner controls visibility and pricing.

  • GET
    /api/v1/models/mine

    List my models

  • POST
    /api/v1/models

    Create a model draft

  • PATCH
    /api/v1/models/{id}

    Update a draft

  • POST
    /api/v1/models/{id}/versions

    Create a version

  • POST
    /api/v1/models/{id}/versions/{vid}/publish

    Publish a version

  • POST
    /api/v1/models/{id}/hide

    Hide / 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/uploads

    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}

    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}/confirm

    Multipart upload: chunked SHA-256, PUT to presigned URLs, resume from confirmed parts, extension and banned-artifact validation.

  • POST
    /api/v1/uploads/{upload_id}/complete

    Multipart upload: chunked SHA-256, PUT to presigned URLs, resume from confirmed parts, extension and banned-artifact validation.

  • GET
    /api/v1/uploads/{upload_id}/status

    Multipart 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.

422 Validation error
{
  "error": {
    "code": "validation_failed",
    "message": "Invalid input",
    "param": "input_chars"
  }
}
401 unauthorized
403 forbidden
404 not_found
409 conflict
429 rate_limited

Keys and connectors live in the API section →