Download static/docs.html from apiarium/labs: direct link, hf CLI and curl.
- Browser
- Download file 14.1 kB
-
https://huggingface.co/spaces/apiarium/labs/resolve/main/static/docs.html
- Command line
-
hf download hf://spaces/apiarium/labs/static/docs.html
-
curl -L -o docs.html https://huggingface.co/spaces/apiarium/labs/resolve/main/static/docs.html
14.1 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| <meta name="theme-color" content="#FFD6E8" /> | |
| <!-- CRITICAL: paint the dawn sky on the first byte, before any external CSS/JS | |
| loads. background-attachment:fixed locks it to the viewport AND is the only | |
| background iOS Safari renders in the overscroll/rubber-band region — so | |
| scrolling never exposes a bare strip. Literal hex because tokens.css | |
| hasn't loaded yet. --> | |
| <style> | |
| html{background:linear-gradient(180deg,#E8E0FF 0%,#FFD6E8 52%,#FFE5D9 100%) fixed;background-color:#FFD6E8;} | |
| </style> | |
| <title>Docs — DreamRouter</title> | |
| <meta name="description" content="DreamRouter API reference: authenticate, list models, send chat completions, stream responses, and handle errors across one OpenAI-compatible endpoint." /> | |
| <link rel="canonical" href="https://apiarium-labs.hf.space/docs.html" /> | |
| <meta property="og:type" content="website" /> | |
| <meta property="og:title" content="DreamRouter Docs" /> | |
| <meta property="og:description" content="One OpenAI-compatible endpoint. Auth, models, chat, streaming, errors." /> | |
| <link rel="preconnect" href="https://fonts.googleapis.com" /> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> | |
| <link href="https://fonts.googleapis.com/css2?family=Comfortaa:wght@400;500;700&family=Nunito:wght@400;600;700;800&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet" /> | |
| <script src="https://unpkg.com/lenis@1.1.13/dist/lenis.min.js" defer></script> | |
| <link rel="stylesheet" href="css/tokens.css?v=20260620b" /> | |
| <link rel="stylesheet" href="css/base.css?v=20260620b" /> | |
| <link rel="stylesheet" href="css/scene.css?v=20260620b" /> | |
| <link rel="stylesheet" href="css/nav.css?v=20260620b" /> | |
| <link rel="stylesheet" href="css/sections.css?v=20260620b" /> | |
| <link rel="stylesheet" href="css/docs.css?v=20260620b" /> | |
| </head> | |
| <body data-page="docs"> | |
| <!-- dream overlays --> | |
| <div class="blur-overlay" aria-hidden="true"></div> | |
| <div class="grain-overlay" aria-hidden="true"></div> | |
| <!-- a lighter scene for inner pages: far clouds + moon only (no whale) --> | |
| <div class="scene" aria-hidden="true"> | |
| <div class="layer layer-far-clouds" data-speed="0.06" data-mouse="6"> | |
| <svg class="cloud-far c1" viewBox="0 0 200 100"><use href="#cloud"/></svg> | |
| <svg class="cloud-far c3" viewBox="0 0 200 100"><use href="#cloud"/></svg> | |
| </div> | |
| <div class="layer layer-moon" data-speed="0.10" data-mouse="10"> | |
| <div class="moon"><span class="moon-disc"></span></div> | |
| </div> | |
| </div> | |
| <!-- shared nav + footer --> | |
| <div data-site-nav></div> | |
| <main id="main"> | |
| <header class="doc-hero"> | |
| <div class="container"> | |
| <h1 data-split>docs</h1> | |
| <p data-reveal>One OpenAI-compatible endpoint. Authenticate, send a request, stream the reply.</p> | |
| </div> | |
| </header> | |
| <div class="container"> | |
| <div class="doc-layout"> | |
| <!-- sticky TOC --> | |
| <aside class="doc-toc" aria-label="On this page"> | |
| <h2>On this page</h2> | |
| <ul> | |
| <li><a href="#quickstart">Quickstart</a></li> | |
| <li><a href="#auth">Authentication</a></li> | |
| <li><a href="#base-url">Base URL</a></li> | |
| <li><a href="#models">List models</a></li> | |
| <li><a href="#chat">Chat completions</a></li> | |
| <li><a href="#streaming">Streaming</a></li> | |
| <li><a href="#parameters">Parameters</a></li> | |
| <li><a href="#errors">Errors</a></li> | |
| <li><a href="#retries">Retries & limits</a></li> | |
| </ul> | |
| </aside> | |
| <!-- content --> | |
| <div class="doc-content"> | |
| <section id="quickstart"> | |
| <h2>Quickstart</h2> | |
| <p data-reveal>Send a standard OpenAI-style chat completion. Swap the base URL and the model name — that's the whole integration.</p> | |
| <div class="bezel" data-code-tabs> | |
| <div class="code-tabs" role="tablist"> | |
| <button data-tab="curl" aria-selected="true">cURL</button> | |
| <button data-tab="py" aria-selected="false">Python</button> | |
| <button data-tab="js" aria-selected="false">JavaScript</button> | |
| </div> | |
| <div class="code-wrap"> | |
| <pre class="code-panel" data-tab="curl" data-active="true"><span class="tok-com"># one endpoint, every model</span> | |
| curl https://apiarium-labs.hf.space/v1/chat/completions \ | |
| -H <span class="tok-str">"Authorization: Bearer $DREAMROUTER_KEY"</span> \ | |
| -H <span class="tok-str">"Content-Type: application/json"</span> \ | |
| -d <span class="tok-str">'{ | |
| "model": "claude-opus-4.8", | |
| "messages": [{"role":"user","content":"Hello, whale."}] | |
| }'</span></pre> | |
| <pre class="code-panel" data-tab="py"><span class="tok-key">from</span> openai <span class="tok-key">import</span> OpenAI | |
| client = OpenAI( | |
| base_url=<span class="tok-str">"https://apiarium-labs.hf.space/v1"</span>, | |
| api_key=<span class="tok-str">"dr_u_..."</span>, <span class="tok-com"># your personal key from the dashboard</span> | |
| ) | |
| resp = client.chat.completions.create( | |
| model=<span class="tok-str">"claude-opus-4.8"</span>, | |
| messages=[{<span class="tok-str">"role"</span>: <span class="tok-str">"user"</span>, <span class="tok-str">"content"</span>: <span class="tok-str">"Hello, whale."</span>}], | |
| ) | |
| <span class="tok-key">print</span>(resp.choices[<span class="tok-num">0</span>].message.content)</pre> | |
| <pre class="code-panel" data-tab="js"><span class="tok-key">import</span> OpenAI <span class="tok-key">from</span> <span class="tok-str">"openai"</span>; | |
| <span class="tok-key">const</span> client = <span class="tok-key">new</span> OpenAI({ | |
| baseURL: <span class="tok-str">"https://apiarium-labs.hf.space/v1"</span>, | |
| apiKey: <span class="tok-str">"dr_u_..."</span>, <span class="tok-com">// your personal key from the dashboard</span> | |
| }); | |
| <span class="tok-key">const</span> resp = <span class="tok-key">await</span> client.chat.completions.create({ | |
| model: <span class="tok-str">"claude-opus-4.8"</span>, | |
| messages: [{ role: <span class="tok-str">"user"</span>, content: <span class="tok-str">"Hello, whale."</span> }], | |
| }); | |
| console.log(resp.choices[<span class="tok-num">0</span>].message.content);</pre> | |
| </div> | |
| </div> | |
| <div class="callout note"> | |
| <span class="ico">i</span> | |
| <div>The router rewrites your model name to each target's upstream id automatically. You send one name; it resolves to a healthy pool behind the scenes. <a href="models.html">Browse the 374 available models →</a></div> | |
| </div> | |
| </section> | |
| <section id="auth"> | |
| <h2>Authentication</h2> | |
| <p data-reveal>Proxy endpoints require a Bearer token in the <code>Authorization</code> header.</p> | |
| <pre class="code-panel" style="background:var(--ink);padding:1rem 1.2rem;border-radius:14px;"><span class="tok-key">Authorization</span>: Bearer sk-your-DreamRouter-key</pre> | |
| <div class="callout warn"> | |
| <span class="ico">!</span> | |
| <div>Public endpoints (<code>/</code>, <code>/health</code>, <code>/v1/models</code>) need no auth. Everything else returns <code>403</code> without a valid key. An optional IP allowlist can further lock access.</div> | |
| </div> | |
| </section> | |
| <section id="base-url"> | |
| <h2>Base URL</h2> | |
| <p data-reveal>All requests are made against:</p> | |
| <pre class="code-panel" style="background:var(--ink);padding:1rem 1.2rem;border-radius:14px;">https://apiarium-labs.hf.space/v1</pre> | |
| <p>Point any OpenAI-compatible client at this base URL and you are done.</p> | |
| </section> | |
| <section id="models"> | |
| <h2>List models</h2> | |
| <p data-reveal><code>GET /v1/models</code> returns every model the router can resolve. Public, no auth required.</p> | |
| <div class="bezel" data-code-tabs> | |
| <div class="code-tabs" role="tablist"> | |
| <button data-tab="curl" aria-selected="true">cURL</button> | |
| <button data-tab="resp" aria-selected="false">Response</button> | |
| </div> | |
| <div class="code-wrap"> | |
| <pre class="code-panel" data-tab="curl" data-active="true">curl https://apiarium-labs.hf.space/v1/models</pre> | |
| <pre class="code-panel" data-tab="resp">{ | |
| <span class="tok-key">"object"</span>: <span class="tok-str">"list"</span>, | |
| <span class="tok-key">"data"</span>: [ | |
| { <span class="tok-key">"id"</span>: <span class="tok-str">"claude-opus-4.8"</span>, <span class="tok-key">"object"</span>: <span class="tok-str">"model"</span>, <span class="tok-key">"owned_by"</span>: <span class="tok-str">"claude-subnet"</span> }, | |
| { <span class="tok-key">"id"</span>: <span class="tok-str">"deepseek-v4-pro"</span>, <span class="tok-key">"object"</span>: <span class="tok-str">"model"</span>, <span class="tok-key">"owned_by"</span>: <span class="tok-str">"deepseek"</span> } | |
| <span class="tok-com">// ...374 models</span> | |
| ] | |
| }</pre> | |
| </div> | |
| </div> | |
| </section> | |
| <section id="chat"> | |
| <h2>Chat completions</h2> | |
| <p data-reveal><code>POST /v1/chat/completions</code> accepts the standard OpenAI request body. The <code>model</code> field selects the pool; everything else passes through.</p> | |
| <table class="doc-table"> | |
| <thead><tr><th>Field</th><th>Type</th><th>Notes</th></tr></thead> | |
| <tbody> | |
| <tr><td><code>model</code></td><td>string</td><td>Required. Any name from <code>/v1/models</code>.</td></tr> | |
| <tr><td><code>messages</code></td><td>array</td><td>OpenAI message format.</td></tr> | |
| <tr><td><code>stream</code></td><td>boolean</td><td>SSE stream when <code>true</code>.</td></tr> | |
| <tr><td><code>temperature</code></td><td>number</td><td>Forwarded upstream.</td></tr> | |
| <tr><td><code>max_tokens</code></td><td>number</td><td>Forwarded. GPT-5.x maps to <code>max_completion_tokens</code> automatically.</td></tr> | |
| <tr><td><code>tools</code></td><td>array</td><td>Tool/function calling supported where the upstream allows it.</td></tr> | |
| </tbody> | |
| </table> | |
| </section> | |
| <section id="streaming"> | |
| <h2>Streaming</h2> | |
| <p data-reveal>Set <code>"stream": true</code>. The router forwards the upstream SSE stream and filters non-<code>data:</code> lines so strict parsers stay happy. Each chunk is a standard <code>chat.completion.chunk</code>.</p> | |
| <div class="bezel"> | |
| <div class="code-wrap"> | |
| <pre class="code-panel" data-active="true" style="display:block;">data: {<span class="tok-key">"choices"</span>:[{<span class="tok-key">"delta"</span>:{<span class="tok-key">"content"</span>:<span class="tok-str">"Hello"</span>}}]} | |
| data: {<span class="tok-key">"choices"</span>:[{<span class="tok-key">"delta"</span>:{<span class="tok-key">"content"</span>:<span class="tok-str">", whale."</span>}}]} | |
| data: [DONE]</pre> | |
| </div> | |
| </div> | |
| </section> | |
| <section id="parameters"> | |
| <h2>Parameters</h2> | |
| <p data-reveal>Unsupported parameters are silently dropped before forwarding. The router never invents upstream behavior — it only translates model names and injects keys.</p> | |
| </section> | |
| <section id="errors"> | |
| <h2>Errors</h2> | |
| <table class="doc-table"> | |
| <thead><tr><th>Status</th><th>Meaning</th></tr></thead> | |
| <tbody> | |
| <tr><td><code>401</code></td><td>Missing or invalid bearer token.</td></tr> | |
| <tr><td><code>403</code></td><td>Endpoint blocked, or IP not on the allowlist.</td></tr> | |
| <tr><td><code>404</code></td><td>Model not found. Returned before any upstream call.</td></tr> | |
| <tr><td><code>429</code></td><td>All targets rate-limited after retries.</td></tr> | |
| <tr><td><code>502</code></td><td>Every target in the pool failed its attempts.</td></tr> | |
| <tr><td><code>503</code></td><td>Pool exhausted — every target cooling down.</td></tr> | |
| </tbody> | |
| </table> | |
| </section> | |
| <section id="retries"> | |
| <h2>Retries & limits</h2> | |
| <p data-reveal>Each request gets up to <strong>five attempts</strong>. On <code>401</code>, <code>402</code>, <code>403</code>, <code>429</code>, or <code>5xx</code>, the failing target cools for <strong>sixty seconds</strong> and the router tries the next healthy one. Cooldowns are idempotent — re-failing a target never resets its timer, so flapping endpoints recover cleanly.</p> | |
| <div class="callout note"> | |
| <span class="ico">↻</span> | |
| <div>Load is spread by a thread-safe round-robin cursor, so traffic distributes evenly across the whole pool — not hammering the first target.</div> | |
| </div> | |
| </section> | |
| </div><!-- /.doc-content --> | |
| </div><!-- /.doc-layout --> | |
| </div><!-- /.container --> | |
| <div data-site-footer></div> | |
| </main> | |
| <!-- SVG sprite (cloud symbol) --> | |
| <svg width="0" height="0" style="position:absolute" aria-hidden="true"> | |
| <symbol id="cloud" viewBox="0 0 200 100"> | |
| <path fill="currentColor" d="M44,82 C24,82 18,58 38,53 C32,32 62,26 74,42 C80,22 116,22 122,44 C142,32 168,48 158,68 C172,72 172,90 152,90 L54,90 C40,92 35,88 44,82 Z" /> | |
| </symbol> | |
| </svg> | |
| <script src="js/layout.js?v=20260620b"></script> | |
| <script src="js/motion.js?v=20260620b"></script> | |
| <script src="js/parallax.js?v=20260620b"></script> | |
| <script src="js/docs.js?v=20260620b"></script> | |
| </body> | |
| </html> | |