Skip to content

Developer API

Available now: text chat, streaming and per-key usage. Open Usage → Developer access after connecting and verifying your wallet.

Connect your applications to Noema’s cloud models using the credits already available in your wallet account. Give each application its own key, allowed models, expiry and lifetime spending limit.

Create a key

  1. Connect and verify your wallet, then open Usage → Developer access.
  2. Choose Create key, name the application and set a dollar-denominated lifetime budget.
  3. Select allowed models and an expiry. Zero-retention only is the default. Allowing labelled provider retention is optional.
  4. Save the key when it appears. It cannot be shown again.

Keep keys in server environment variables. Never put them in frontend code, URLs or a public repository. Revoke a lost key and create a replacement. Revocation blocks new requests; requests already accepted can finish.

A key’s budget does not add credits. The key and the wallet both need enough available credit for a request. Active reservations count toward the limit; successful requests settle at the measured charge. Failed or cancelled requests release their reservation. Changing a key’s permissions or budget requires revoking and replacing it.

First request

Base URL: https://app.noemanetwork.xyz/api/v1

The following example runs on a server with the openai JavaScript package. Set NOEMA_API_KEY privately. A caller-generated UUID identifies one logical request.

js
import OpenAI from 'openai';
import { randomUUID } from 'node:crypto';

const noema = new OpenAI({
  apiKey: process.env.NOEMA_API_KEY,
  baseURL: 'https://app.noemanetwork.xyz/api/v1',
  maxRetries: 0,
});

const requestId = randomUUID();
const reply = await noema.chat.completions.create({
  model: 'noema-auto',
  messages: [{ role: 'user', content: 'Write a short project checklist.' }],
  max_tokens: 512,
}, { headers: { 'Idempotency-Key': requestId } });

console.log(reply.choices[0].message.content);

noema-auto lets Noema Router choose a cloud model. The selected underlying route is kept private. This hosted API does not run inference on your device or connected hardware.

Streaming

js
const stream = await noema.chat.completions.create({
  model: 'noema-auto',
  messages: [{ role: 'user', content: 'Outline a simple landing page.' }],
  max_completion_tokens: 512,
  stream: true,
  stream_options: { include_usage: true },
}, { headers: { 'Idempotency-Key': randomUUID() } });

for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta.content ?? '');
  if (chunk.usage) console.log(chunk.usage);
}

Chunks use chat.completion.chunk, followed by [DONE]. Reported token usage arrives at the end when requested. It may be absent if the provider did not report it or the stream was interrupted. An error after streaming begins is an error event, not a successful completion. Treat partial output as incomplete.

Choose a model

GET /models lists models permitted by your key and its retention policy. Each entry includes a public ID, display name and a noema object with retention and current prices. Prices are in micro-USD per million tokens and include Noema’s service costs. One dollar equals 1,000,000 micro-USD.

For a named model, use its returned ID and acknowledge the returned price version:

js
const catalogue = await noema.models.list();
const model = catalogue.data.find(item => item.id !== 'noema-auto');
if (!model) throw new Error('This key has no available named models.');

const response = await fetch('https://app.noemanetwork.xyz/api/v1/chat/completions', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.NOEMA_API_KEY}`,
    'Content-Type': 'application/json',
    'Idempotency-Key': randomUUID(),
  },
  body: JSON.stringify({
    model: model.id,
    messages: [{ role: 'user', content: 'Explain this task in three steps.' }],
    max_tokens: 512,
    noema: {
      price_version: model.noema.price.version,
      ...(model.noema.retention_version
        ? { retention_version: model.noema.retention_version }
        : {}),
    },
  }),
});
if (!response.ok) throw new Error(`Noema request failed: ${response.status}`);
console.log((await response.json()).choices[0].message.content);

The additional noema fields are extensions to the common API format. TypeScript clients should use a typed extension or a plain HTTP request to access them. Refresh the model list if the price or retention version changes; Noema rejects stale selections instead of silently accepting different terms. Requests fail if no permitted route is available.

Privacy and data

The key’s policy is enforced for every accepted request. A zero-retention key cannot be weakened by a caller. A request can require zero retention using X-Noema-Privacy-Policy: zero-retention. Local-only policies reject hosted requests; the API cannot redirect work to your hardware.

Protect sensitive text before sending it. An external application does not automatically run Noema’s browser ZKR. The API receives the text you submit, and permitted cloud providers process it. Zero retention is a provider-routing policy, not a hardware attestation or a claim that content never leaves your machine.

Keys cannot read your browser’s conversations, files, project context or memories. Noema stores key permissions and billing metadata, including request IDs, timing, token counts and charges. The API does not store prompts or answers for later retrieval. Usage stays associated with the funding wallet.

Usage and retries

Use GET /usage?page=0 with the same Bearer key to view that key’s budget, spend, reservations and requests. Pages contain up to 50 requests and hasMore indicates whether another page is available. Wallet owners can see all their keys in Usage.

Successful responses include compact noema billing metadata: request ID, charge state, reported cost, retention and zkr: caller-managed. These are application records, not cryptographic execution proofs.

Reuse the same UUIDv4 Idempotency-Key when checking an uncertain attempt. A repeated accepted ID returns 409; it never dispatches again. A changed payload with the same ID also returns 409. Check /usage for the original state. Responses cannot be replayed because their content is not stored.

Omitting the header generates a new request ID for each call. Automatic SDK retries without a stable ID can therefore create separate billable attempts. Disable automatic retries, or always supply and reuse your own ID. A new ID deliberately starts a new attempt.

StatusMeaningAction
400Invalid or unsupported requestCorrect the parameters or shorten the input
401Key invalid, expired or revokedCreate or use a valid key
402Wallet credit or key budget insufficientFund the wallet or replace the capped key
403Model outside key permissions, or browser callerUse a permitted model from server code
409Duplicate ID, changed terms or privacy conflictCheck usage, refresh terms or choose an allowed route
422Model could not complete the taskReview the task before a new attempt
429Request or provider capacity limitWait before a new attempt
503Service or provider unavailableCheck usage before retrying an uncertain attempt

Supported surface

  • GET /models, POST /chat/completions, GET /usage.
  • One text completion; system, developer, user and assistant messages. End with a user message.
  • Up to 80 messages and 24,000 combined input characters.
  • Either max_tokens or max_completion_tokens, from 1 to 4,096. Default 4,096.
  • Optional stream and stream_options.include_usage.
  • Up to three simultaneous reservations and 30 accepted requests per minute per key, subject to shared capacity.
  • Up to ten active keys per wallet; expiry from one to 365 days.

Tool calling, the Responses API, multimodal input, image/video/audio generation, sampling controls and structured-output parameters are not part of this first API version. Unsupported fields are rejected rather than ignored. These API limits do not remove the media tools available inside the Noema app.

A private AI workspace, built to put you in control.