OpenGray API

Version 1 · Last updated September 24, 2026

OpenGray exposes a single OpenAI-compatible HTTP API in front of frontier language models. If your code already talks to the OpenAI Chat Completions API, you only need to change the base URL and the key.

Base URLhttps://open-gray.com/api/v1
Auth schemeAuthorization: Bearer sk-og-v1-...
Content typeapplication/json
Billing unitCredits (100 credits = US$1.00)

Authentication

Every request must carry a bearer token issued from the API keys page. Keys are shown once at creation and stored only as a SHA-256 hash, so keep a copy in your secret manager. A key can be revoked at any time and can optionally carry a credit spend limit.

Never ship a key in browser code. Requests should be signed from your backend.

Quickstart

Create an account, add credits, then send your first request:

curl https://open-gray.com/api/v1/chat/completions \
  -H "Authorization: Bearer sk-og-v1-..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-fable-5",
    "messages": [
      { "role": "user", "content": "Summarise our Q3 revenue drivers." }
    ]
  }'
Replace the key with one from your dashboard.

Chat completions

POST /chat/completions

Request fields:

FieldTypeDescription
modelstringRequired. A slug from /models, for example claude-fable-5.
messagesarrayRequired. Standard chat messages with role and content. Content may be a string or an array of text and image parts.
streambooleanStream the response as server-sent events. Defaults to false.
max_tokensintegerUpper bound on generated tokens.
temperaturenumberSampling temperature, where the model supports it.
reasoning_effortstringlow, medium, high, xhigh or max. Higher effort costs more output tokens.
tools, tool_choicearray, stringFunction calling, passed through unchanged.
response_formatobjectUse {"type":"json_object"} or a JSON schema for structured output.

A successful response mirrors the OpenAI shape and adds the credits consumed:

{
  "id": "gen-1a2b3c",
  "object": "chat.completion",
  "created": 1785794208,
  "model": "claude-fable-5",
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "..." },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 412,
    "completion_tokens": 180,
    "total_tokens": 592,
    "cost_credits": 1.312
  }
}
The x-opengray-credits-charged and x-opengray-balance response headers carry the same figures.

Streaming

Set "stream": true to receive text/event-stream frames. Each frame is a data: line containing a chunk object, and the stream terminates with data: [DONE]. The final chunk before the terminator includes the usage block with cost_credits.

curl -N https://open-gray.com/api/v1/chat/completions \
  -H "Authorization: Bearer sk-og-v1-..." \
  -H "Content-Type: application/json" \
  -d '{"model":"claude-fable-5","stream":true,"messages":[{"role":"user","content":"Count to five."}]}'

Credits are debited when the stream completes. If a client disconnects mid-stream, the tokens already generated upstream are still billed.

List models

GET /models returns the catalogue with pricing expressed in credits per token.

{
  "object": "list",
  "data": [
    {
      "id": "claude-fable-5",
      "object": "model",
      "owned_by": "Anthropic",
      "context_length": 1000000,
      "pricing": { "prompt_credits": "0.001", "completion_credits": "0.005" }
    }
  ]
}

Key and balance

GET /key returns the calling key's metadata and the account balance. Use it for preflight checks in long-running jobs.

{
  "data": {
    "label": "Production",
    "balance_credits": 842.51,
    "balance_usd": 8.4251,
    "limit_credits": null,
    "usage_credits": 57.49
  }
}

Billing behaviour

  • Charges are derived from the generation's real token counts, never from an estimate.
  • Cached input tokens bill at the model's cache-read rate automatically.
  • Requests are refused with 402 when the balance is at or below the minimum threshold.
  • Failed upstream requests are logged but not charged.
  • Every charge appears on the activity and transactions pages within seconds.

Errors

Errors use the OpenAI envelope: {"error": {"message": "...", "type": "...", "code": 400}}.

StatusTypeMeaning
400invalid_request_errorMalformed JSON, missing messages or an unknown model.
401authentication_errorMissing, malformed or revoked API key.
402insufficient_creditsAccount balance or key limit exhausted.
403account_suspendedThe owning account is suspended.
404model_not_foundThe requested model is not in the catalogue.
429rate_limit_errorToo many requests; retry with backoff.
502upstream_errorThe provider returned an error or timed out. Not billed.

Limits

  • Request body limit: 8 MB.
  • Non-streaming timeout: 300 seconds. Streaming timeout: 600 seconds.
  • Concurrency is not capped per account; sustained abuse is rate limited per key.
  • Keys per account: unlimited.

Migrating

From OpenAI: set base_url to https://open-gray.com/api/v1, swap the key, and use an OpenGray model slug.

From OpenRouter: the request and response shapes match. Replace vendor-prefixed slugs such as anthropic/claude-fable-5 with claude-fable-5; the prefixed form is accepted too.

Anything unclear? Write to contact@open-gray.com and we will answer.