Chat. Vision. Embeddings. Images. Video. Voice. Search. Structured extraction. One API surface, one key, one model naming convention.
API keys aren't self-serve yet. We're finalising sovereign account primitives (mnemonic + wallet) before opening registrations. Join the Signal group to request a test key and get updates when self-serve opens.
Three request-shape families. Every endpoint accepts Authorization: Bearer drg_... and JSON. Model names are shared across all three.
DragonFire agents are .ai personas: a LoRA tuned on a small dense base, owned by a creator, addressable by a memorable name. Fires the same POST /v1/chat/completions shape — just set "model": "<agent-id>". Router picks a hot provider when one is serving, otherwise falls back to the base-family cloud (and always settles the earnings under the agent name so creator attribution holds).
GET /v1/agents…curl https://api.dragonfireai.org/v1/agents (public, no auth). More agents publish as creators register.
Wire-compat tier for OpenAI/Anthropic SDKs. Every entry maps to a base chat model. Set "model": "<id>" in the request body. The list is grouped by modality (chat, embeddings, image, video, speech, transcription, vision, search) and refreshed on every page load.
GET /v1/models…model_not_found during closed alpha, the name may have drifted — always cross-check against the live grid above (or curl GET /v1/models).
Copy-paste ready. All three families share the same drg_ Bearer — only the wire shape changes.
curl https://api.dragonfireai.org/v1/chat/completions \
-H "Authorization: Bearer drg_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "dragon-gpt",
"messages": [{"role": "user", "content": "Hello, forge master."}]
}'
curl https://api.dragonfireai.org/v1/chat/completions \
-H "Authorization: Bearer drg_xxxxx" \
-H "Content-Type: application/json" \
--no-buffer \
-d '{
"model": "dragon-gpt",
"stream": true,
"messages": [{"role": "user", "content": "Tell me a short story."}]
}'
# Response: text/event-stream, one JSON chunk per line, terminated by "data: [DONE]"
curl https://api.dragonfireai.org/v1/messages \
-H "Authorization: Bearer drg_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "dragon-gpt",
"max_tokens": 512,
"messages": [{"role": "user", "content": "Hello, forge master."}]
}'
curl https://api.dragonfireai.org/v1/embeddings \
-H "Authorization: Bearer drg_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "dragon-embed",
"input": ["forge master", "the anvil sings", "iron will bends"]
}'
curl https://api.dragonfireai.org/v1/extract \
-H "Authorization: Bearer drg_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"content": "The Ember 300 sedan launches at £24,990 and ships in Q3.",
"schema": {
"type": "object",
"properties": {
"product_name": {"type": "string"},
"price_gbp": {"type": "number"},
"release_quarter": {"type": "string"}
},
"required": ["product_name", "price_gbp", "release_quarter"]
}
}'
curl https://api.dragonfireai.org/v1/web/search \
-H "Authorization: Bearer drg_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"q": "distributed systems consensus overview",
"num_results": 5
}'
curl https://api.dragonfireai.org/v1/images/generations \
-H "Authorization: Bearer drg_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "dragon-image",
"prompt": "a bronze dragon curled around a lit forge, dusk light",
"size": "1024x1024"
}'
curl https://api.dragonfireai.org/v1/videos/generations \
-H "Authorization: Bearer drg_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "dragon-reel",
"image_url": "https://example.com/still.jpg",
"prompt": "gentle camera pan, sparks bloom",
"duration_s": 4
}'
curl https://api.dragonfireai.org/v1/audio/speech \
-H "Authorization: Bearer drg_xxxxx" \
-H "Content-Type: application/json" \
-o speech.mp3 \
-d '{
"model": "dragon-tts",
"voice": "george",
"input": "The dragon rises at dawn."
}'
curl https://api.dragonfireai.org/v1/audio/speech \
-H "Authorization: Bearer drg_xxxxx" \
-H "Content-Type: application/json" \
-o speech.mp3 \
-d '{
"model": "dragon-voice",
"voice": "george",
"emotion": "warm",
"input": "The dragon rises at dawn."
}'
curl https://api.dragonfireai.org/v1/audio/transcriptions \
-H "Authorization: Bearer drg_xxxxx" \
-F "[email protected]" \
-F "model=dragon-stt"
import requests
resp = requests.post(
"https://api.dragonfireai.org/v1/chat/completions",
headers={"Authorization": "Bearer drg_xxxxx"},
json={
"model": "dragon-gpt",
"messages": [{"role": "user", "content": "Hello, forge master."}],
},
timeout=60,
)
print(resp.json()["choices"][0]["message"]["content"])
const resp = await fetch("https://api.dragonfireai.org/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": "Bearer drg_xxxxx",
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "dragon-gpt",
messages: [{ role: "user", content: "Hello, forge master." }],
}),
});
const data = await resp.json();
console.log(data.choices[0].message.content);
package main
import (
"bytes"
"fmt"
"io"
"net/http"
)
func main() {
body := []byte(`{"model":"dragon-gpt","messages":[{"role":"user","content":"Hello, forge master."}]}`)
req, _ := http.NewRequest("POST", "https://api.dragonfireai.org/v1/chat/completions", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer drg_xxxxx")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(string(out))
}
Every non-2xx response is JSON with the shape {"error": {"code": "...", "message": "..."}}. Log the x-request-id header if you need to report one.
| Status | Error code | What it means |
|---|---|---|
| 400 | bad_request | Malformed JSON body or missing required field |
| 400 | model_not_found | The model value isn't in /v1/models and has no alias — never billed upstream |
| 401 | invalid_api_key | Bearer missing, wrong format, or unknown to the registry |
| 402 | insufficient_balance | Wallet balance won't cover the estimated call cost |
| 402 | quota_exceeded_monthly | Key hit its monthly DC cap; response body includes the reset unix timestamp |
| 403 | scope_denied | Key isn't scoped for this endpoint or model |
| 429 | rate_limited | Too many requests inside the sliding window — back off and retry |
| 502 | upstream_unreachable | Route to the model provider failed — retry safely, no billing |
| 504 | upstream_timeout | Provider held the connection too long — retry safely, no billing |
4xx should not be retried without a code change. 5xx (502 / 504) is safe to retry — no wallet debit lands until the upstream returns a usable response, so a timeout costs nothing.
Self-serve isn't open yet — we're finalising sovereign account primitives (mnemonic + wallet) before we accept registrations. Join the Signal group to request a test key, share feedback, and get pinged when the front door opens.
Join the Signal Group