Skip to content

API reference

# API reference

Graphene is an OpenAI-compatible inference API. If your code already talks to
OpenAI, the only change is the base URL — see the [Quickstart](/docs/welcome).
This page is the reference for everything else: authentication, the inference
surface, the management endpoints, errors, rate limits and versioning.

## Base URLs

| Purpose                    | URL                          |
| -------------------------- | ---------------------------- |
| Inference (OpenAI-compat)  | `https://api.graphene.ai/v1` |
| Portal, docs and manifests | `https://graphene.ai`        |

Machine-readable definitions of everything below:

- `https://graphene.ai/api/openapi` — OpenAPI 3.1, including the `x-pricing`,
  `x-rate-limits` and `x-sla` vendor extensions.
- `https://graphene.ai/.well-known/agent.json` — capability manifest.
- `https://graphene.ai/api/benchmarks` — live performance telemetry.

## Authentication

Every request carries a workspace inference key as a bearer token:

```
Authorization: Bearer grph_live_...
```

Keys are created in the portal under **API keys**. Things worth knowing:

- **The prefix tells you which environment issued the key.** `grph_live_` is a
  production credential; `grph_test_` was issued by a non-production deployment
  and is not valid for live traffic. Check the prefix before wiring a key into
  anything that bills.

- **Keys are scoped credentials only.** A key never grants a capability your
  workspace does not already hold. It inherits the routing policy, budget and
  agreement lane of the workspace that issued it. Adding a scope to a key cannot
  unlock an enterprise capability — that is decided by your agreement, not by
  the key.
- **The secret is shown once.** Only the last four characters are recoverable
  afterwards. Rotate rather than recover.
- **Scopes** limit what a key may do. Inference keys need no extra scope;
  management endpoints require explicit scopes such as `entitlements:read`,
  listed per endpoint below.

## Chat completions

```
POST https://api.graphene.ai/v1/chat/completions
```

Request and response bodies follow the OpenAI chat-completions schema, so the
official SDKs work unmodified:

```python
from openai import OpenAI
import os

client = OpenAI(
    base_url="https://api.graphene.ai/v1",
    api_key=os.environ["GRAPHENE_API_KEY"],
)

resp = client.chat.completions.create(
    model="claude-opus-4-8",
    messages=[{"role": "user", "content": "Hello, Graphene"}],
    stream=True,
)
```

Streaming uses the same server-sent-event framing as OpenAI. Tool calls, JSON
mode, `temperature`, `max_tokens` and the rest of the common surface pass
through to the routed provider.

### Models

The public model identifiers are the provider names, addressable through the one
endpoint:

```
claude-opus-4-8   gpt-5.5   llama-4   gemini-3   mistral-large   deepseek-r2
```

The authoritative list is `models` in the capability manifest — read it rather
than hard-coding this list, because it moves when capacity does. See
[Models](/docs/models) for what each is good for.

Enterprise and sovereign customers get a larger catalogue with per-model
pricing, context windows and routing locality, plus the ability to bind a key to
a single model. That surface is gated — see
[Enterprise and sovereign access](/docs/enterprise-access).

## Management endpoints

These live on the portal origin (`https://graphene.ai`), not the inference base
URL. All of them accept a signed-in browser session; the ones with a scope also
accept `Authorization: Bearer <key>` when the integrator API is enabled for your
deployment.

| Endpoint                                 | Method   | Scope               | Returns                                                  |
| ---------------------------------------- | -------- | ------------------- | -------------------------------------------------------- |
| `/api/v1/me/entitlements`                | GET      | `entitlements:read` | Plan, limits and which capabilities your workspace holds |
| `/api/v1/catalogue/models`               | GET      | session only        | Full model catalogue — **enterprise/sovereign only**     |
| `/api/v1/capacity`                       | GET      | session only        | Current capacity posture                                 |
| `/api/v1/capacity/history`               | GET      | session only        | Historical capacity series                               |
| `/api/v1/capacity/alerts`                | GET      | session only        | Capacity alerts                                          |
| `/api/v1/workspace/{workspaceId}/runway` | GET      | session only        | Token runway projection                                  |
| `/api/budget/snapshot`                   | GET      | session only        | Monthly cap, spend-to-date and warn threshold            |
| `/api/workspace/v1/keys`                 | GET/POST | session only        | List and create workspace inference keys                 |
| `/api/workspace/v1/keys/{keyId}/rotate`  | POST     | session only        | Rotate a key's secret                                    |
| `/api/benchmarks`                        | GET      | none (public)       | Per-model latency, throughput, queue depth, 24h uptime   |
| `/api/openapi`                           | GET      | none (public)       | OpenAPI 3.1 document with pricing metadata               |

## Errors

Errors are returned as `application/problem+json` (RFC 9457) with a stable
machine-readable `code`. Branch on `code`, never on `title` or `detail`:

```json
{
  "title": "Enterprise catalogue access required",
  "status": 403,
  "code": "model_catalogue_access_required",
  "detail": "The model catalogue is available exclusively to enterprise and sovereign-compute customers."
}
```

| Status | `code`                            | Meaning                                                                     |
| ------ | --------------------------------- | --------------------------------------------------------------------------- |
| 401    | `unauthorized`, `invalid_token`   | No session and no valid bearer key                                          |
| 403    | `insufficient_scope`              | Key is valid but lacks the scope the endpoint requires                      |
| 403    | `model_catalogue_access_required` | Capability is enterprise/sovereign-gated and your lane does not hold it     |
| 404    | `integrator_api_disabled`         | Bearer-key access to management endpoints is off for this deployment        |
| 429    | `rate_limited`                    | Rate limit hit; honour `retry_after` (seconds)                              |
| 503    | `no_compliant_route`              | No route satisfied your compliance constraints — **fail-closed**, see below |
| 503    | `budget_unavailable`              | Budget service could not be read                                            |

### `no_compliant_route` is not a transient error

If your workspace carries region, provider or residency constraints and no
available capacity satisfies them, Graphene returns `503 no_compliant_route`
with a `failed_constraints[]` array — it does **not** quietly serve the request
somewhere else. Retrying without changing anything will fail the same way.
Graphene does not silently reroute workloads across jurisdictions. See
[Sovereignty](/docs/sovereignty).

## Rate limits

The published tiers, also carried in the OpenAPI `x-rate-limits` extension:

| Tier         | Requests / minute | Tokens / minute |
| ------------ | ----------------- | --------------- |
| `free`       | 60                | 60,000          |
| `pro`        | 600               | 1,000,000       |
| `enterprise` | by agreement      | by agreement    |

Management endpoints are separately limited to 120 requests per minute per
session or key. A limited response is `429` with `retry_after` in seconds — back
off for that long rather than retrying immediately.

## Pricing and billing

Billing is per token at a flat **20% under each provider's published list
price**. There is no platform fee, seat charge or minimum. Machine-readable
form, from the OpenAPI `x-pricing` extension:

```json
{
  "unit": "per_million_tokens",
  "basis": "provider_list_price",
  "discount_pct": 20,
  "rates_endpoint": "/api/v1/pricing"
}
```

`rates_endpoint` names the planned per-model machine rates feed; it is a
follow-up and may return 404 today. Until it ships, read prices from the
catalogue (enterprise) or compute them from the provider list price and the
discount. See the [Billing FAQ](/docs/billing-faq).

## Service levels

The OpenAPI `x-sla` extension reports `commitment: "enterprise-agreement-only"`.
That is literal: self-serve usage is provided as-is, and uptime, latency floors
and support tiers are commitments that exist only under an enterprise agreement.
The [benchmarks endpoint](/docs/system-status) publishes what we actually
measure, including honest nulls where a metric is not yet instrumented.

## Versioning

- The inference surface is versioned in the path (`/v1`). Breaking changes ship
  as a new path segment, never as a silent change to `/v1`.
- Additive changes — new fields, new models, new vendor extensions — can land in
  `/v1` at any time. Parse defensively and ignore fields you do not recognise.
- Deprecations are announced in the [changelog](/changelog) and, for enterprise
  agreements, directly. Superseded model identifiers keep an alias for at least
  one minor version.

## Next steps

- **[Agent cards](/docs/agent-cards)** — every machine-readable descriptor
  Graphene publishes
- **[Building agents](/docs/building-agents)** — notes for developers wiring
  agents to Graphene
- **[For agents](/docs/for-agents)** — instructions written for the agent itself
- **[Enterprise and sovereign access](/docs/enterprise-access)** — pinned
  models, region constraints, private routing