Skip to main content

Dracon AI API — docs

For Chrome extension authors. One API. One key. Pay only for what you use.

AI API

Get a key

Sign in at /auth/login with a magic link, then create an API key at /dashboard/api-keys. The key is prefixed with drn_.

Make your first call in 60 seconds

curl -X POST https://dracon.uk/api/v1/ai/chat/completions \
  -H "x-api-key: drn_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"messages":[{"role":"user","content":"Hello"}]}'

Get a key

Endpoint reference

MethodPathWhat it does
POST/api/v1/ai/chat/completionsSend messages; receive a streamed or non-streamed completion.
POST/api/v1/auth/email-linkRequest a magic-link sign-in email.
GET/api/v1/auth/api-keysList your API keys.
POST/api/v1/auth/api-keysCreate a new API key (scope=ai).
DELETE/api/v1/auth/api-keys/{id}Revoke a key.
GET/api/v1/meCurrent profile (requires session cookie or x-api-key).
POST/api/v1/billing/checkoutStart a Paddle checkout for a plan.
POST/api/v1/webhooks/paddlePaddle webhook receiver (server-side).

Auth

Every request must include the x-api-key header. Example:

x-api-key: drn_YOUR_KEY

For dashboard sessions (browser cookie auth), the same x-api-key header is also accepted. There is no OAuth flow for the AI API — the key is the credential.

Request shape (chat/completions)

{
  "messages": [
    { "role": "system", "content": "You are a helpful assistant." },
    { "role": "user",   "content": "Summarize the page." }
  ],
  "lane": "free",          // optional: free | omega (default: free)
  "stream": false,         // optional: true for SSE streaming
  "model": "auto"          // optional: provider-routed or explicit model slug
}

Response shape (non-streamed)

{
  "id": "chatcmpl-...",
  "object": "chat.completion",
  "created": 1718000000,
  "model": "auto",
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "..." },
      "finish_reason": "stop"
    }
  ],
  "usage": { "prompt_tokens": 12, "completion_tokens": 87, "total_tokens": 99 }
}

Lanes

  • free — 5 free lanes, rate-limited per provider, no Paddle billing. Routes across 5 rotating providers from the 38 in the catalog.
  • omega — Dracon Omega subscribers. Higher rate limits, dedicated model selection, metered billing via Paddle. Currently gated by BILLING_OMEGA_ENABLED=false pre-go-live.

Error catalog

CodeNameMeaning
400bad_requestMalformed JSON, missing fields, or messages array empty.
401unauthorizedMissing or invalid x-api-key. Check that the key was created and is in chrome.storage.sync.
403forbiddenAPI key valid but the requested lane is not enabled for this key.
429rate_limitedFree-tier rate limit hit. Wait and retry, or upgrade to Dracon Omega.
500internal_errorUpstream provider error or Dracon internal error. Retry with backoff.
502bad_gatewayAll upstream providers in the lane failed. Retry.
503unavailableLane is disabled (BILLING_OMEGA_ENABLED=false) or all providers in maintenance.

Rate limits

Free lane: per-provider limits inherited from the upstream free tier (typically 30 RPM and 1K–14.4K req/day). Omega lane: configurable in BILLING_OMEGA_RATE_LIMIT_RPM; default 600 RPM.

429 responses include a retry_after_ms field. Exponential backoff in the extension's background.js is recommended.

Chrome extension example (copy-paste)

A minimal Manifest V3 extension that prompts the user, sends it to the Dracon AI API, and shows the reply. Drop the four files into a folder, load it as an unpacked extension in chrome://extensions, and set the API key in chrome.storage.sync via the extension's options page (or the snippet at the bottom).

manifest.json

{
  "manifest_version": 3,
  "name": "My Dracon Extension",
  "version": "1.0.0",
  "permissions": ["storage", "scripting"],
  "host_permissions": ["https://dracon.uk/*"],
  "background": { "service_worker": "background.js" },
  "action": { "default_popup": "popup.html" }
}

background.js

// Read the API key from chrome.storage.sync (set on first run
// via options.js or by pasting it in the extension's options page).
const API_KEY = await chrome.storage.sync.get('dracon_api_key');
const API_URL = 'https://dracon.uk/api/v1/ai/chat/completions';

chrome.runtime.onMessage.addListener((msg, _sender, sendResponse) => {
  if (msg.type !== 'dracon_chat') return false;
  fetch(API_URL, {
    method: 'POST',
    headers: {
      'x-api-key': API_KEY.dracon_api_key,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      messages: [{ role: 'user', content: msg.prompt }],
      lane: msg.lane || 'free'
    })
  })
    .then(r => r.json())
    .then(data => sendResponse({ ok: true, data }))
    .catch(err => sendResponse({ ok: false, error: String(err) }));
  return true; // keep the message channel open for the async response
});

popup.html

<!doctype html>
<html>
  <body style="min-width:300px">
    <h3>Dracon AI</h3>
    <textarea id="prompt" rows="4" style="width:100%"></textarea>
    <button id="ask">Ask</button>
    <pre id="out"></pre>
    <script src="popup.js"></script>
  </body>
</html>

popup.js

document.getElementById('ask').addEventListener('click', async () => {
  const prompt = document.getElementById('prompt').value;
  const out = document.getElementById('out');
  out.textContent = '...';
  const res = await chrome.runtime.sendMessage({
    type: 'dracon_chat',
    prompt,
    lane: 'free'
  });
  out.textContent = res.ok
    ? (res.data.choices?.[0]?.message?.content || JSON.stringify(res.data))
    : ('Error: ' + res.error);
});

Set the API key once (one-time, from the devtools console of the extension's options page)

chrome.storage.sync.set({ dracon_api_key: 'drn_YOUR_KEY' });

Products in the catalog

  • Azumi — Ship Rust web products that can't break silently in production.
  • Tiles — Stop maintaining shell scripts that only you understand.
  • SamAI — Automate browser tasks without writing brittle scripts.
  • Filler — Never fill the same form twice.

AI providers (38)

The free lane rotates across 5 of these at a time. The full list is in tools/specta-data/ai-providers-catalog.json.

  • Groq free tier 30 RPM, 14.4K req/day
  • DeepInfra free tier 200 concurrent requests
  • Hyperbolic free tier $1 free credits
  • NVIDIA NIM free tier ~40 RPM
  • Cloudflare Workers AI free tier 10K neurons/day, 300 RPM
  • Google AI Studio free tier 15–60 RPM, 250–1.5K req/day
  • SambaNova free tier Generous dev tier
  • SiliconFlow free tier 100 req/day + $1 free credits
  • Scaleway free tier 1M free tokens (permanent)
  • Alibaba DashScope free tier 1M free tokens/model (90 days)
  • OVHcloud AI Endpoints free tier 2 req/min/IP free, 400 RPM with key
  • Replicate free tier 6 req/min free, 3K RPM with payment
  • Hugging Face free tier ~$0.10/month free credits
  • Perplexity free tier ~50 RPM (tiered by spend)
  • Mistral La Plateforme free tier 1 req/s, 1B tokens/month
  • Codestral free tier 30 RPM, 2K req/day
  • Cerebras free tier 1M tokens/day
  • Kilo Code free tier 200 req/hr for anonymous users
  • RunPod free tier Varies by plan
  • Nous Portal free tier Ultra: 1,600 RPM
  • Z.AI GLM free tier Varies by plan
  • BytePlus ModelArk free tier 500K free tokens per model
  • MiniMax free tier Varies by plan
  • Venice free tier Varies by plan
  • LLM Gateway free tier Depends on upstream provider
  • Synthetic free tier Varies by plan
  • Mimo free tier
  • Anthropic Varies by usage tier
  • Fireworks AI free tier High rate limits with postpaid billing
  • GitHub Models free tier Free tier limits, pay per token unit beyond
  • Ollama free tier Local: unlimited. Cloud: 1 concurrent model (Free)
  • Baidu Qianfan Varies by tier
  • Kimi free tier Varies by usage tier
  • StepFun free tier Varies by plan
  • Chutes Varies by model
  • CrofAI free tier 500 requests/day (Hobby)
  • OpenCode $12/5hr, $30/week, $60/month
  • AI Router free tier Free: 1K req/mo, Starter: 20K req/mo, Pro: 100K req/mo