NetRoom Developer API: Text, Images, Video and Sound with One Key
NETROOM API

Developer API

One key for text models, images, video and sound. The chat endpoint is OpenAI-compatible, media generation runs through a single endpoint with a per-model parameter schema in the catalog. You pay from your NetRoom balance for actual usage only.

Base URL https://net-room.com/api/v1
Format JSON, UTF-8
Auth Authorization: Bearer nr-...
Compatibility OpenAI SDKs — only base_url changes

Quickstart

01

Create an API key

In your NetRoom account, API tab. The nr-... key is shown once at creation — save it right away.

02

Top up your balance

Requests are paid from your NetRoom balance as you go — no subscription required.

03

Make your first request

Copy an example below, drop in your key and a model id from the catalog.

curl
curl https://net-room.com/api/v1/chat/completions \
  -H "Authorization: Bearer nr-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4o-mini",
    "messages": [{"role": "user", "content": "Hello! What can you do?"}]
  }'
Python (openai SDK)
from openai import OpenAI

client = OpenAI(
    base_url="https://net-room.com/api/v1",
    api_key="nr-YOUR_KEY",
)

response = client.chat.completions.create(
    model="openai/gpt-4o-mini",
    messages=[{"role": "user", "content": "Hello! What can you do?"}],
)
print(response.choices[0].message.content)
JavaScript / Node.js (openai SDK)
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://net-room.com/api/v1",
  apiKey: "nr-YOUR_KEY",
});

const response = await client.chat.completions.create({
  model: "openai/gpt-4o-mini",
  messages: [{ role: "user", content: "Hello! What can you do?" }],
});
console.log(response.choices[0].message.content);

Model ids in the examples are placeholders — take real ids from the GET /api/v1/models catalog.

Authentication

Every request except GET /api/v1/models must carry the header:

HTTP header
Authorization: Bearer nr-YOUR_KEY
  • Keys are created and revoked in your NetRoom account. A revoked key stops working within a minute.
  • The raw key is stored only on your side: NetRoom keeps its sha256 hash. Lost a key — create a new one and revoke the old one.
  • Never publish a key in client-side code, repositories or logs. For browser apps, proxy requests through your own backend.
  • A wrong or revoked key returns 401 with code invalid_api_key.

Model catalog and pricing

GET /api/v1/models

No auth required. Returns a single list of all available models with final NetRoom prices — the only source of pricing, always up to date. The catalog is cached server-side for about 5 minutes.

Request
curl https://net-room.com/api/v1/models
Response (excerpt, sample values)
{
  "object": "list",
  "data": [
    {
      "id": "openai/gpt-4o-mini",
      "object": "model",
      "type": "text",
      "name": "GPT-4o mini",
      "pricing": {"currency": "RUB", "input_per_1k_tokens": 0.5, "output_per_1k_tokens": 1.5}
    },
    {
      "id": "image-model-id",
      "object": "model",
      "type": "image",
      "name": "...",
      "pricing": {"currency": "RUB", "per_image": 12.0},
      "input_schema": {"type": "object", "required": ["prompt"], "properties": {"...": "..."}}
    }
  ]
}
FieldDescription
typetext | image | video | sound. Text models are called via /api/v1/chat/completions, everything else via /api/v1/generations.
pricingFinal NetRoom prices: text models — per 1K input and output tokens; images — per_image; video — per_second; sound — per_1000_chars, per_1000_bytes (UTF-8 bytes of the text: 1 per Latin character, 2 per Cyrillic), per_minute, per_generation or per_second depending on the model. Free text models have zero prices.
input_schemaMedia models only: the JSON Schema of the input field for /api/v1/generations — required fields, allowed values, limits. Requests are validated against exactly this schema, so build your forms and clients from it.

Model descriptions and current prices are also on the site — in the model catalog.

Text models

POST /api/v1/chat/completions

An OpenAI-compatible endpoint for every text model in the catalog. Official OpenAI SDKs work as is — just change base_url and the key.

FieldTypeDescription
modelstringRequired. A text model id from the catalog.
messagesarrayRequired. A non-empty array of {role, content} messages.
streambooleantrue — stream the response over SSE. Defaults to false.

Standard parameters are also supported:

temperaturemax_tokenstop_ptop_kfrequency_penaltypresence_penaltyrepetition_penaltystopseedresponse_formatlogit_biaslogprobstop_logprobstoolstool_choiceparallel_tool_callsreasoning

Parameters a model does not support are ignored on its side.

Regular mode (no streaming)

Response
{
  "id": "gen-...",
  "object": "chat.completion",
  "model": "openai/gpt-4o-mini",
  "choices": [
    {
      "index": 0,
      "message": {"role": "assistant", "content": "Hi! I can help with..."},
      "finish_reason": "stop"
    }
  ],
  "usage": {"prompt_tokens": 12, "completion_tokens": 34, "total_tokens": 46}
}

usage carries token counters only — the same numbers your balance is billed by.

Streaming (stream: true)

The response arrives as Server-Sent Events (Content-Type: text/event-stream): data: {chunk} lines with deltas in choices[].delta.content and a final data: [DONE] marker.

Python
stream = client.chat.completions.create(
    model="openai/gpt-4o-mini",
    messages=[{"role": "user", "content": "Tell me about yourself"}],
    stream=True,
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)

If an error happens after the stream has started, it arrives inside the stream as a data: {"error": {...}} event followed by data: [DONE]. If the client drops the connection, the part of the response generated so far is billed.

Images as input (vision)

For vision-capable models, images are passed in the standard OpenAI format — content parts of type image_url (a regular URL or a base64 data: URL). Request body limit is 25 MB.

Request body
{
  "model": "...",
  "messages": [{
    "role": "user",
    "content": [
      {"type": "text", "text": "What is in this photo?"},
      {"type": "image_url", "image_url": {"url": "https://example.com/photo.jpg"}}
    ]
  }]
}

Billing for text requests

Billing happens after the response, by actual token usage and the model's catalog prices. Paid models require a positive balance — otherwise 402 insufficient_balance before the model is even called.

Media generation

POST /api/v1/generations

One endpoint for images, video and sound. The set of input fields depends on the model — it is described by the model's input_schema in the catalog.

Request body
{
  "model": "model-id-from-catalog",
  "input": { ... }
}
  • All media references (frames, reference images) must be public http(s) URLs. Inline base64 is not accepted; the request body limit is 2 MB.
  • Requests are validated against input_schema; violations return 400 invalid_request with a list of specific errors.
  • The cost is computed server-side from the generation parameters and debited from your balance; with insufficient funds you get 402 insufficient_balance and the generation does not start.

Images

Run synchronously: a 200 response comes back right away with ready URLs. Typical input fields: prompt (required), negative_prompt, aspect_ratio, resolution, width/height, number_results (1-4), output_format, reference_images — on models that support references.

Request
curl https://net-room.com/api/v1/generations \
  -H "Authorization: Bearer nr-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "image-model-id",
    "input": {"prompt": "a cozy seaside cafe, cinematic light", "aspect_ratio": "16:9"}
  }'
Response (excerpt, sample values)
{
  "id": "img_12345",
  "object": "generation",
  "type": "image",
  "model": "image-model-id",
  "status": "succeeded",
  "progress": 100,
  "outputs": ["https://.../result.jpg"],
  "cost": 12.0,
  "error": null,
  "created_at": "2026-08-15T12:00:00+03:00"
}

Video

Run asynchronously: a 202 response with status queued or processing, the result is fetched by polling. Typical input fields: prompt (required), duration (seconds, allowed values are in the schema), aspect_ratio, resolution, negative_prompt, sound, cfg_scale, first_frame / last_frame (frame URLs for image-to-video), reference_images, reference_videos.

Request
curl https://net-room.com/api/v1/generations \
  -H "Authorization: Bearer nr-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "video-model-id",
    "input": {
      "prompt": "a drone flies over a mountain lake at sunrise",
      "duration": 5,
      "aspect_ratio": "16:9",
      "resolution": "1080p"
    }
  }'
202 response (sample values)
{
  "id": "3f2a9c...",
  "object": "generation",
  "type": "video",
  "model": "video-model-id",
  "status": "queued",
  "progress": 0,
  "outputs": [],
  "cost": 45.0,
  "error": null,
  "created_at": "2026-08-15T12:00:00+03:00",
  "estimated_time_seconds": 60
}

Sound

Also asynchronous (202 + polling). Sound models come in three kinds with different input fields — the exact set is always in input_schema:

Text to speech (TTS)

text (required), voice, language, output_format

{"model": "tts-model-id", "input": {"text": "Good afternoon! Your order is confirmed.", "voice": "voice-name"}}

Music

mode (prompt | lyrics | instrumental), prompt and/or lyrics, negative_prompt, seed, output_format

{"model": "music-model-id", "input": {"mode": "prompt", "prompt": "a calm lo-fi beat with vinyl crackle"}}

Sound effects (SFX)

prompt (required), output_format

{"model": "sfx-model-id", "input": {"prompt": "rain on a tin roof, 10 seconds"}}

Generation status

GET /api/v1/generations/{id}

Status and result of any generation. id comes from the creation response (a string; img_<n> for images), accessible only to the key owner. Statuses: queued -> processing -> succeeded | failed.

Request
curl https://net-room.com/api/v1/generations/3f2a9c... \
  -H "Authorization: Bearer nr-YOUR_KEY"
  • succeeded — ready files in outputs (a list of URLs).
  • failed — the reason is in error; a failed generation is not billed.
  • progress — 0-100; for video, estimated_time_seconds from the creation response helps too.
  • cost — the generation cost; for asynchronous generations the debit is finalized on successful completion.

The recommended polling interval is 3-5 seconds. Polling several generations too aggressively in parallel can hit the per-minute request limit.

Error format

All errors are JSON of the same shape:

{
  "error": {
    "message": "A human-readable description of the problem",
    "type": "invalid_request_error",
    "code": "invalid_request"
  }
}
HTTPcodeWhen
400invalid_requestInvalid body, unsupported method, input validation error, or a request rejected by the model.
401invalid_api_keyMissing Authorization header, wrong or revoked key.
402insufficient_balanceNot enough funds on the NetRoom balance.
404model_not_foundNo model with this id (check GET /api/v1/models).
404not_foundNo generation with this id, or it belongs to another account.
429rate_limit_exceededPer-minute or concurrency limit exceeded; the response carries a Retry-After header (seconds).
502upstream_errorA temporary error on the generation side — retry later.
500server_errorInternal NetRoom error.

The type field is an OpenAI-like category (authentication_error, insufficient_quota, invalid_request_error, rate_limit_error, api_error) kept for SDK compatibility; build your program logic on code and the HTTP status.

In streaming mode an error after the stream has started arrives as a data: {"error": {...}} event inside the SSE stream.

Limits

LimitValue
Rate60 requests per minute per key by default (fixed window); an individual key limit may differ. Exceeding it returns 429 with a Retry-After header.
ConcurrencyAt most 4 simultaneous requests per account — across all of the account's keys.
Body size25 MB for /chat/completions (inline images included), 2 MB for /generations (media by URL only).
KeysUp to 10 active keys per account.

Handle 429 with exponential backoff starting from the Retry-After value; request long text answers with stream: true.

Request logging and retention

To prevent abuse and to investigate incidents and disputed charges, NetRoom keeps a log of API requests. The log records: the model, request parameters, messages (truncated), the truncated response text, token counters, cost, status, IP address and response time. Inline images (data: URLs) are never stored — a technical stub with the size and a checksum is recorded instead of the content.

Log records are kept for a limited time — 90 days by default — and are then deleted automatically. Balance debit history is kept separately in the account's financial history and is not subject to this period.

One key — every model

Create a key in the API tab of your account and make the first request in five minutes. Validation errors are free, failed generations are not billed.