Skip to content

For developers

Switch the base URL.
Keep the receipts.

Ryvion speaks the OpenAI protocol. Every response — streaming or batch — carries a signed RYV1 receipt CID in the headers.

Latency p50
280 ms
Speedup
2.4×
Receipt
every response

▪ latency + speedup are reference benchmarks · live network metrics on /v8

Request
from openai import OpenAI

client = OpenAI(
    base_url="https://api.ryvion.ai/v1",
    api_key="ryv_…",
)

resp = client.chat.completions.create(
    model="llama-3.2-3b",
    messages=[{"role": "user", "content": "Hello"}],
)

# Every response carries a signed receipt CID.
print(resp.headers["X-Ryvion-Receipt-CID"])

Quick starts

Three snippets to ship.

Copy, paste, swap your key. The third snippet runs without a key — that’s the verifier.

Standard inference

Switch the base URL

OpenAI SDK, Ryvion key. Your existing code keeps working.

from openai import OpenAI

client = OpenAI(
    base_url="https://api.ryvion.ai/v1",
    api_key="ryv_…",
)

resp = client.chat.completions.create(
    model="llama-3.2-3b",
    messages=[{"role": "user", "content": "ping"}],
)
print(resp.headers["X-Ryvion-Receipt-CID"])

Streaming with ghost tokens

Opt into v8 stream

Provisional / commit / rollback events, one SSE channel.

const stream = await fetch(
  "https://api.ryvion.ai/v1/chat/completions",
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      model: "llama-3.2-3b",
      messages: [{ role: "user", content: "go" }],
      stream: true,
      stream_mode: "v8",
    }),
  }
)

Verify a receipt CID

Resolve and check the seal

Public endpoint, no key required. Ed25519 over RYV1 fields.

curl https://api.ryvion.ai/v8/receipts/\
ryv1:sha256:9c1e4d7f…

# → { "cid": "…", "node": "…",
#     "model": "llama-3.2-3b",
#     "signature": "…", "verified": true }

API surface

Everything you can call.

The OpenAI surface for inference. The V8 surface for receipts and network telemetry. Public endpoints don’t need a key.

MethodPathDescriptionAuth
POST/v1/chat/completionsOpenAI-compatible chat. Streaming + non-streaming.API key
POST/v1/embeddingsVector embeddings for retrieval and search.API key
GET/v1/modelsList models available to the workspace.API key
GET/v8/receipts/{cid}Resolve a content-addressed receipt.Public
GET/v8/receipts/recentTail of the network's receipt feed.Public
GET/v8/network/summaryLive TPS, online nodes, regional split.Public
GET/v8/reputation/summaryOperator reputation and FuzzyTrace agreement scores.Public

Stream mode v8

Provisional → commit → finalize.

Pass stream_mode="v8" to receive speculative tokens with their commit / rollback lineage. Render ghost tokens at 55% opacity, snap on commit, wipe on rollback.

SSE over HTTP/1.1 + HTTP/2
token.provisionalSSE event

A draft token from the speculative drafter. Render in ghost state — it may be rolled back.

{
  "event": "token.provisional",
  "id": 187,
  "text": " sat",
  "draft_node": "node_de_amd_7900xtx",
  "ts_ms": 14
}
token.commitSSE event

Target model verified the draft. Snap from ghost → solid in the UI.

{
  "event": "token.commit",
  "id": 187,
  "logprob": -0.014
}
token.rollbackSSE event

Target rejected the draft. Wipe the provisional token to the right; the next provisional comes from the left.

{
  "event": "token.rollback",
  "from_id": 187,
  "reason": "logprob_below_threshold"
}
receipt.boundSSE event

Partial receipt CID committed for the segment so far. Multiple bindings per stream — each is independently verifiable.

{
  "event": "receipt.bound",
  "cid": "ryv1:sha256:9c1e4d7f…",
  "segment_end": 187
}
token.finalizeSSE event

Stream is complete. Final receipt CID is sealed into the response trailer.

{
  "event": "token.finalize",
  "final_cid": "ryv1:sha256:bf02a1…",
  "tokens_committed": 312,
  "tokens_rolled_back": 14
}

Receipts

One header, full lineage.

Every response carries X-Ryvion-Receipt-CID. Hit the public verifier with that CID and you get the operator key, model id, signed token counts, and the speculative draft history if you streamed.

  • Ed25519 over RYV1: job_id, node_pk, result_hash, metering_units.
  • Content-addressed CID is reproducible — anyone can recompute the digest.
  • No extra request — the receipt is bound at finalize time.
Response headers
# Every response — streaming or batch — sets:
X-Ryvion-Receipt-CID: ryv1:sha256:9c1e4d7f8a2b…
X-Ryvion-Node-ID: node_de_amd_7900xtx
X-Ryvion-Model: llama-3.2-3b
X-Ryvion-Tokens-Input: 14
X-Ryvion-Tokens-Output: 312

# Resolve the lineage:
curl https://api.ryvion.ai/v8/receipts/ryv1:sha256:9c1e4d7f8a2b…

SDK compatible

No new SDK to learn.

Any client that speaks the OpenAI chat API speaks Ryvion. Set the base URL, set the key, you’re done.

  • OpenAI Python SDK

    Drop-in.

    Drop-in
  • OpenAI Node.js SDK

    Drop-in.

    Drop-in
  • Vercel AI SDK

    Use the OpenAI provider with custom baseUrl.

    Drop-in
  • LangChain

    ChatOpenAI with openai_api_base override.

    Drop-in
  • LlamaIndex

    OpenAI LLM with api_base override.

    Drop-in
  • LiteLLM

    Set OPENAI_API_BASE.

    Drop-in

Build now

Get a key, send a request, see the CID.