Developer guide

Documentation

Prism is fully compatible with the OpenAI SDK. Any tool or library that speaks the OpenAI API format — Python, JavaScript, LangChain, whatever you already have — works against Prism out of the box. The only change required is the base URL and API key.

Quickstart

Point the official OpenAI SDK at Prism instead of OpenAI, and use any Prism model id in place of a model name — including Gemini and Claude models, through the same client.

Python

from openai import OpenAI

client = OpenAI(
    base_url="https://prism.dcornerr.in/api/v1",
    api_key="sk-dprism-...",
)

completion = client.chat.completions.create(
    model="openai/gpt-5.4-mini",
    messages=[{"role": "user", "content": "Hello!"}],
)
print(completion.choices[0].message.content)

JavaScript

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://prism.dcornerr.in/api/v1",
  apiKey: "sk-dprism-...",
});

const completion = await client.chat.completions.create({
  model: "openai/gpt-5.4-mini",
  messages: [{ role: "user", content: "Hello!" }],
});
console.log(completion.choices[0].message.content);

Swap providers by changing only the model string — openai/gpt-5.4-mini, gemini/gemini-flash-lite-latest, and anthropic/claude-haiku-4-5 all work through the exact same client, same method calls, same response shape.

Installation

Prism has no SDK of its own — install the official OpenAI client for your language and point it at Prism (see Quickstart). If you don't already have it installed:

Python

pip install openai

JavaScript / TypeScript

npm install openai

Any OpenAI SDK version that supports baseURL / base_urlworks — there's nothing Prism-specific to install beyond that.

Authentication

Create an API key from your dashboard and use it as your SDK's api_key— or send it directly as a bearer token if you're calling the HTTP API yourself. Keys are shown once at creation — store them somewhere safe.

Authorization: Bearer sk-dprism-...

Available models

Pass any of these as the model string. Higher tiers unlock more models — see pricing for what each plan includes.

Model IDProviderTypeTokens/1M inputTokens/1M output
openai/gpt-5.4-nanoopenaichat26.67166.67
openai/gpt-5.4-miniopenaichat100.00600.00
gemini/gemini-flash-lite-latestgeminichat33.33200.00
gemini/gemini-flash-latestgeminichat200.001200.00
gemini/gemini-3.1-flash-lite-imagegeminiimage33.334000.00
openai/gpt-image-1-miniopenaiimage266.671066.67
anthropic/claude-haiku-4-5anthropicchat133.33666.67
anthropic/claude-sonnet-5anthropicchat400.002000.00

Streaming

Pass stream: true (or stream=Truein Python) to any chat model and the SDK's normal streaming iterator works unchanged — no different code path than talking to OpenAI directly.

stream = client.chat.completions.create(
    model="gemini/gemini-flash-lite-latest",
    messages=[{"role": "user", "content": "Write a haiku about the ocean."}],
    stream=True,
)
for chunk in stream:
    delta = chunk.choices[0].delta.content
    if delta:
        print(delta, end="")

The final chunk carries usage and a billingfield, same as the non-streaming response — that's when the call is actually billed, since token usage for a streamed response is only known once it finishes.

Image generation

POST /api/v1/images/generations, or client.images.generate() in the SDK. Image models are billed in tokens exactly like chat models — see the model table above.

image = client.images.generate(
    model="gemini/gemini-3.1-flash-lite-image",
    prompt="A watercolor painting of a mountain lake at sunrise",
)
# image.data[0].b64_json is the base64-encoded image

Billing

Your account holds a single token balance. Every call — chat or image — is billed based on the actual input/output token counts the provider returns, deducted from your balance. Different models consume tokens at different rates — see the model table above for tokens per 1M input/output tokens on each model.

A call is rejected with 402 if your balance is at or below zero before the call starts. Because the exact usage of a call is only known after it completes, a single large completion can take your balance slightly negative — check your logs for exact token usage per call. Balances are credited manually — contact the Prism team to top up.

Raw HTTP

If you'd rather not use an SDK, the endpoints are plain JSON over HTTPS.

cURL

curl https://prism.dcornerr.in/api/v1/chat/completions \
  -H "Authorization: Bearer sk-dprism-..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemini/gemini-flash-lite-latest",
    "messages": [{ "role": "user", "content": "Hello!" }]
  }'

Response

{
  "id": "chatcmpl-...",
  "object": "chat.completion",
  "created": 1730000000,
  "model": "openai/gpt-5.4-mini",
  "choices": [
    { "index": 0, "message": { "role": "assistant", "content": "..." }, "finish_reason": "stop" }
  ],
  "usage": { "prompt_tokens": 12, "completion_tokens": 34, "total_tokens": 46 },
  "billing": { "cost_usd": 0.000163, "tokens_deducted": 0.021733 }
}

Errors

StatusMeaning
401Missing, invalid, or revoked API key.
400Malformed request, unknown model, or wrong endpoint for that model's type.
402Token balance exhausted.
403Your plan doesn't include this model — upgrade at /pricing.
502The upstream provider (OpenAI/Gemini/Anthropic) returned an error.

Debugging

Common issues and how to work through them:

  • 401invalid_api_key — the key is missing, misspelled, or was revoked. Generate a fresh one from the dashboard and confirm it's sent as Authorization: Bearer sk-dprism-..., not just the raw key.
  • 400Unknown model — the model string must exactly match an ID from the models table above, including the provider prefix (e.g. anthropic/claude-haiku-4-5, not just claude-haiku-4-5).
  • 403insufficient_plan — that model requires a higher plan than your account currently has. Check the model table above against your plan.
  • 402insufficient_balance — your token balance is at or below zero. It renews automatically each billing period, or contact the Prism team to top up sooner.
  • 502upstream_error — the underlying provider (OpenAI, Gemini, or Anthropic) rejected or failed the request. The error message in the response body is passed through from the provider largely as-is, so it usually tells you exactly what went wrong (bad prompt format, provider outage, rate limit, etc.).
  • TipResponse looks truncated — check finish_reason; if it's length, raise max_tokens in your request.
  • TipStill stuck — every call, successful or not, shows up in your logs with its exact status and token counts, which is usually the fastest way to see what actually happened.
Powered byDCornerr