QuReDec Public API
Programmatic access to the QuReDec decision-brief engine. Same engine the web app uses; same per-user credit accounting.
Base URL: https://quredec.com
Quick Start (≈ 5 minutes)
- Sign in at https://quredec.com/auth/login.
- Generate a key at https://quredec.com/account → API Keys → Generate new key. Copy the
qrd_live_…token shown in the modal — it is displayed exactly once. - Submit a question from any terminal:
bash
curl -sS -X POST https://quredec.com/api/v1/brief \
-H "Authorization: Bearer qrd_live_YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"question":"Should we adopt parametric release for our terminal sterilization line?"}'
- Poll the
status_urlevery 30 s untilstatusiscompletedorpartial(typically 2–5 min):
bash
curl -sS -H "Authorization: Bearer qrd_live_YOUR_TOKEN" \
https://quredec.com/api/v1/brief/THE_BRIEF_RUN_ID
The terminal-status response contains the full structured brief — recommendation, confidence, key facts with citation IDs, risks, citations, and a public_share_url you can hand to anyone.
Python (with httpx)
import os, time, httpx
API = "https://quredec.com"
KEY = os.environ["QUREDEC_API_KEY"]
H = {"Authorization": f"Bearer {KEY}"}
# Submit
r = httpx.post(f"{API}/api/v1/brief",
headers=H,
json={"question": "Should we ship the new auth flow this sprint?"},
timeout=30.0)
r.raise_for_status()
run_id = r.json()["brief_run_id"]
print("queued:", run_id)
# Poll
while True:
s = httpx.get(f"{API}/api/v1/brief/{run_id}", headers=H, timeout=30.0).json()
if s["status"] in {"completed", "partial", "failed"}:
break
print(f"{s['status']}: {s['progress']}%")
time.sleep(15)
print("recommendation:", s["brief"]["recommendation"])
print("confidence: ", s["brief"]["confidence"])
print("share URL: ", s["public_share_url"])
Node / TypeScript
const KEY = process.env.QUREDEC_API_KEY!;
const H = { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" };
const submit = await fetch("https://quredec.com/api/v1/brief", {
method: "POST",
headers: H,
body: JSON.stringify({ question: "Should we migrate our DB to Postgres 16?" }),
});
const { brief_run_id } = await submit.json();
while (true) {
const r = await fetch(`https://quredec.com/api/v1/brief/${brief_run_id}`, { headers: H });
const s = await r.json();
if (["completed", "partial", "failed"].includes(s.status)) {
console.log(s.brief?.recommendation);
break;
}
await new Promise((res) => setTimeout(res, 15000));
}
Authentication
Every request authenticates with a per-user API key sent in the
Authorization header as a Bearer token:
Authorization: Bearer qrd_live_<random-suffix>
Generate keys at https://quredec.com/account. Each key is shown to you exactly once at creation — copy it into a password manager immediately. The server stores only a bcrypt hash and a short prefix; if you lose the token, revoke it from the account page and create a new one.
Token formats:
| Prefix | Usage |
|---|---|
qrd_live_… |
Production traffic. Charges credits. |
qrd_test_… |
Sandbox tag. Same rules — credits still consumed; format is for your bookkeeping. |
Keep your token secret. Anyone who has it can spend your credits.
Credits
Each successful brief submission consumes exactly 1 credit from the authenticated user, identical to a brief generated through the web app. Credit balance and tier are visible on the account page.
If your balance is zero, brief submissions return 402 Payment Required.
Top up your account to continue.
Endpoints
POST /api/v1/brief — submit a decision question
Submit a question and queue a brief. The brief is generated asynchronously;
poll the status URL until status == "completed".
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
question |
string | yes | The decision question. Minimum 10 characters. |
links |
string[] | no | Up to 10 URLs to use as evidence (papers, articles, transcripts). |
mode |
"A"|"B"|"C" | no | Pipeline mode. Defaults to B. Most callers should leave unset. |
template_key |
string | no | Domain template, e.g. pharma_process_change. Defaults to default. |
Response 200
{
"brief_run_id": "f3a1...e7",
"status": "queued",
"status_url": "/api/v1/brief/f3a1...e7",
"public_share_url": "https://quredec.com/shared/brief/f3a1...e7/9b21...",
"credits_remaining": 29
}
Example
curl -sS -X POST https://quredec.com/api/v1/brief \
-H "Authorization: Bearer qrd_live_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"question":"Should we adopt parametric release for our sterilization line?"}'
GET /api/v1/brief/{brief_run_id} — poll status / fetch brief
Returns the current status. Once status is completed (or partial if
some evidence layers timed out), the response also includes the structured
brief.
Response 200 (in progress)
{
"brief_run_id": "f3a1...e7",
"status": "running",
"progress": 42,
"status_url": "/api/v1/brief/f3a1...e7",
"public_share_url": "https://quredec.com/shared/brief/f3a1...e7/9b21...",
"created_at": "2026-04-27T15:02:18+00:00"
}
Response 200 (completed)
{
"brief_run_id": "f3a1...e7",
"status": "completed",
"progress": 100,
"status_url": "/api/v1/brief/f3a1...e7",
"public_share_url": "https://quredec.com/shared/brief/f3a1...e7/9b21...",
"created_at": "2026-04-27T15:02:18+00:00",
"brief": {
"executive_summary": "Parametric release is feasible if process capability ...",
"recommendation": "Proceed with a 6-month qualification trial",
"confidence": 0.74,
"key_facts": [
{"text": "ISO 14937 permits parametric release...", "citation_ids": ["1", "3"]}
],
"implications": [
{"text": "Cost reduction of ~$120K/yr...", "citation_ids": ["2"]}
],
"actions": [
{"text": "Run a 90-day capability study...", "effort": "medium", "impact": "high"}
],
"risks": [
{"text": "FDA may require additional validation...", "severity": "medium", "citation_ids": ["1"]}
],
"citations": [
{"citation_id": "1", "title": "FDA guidance ...", "url": "https://fda.gov/...", "source_type": "web_article"}
]
}
}
Example
curl -sS https://quredec.com/api/v1/brief/f3a1...e7 \
-H "Authorization: Bearer qrd_live_xxxxxxxxxxxx"
Polling cadence: brief generation typically takes 2–5 minutes. Poll every 15–30 seconds, with exponential back-off if you hit the 60 req/min/IP rate limit.
GET /api/v1/brief — list your recent briefs
| Query param | Type | Default | Notes |
|---|---|---|---|
limit |
int | 20 | 1–100. |
Response 200
{
"items": [
{
"brief_run_id": "f3a1...e7",
"status": "completed",
"progress": 100,
"status_url": "/api/v1/brief/f3a1...e7",
"public_share_url": "https://quredec.com/shared/brief/f3a1...e7/9b21...",
"created_at": "2026-04-27T15:02:18+00:00"
}
],
"count": 1
}
Example
curl -sS "https://quredec.com/api/v1/brief?limit=5" \
-H "Authorization: Bearer qrd_live_xxxxxxxxxxxx"
Use from Claude Desktop / Claude Code / Cursor (MCP)
QuReDec ships a Model Context Protocol server, quredec-mcp, that turns
the API above into three tools your AI assistant can call directly:
| Tool | What it does |
|---|---|
decision_brief |
Submit a question and (by default) wait for the brief |
get_brief_status |
Poll a previously-submitted brief by id |
list_recent_briefs |
List your recent briefs |
Install the MCP server and point your AI client at it.
Install
pip install quredec-mcp
(Source: https://github.com/Advanced-Binary-Operations/QuReDec_MCP.)
Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json
(macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"quredec": {
"command": "quredec-mcp",
"env": {
"QUREDEC_API_KEY": "qrd_live_YOUR_TOKEN"
}
}
}
}
Restart Claude Desktop. In a new conversation, ask:
Use the
decision_brieftool to evaluate "Should I migrate from Stripe to LemonSqueezy?"
Claude will call the tool, wait 2–5 min, and reply with the structured brief inline.
Claude Code (CLI)
Add to ~/.claude/mcp_servers.json:
{
"mcpServers": {
"quredec": {
"command": "quredec-mcp",
"env": {
"QUREDEC_API_KEY": "qrd_live_YOUR_TOKEN"
}
}
}
}
Then run claude and use the /mcp command to confirm quredec is connected; decision_brief is now callable in any session.
Cursor
In Settings → Features → MCP Servers, add:
| Field | Value |
|---|---|
| Name | quredec |
| Command | quredec-mcp |
Env: QUREDEC_API_KEY |
qrd_live_YOUR_TOKEN |
Cursor's agent can now request a decision brief mid-conversation.
Direct from Python (no MCP)
If you don't want a long-running MCP server, the Python snippet in Quick Start above is the same path — it calls the same endpoints.
Sharing a brief
Every brief response includes a public_share_url — a read-only HTML view
anyone with the link can open. The URL is bound to the brief id by an
HMAC, so it cannot be guessed from the brief id alone.
To revoke all share URLs at once, rotate the server-side share secret (operator-side action — contact support).
Errors
All errors return JSON with an error code and a human-readable message.
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_json |
Body could not be parsed as JSON. |
| 400 | invalid_body |
Body parsed but is not a JSON object. |
| 400 | invalid_question |
question missing or shorter than 10 characters. |
| 400 | invalid_links |
links is not an array of strings. |
| 401 | unauthorized |
Missing, malformed, or revoked Authorization header. |
| 402 | no_credits |
Authenticated user has no credits remaining this cycle. |
| 404 | not_found |
brief_run_id does not belong to the caller (or doesn't exist). |
| 429 | (rate-limit JSON) | More than 60 requests per minute from your IP. |
| 500 | credit_check_failed |
Internal error checking credits — retry. |
| 503 | feature_disabled |
Brief generation is currently disabled by the operator. |
401 responses include WWW-Authenticate: Bearer realm="QuReDec API".
Limits
- Rate limit: 60 requests / minute / IP. Applies to all
/api/v1/*. - Per-user keys: at most 20 active (non-revoked) keys per account.
- Brief size: up to 10 user-supplied URLs per request. Beyond that, add the rest as follow-up briefs.
Versioning
This document describes API v1. Breaking changes will ship under a new
prefix (/api/v2/...). Additive changes — new fields on existing
responses, new optional request fields — may land without notice; client
code MUST tolerate unknown fields.