NURA NURAChat · Private Inference
Developer API

Build with the NURA API

OpenAI-compatible inference for text, images, video and speech — one endpoint, many providers.

Base URLhttps://api.nuraix.com/v1 Localhttp://localhost:3000/v1
POST /v1/chat/completions
curl https://api.nuraix.com/v1/chat/completions \
  -H "Authorization: Bearer $NURA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen3-32b",
    "messages": [
      { "role": "user", "content": "Hello, NURA!" }
    ]
  }'
Quickstart

Your first request

The NURA API speaks the OpenAI wire format, so most OpenAI SDKs work by simply changing the base URL and key.

Base URL

Send all requests to https://api.nuraix.com/v1. When developing against a local node, use http://localhost:3000/v1.

Authentication

Authenticate with a bearer token: Authorization: Bearer <API_KEY>. Generate a key in the chat app at chat.nuraix.com.

Provider source

The optional header x-aix-source: official | workers picks first-party providers (official) or NURA GPU workers (workers). If omitted, it follows the platform default.

Make a chat completion

Send a minimal request and read the assistant reply from choices[0].message.content.

curl https://api.nuraix.com/v1/chat/completions \
  -H "Authorization: Bearer $NURA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "x-aix-source: official" \
  -d '{
    "model": "qwen3-32b",
    "messages": [
      { "role": "user", "content": "Hello, NURA!" }
    ]
  }'
const res = await fetch("https://api.nuraix.com/v1/chat/completions", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${NURA_API_KEY}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    model: "qwen3-32b",
    messages: [{ role: "user", content: "Hello, NURA!" }]
  })
});

const data = await res.json();
console.log(data.choices[0].message.content);
Endpoint

Chat Completions

POST/v1/chat/completions

Generate conversational and reasoning responses. Send a list of messages and stream tokens back over SSE.

ParameterTypeDescription
model RequiredstringID of the model to use.
messages RequiredarrayThe conversation so far.
streambooleanStream deltas over SSE.
temperaturenumberSampling temperature.
max_tokensnumberMaximum tokens to generate.
reasoning_effortstringReasoning depth.
enable_thinkingbooleanQwen thinking phase.
thinking_budgetnumberMax tokens for thinking.
enable_searchbooleanAlibaba web search.
content (parts)arrayMultimodal image input.

Streaming (SSE)

Set stream: true and read the response body incrementally, appending choices[0].delta.content.

curl -N https://api.nuraix.com/v1/chat/completions \
  -H "Authorization: Bearer $NURA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-5",
    "messages": [
      { "role": "system", "content": "You are a helpful assistant." },
      { "role": "user", "content": "Explain DePIN in one sentence." }
    ],
    "temperature": 0.7,
    "max_tokens": 512,
    "reasoning_effort": "medium",
    "stream": true
  }'
const res = await fetch("https://api.nuraix.com/v1/chat/completions", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${NURA_API_KEY}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    model: "qwen3-32b",
    messages: [{ role: "user", content: "Write a haiku about GPUs." }],
    stream: true
  })
});

const reader = res.body.getReader();
const decoder = new TextDecoder();
let buffer = "";

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  buffer += decoder.decode(value, { stream: true });
  const lines = buffer.split("\n");
  buffer = lines.pop();
  for (const line of lines) {
    if (!line.startsWith("data: ")) continue;
    const payload = line.slice(6).trim();
    if (payload === "[DONE]") break;
    const json = JSON.parse(payload);
    const delta = json.choices[0].delta.content;
    if (delta) process.stdout.write(delta);
  }
}

Reasoning & web search

Reasoning models accept reasoning_effort. Alibaba Qwen adds enable_thinking, thinking_budget and enable_search.

curl https://api.nuraix.com/v1/chat/completions \
  -H "Authorization: Bearer $NURA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen3-32b",
    "messages": [
      { "role": "user", "content": "What broke in AI news today?" }
    ],
    "enable_thinking": true,
    "thinking_budget": 2048,
    "enable_search": true
  }'

Image input (multimodal)

Pass images to vision models using content parts. Provide a public URL or a data: URI.

{
  "model": "gpt-5",
  "messages": [
    {
      "role": "user",
      "content": [
        { "type": "text", "text": "What is in this image?" },
        {
          "type": "image_url",
          "image_url": { "url": "https://example.com/cat.jpg" }
        }
      ]
    }
  ]
}
Endpoint

Image Generation

POST/v1/images/generations

Generate images from a text prompt, or edit an existing image (image-to-image).

ParameterTypeDescription
model RequiredstringImage model.
prompt RequiredstringText description.
nnumberNumber of images.
response_formatstringUse b64_json.
sizestringOpenAI-style pixel size.
aspect_ratiostringxAI grok-imagine ratio.
image_urlstringSource for image-to-image.
curl https://api.nuraix.com/v1/images/generations \
  -H "Authorization: Bearer $NURA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image",
    "prompt": "A neon data center on the moon, cinematic",
    "n": 1,
    "size": "1024x1024",
    "response_format": "b64_json"
  }'
const res = await fetch("https://api.nuraix.com/v1/images/generations", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${NURA_API_KEY}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    model: "grok-imagine",
    prompt: "A koi pond, ukiyo-e woodblock print",
    aspect_ratio: "16:9",
    response_format: "b64_json"
    // image_url: "https://example.com/ref.png"  // image-to-image
  })
});

const { data } = await res.json();
const pngBase64 = data[0].b64_json;
Available image providers include OpenAI gpt-image, xAI grok-imagine, Venice / Flux, and Alibaba Qwen-Image / Wan (up to 2048²).
Endpoint · Async

Video Generation

POST/v1/videos/generationsasync

Video generation is asynchronous: create a job, then poll for the result.

ParameterTypeDescription
model RequiredstringVideo model.
prompt RequiredstringText description.
image_urlstringSource image to animate.

1Create the job

POST a prompt (optionally an image_url). The response returns a request_id and the provider.

curl https://api.nuraix.com/v1/videos/generations \
  -H "Authorization: Bearer $NURA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-imagine-video",
    "prompt": "A drone shot gliding over a glowing city at night"
  }'

# Response:
# { "request_id": "vid_abc123", "provider": "xai" }

2Poll for the result

Call GET /v1/videos/status with the provider and id until status is no longer processing.

GET/v1/videos/status?provider=<p>&id=<request_id>
async function generateVideo(prompt) {
  const create = await fetch("https://api.nuraix.com/v1/videos/generations", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${NURA_API_KEY}`,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({ model: "grok-imagine-video", prompt })
  });
  const { request_id, provider } = await create.json();

  // Poll until the job leaves "processing" (typically 40-60s)
  while (true) {
    await new Promise(r => setTimeout(r, 4000));
    const url =
      "https://api.nuraix.com/v1/videos/status" +
      `?provider=${provider}&id=${request_id}`;
    const res = await fetch(url, {
      headers: { "Authorization": `Bearer ${NURA_API_KEY}` }
    });
    const job = await res.json();
    if (job.status !== "processing") return job; // { status, url, b64 }
  }
}
Generation is asynchronous and typically takes about 40–60 seconds. Poll every few seconds rather than blocking.
Endpoint

Text-to-Speech

POST/v1/audio/speech

Synthesize natural speech from text. The response returns a temporary url, inline b64 audio and its mime type.

ParameterTypeDescription
model RequiredstringTTS model.
text RequiredstringThe text to speak.
voicestringVoice name.
instructionsstringStyle instructions.
languagestringLanguage hint.
curl https://api.nuraix.com/v1/audio/speech \
  -H "Authorization: Bearer $NURA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen3-tts-flash",
    "text": "Welcome to NURA, private inference for everyone.",
    "voice": "Cherry",
    "language": "en"
  }'

# Response:
# { "url": "https://.../speech.mp3", "b64": "...", "mime": "audio/mpeg" }
const res = await fetch("https://api.nuraix.com/v1/audio/speech", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${NURA_API_KEY}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    model: "qwen3-tts-flash",
    text: "The future of compute is decentralized.",
    voice: "Ethan",
    instructions: "Warm, upbeat narration"
  })
});

const { url, b64, mime } = await res.json();
Built-in voices include Cherry, Ethan, Serena, Chelsie and Dylan. Voice-clone models (qwen3-tts-vc) accept a short reference audio clip.
Endpoint

Models

GET/v1/models

List every model currently available to your key.

Each entry reports its owned_by provider and a kind of chat, image, video or tts.

curl https://api.nuraix.com/v1/models \
  -H "Authorization: Bearer $NURA_API_KEY"
{
  "object": "list",
  "data": [
    { "id": "qwen3-32b",          "object": "model", "owned_by": "alibaba", "kind": "chat"  },
    { "id": "gpt-image",          "object": "model", "owned_by": "openai",  "kind": "image" },
    { "id": "grok-imagine-video", "object": "model", "owned_by": "xai",     "kind": "video" },
    { "id": "qwen3-tts-flash",    "object": "model", "owned_by": "alibaba", "kind": "tts"   }
  ]
}
Reference

Providers & Capabilities

Capabilities vary by provider and configured availability. A ✓ marks features described in this documentation.

Provider Text Reasoning Web search Image Video TTS
OpenAI
Anthropic (Claude)
xAI (Grok)
Venice
Alibaba (Qwen / Qwen-Image / Wan / Qwen-TTS)
DeepSeek
Important

Notes & Cautions

A few things to keep in mind when building on the NURA API.

  • Keep keys secret. API keys are secrets — never embed them in client-side code. Call the API from a server.
  • You are billed per use. Requests are metered per token, image, second of video, or character of speech. See pricing.
  • Stream long outputs. Streaming is strongly recommended for long completions.
  • Video is asynchronous. Video jobs must be polled and can take about 40–60 seconds.
  • Media URLs expire. Generated image, video and audio URLs are temporary — download promptly.
  • Chat is not retained. Conversation data is not stored after inference.
  • Rate limits apply. Back off and retry on 429 responses.
  • Availability varies. Reachable models depend on the configured providers and online workers.

Need a hand? See pricing for costs, or ask the Assistant for help.