Qubitz API Documentation

WebSocket API endpoints for AI-powered research, chat, multi-agent architecture generation, deployment, and API key management.

Overview

The Qubitz API provides WebSocket endpoints for AI-powered research, chat, multi-agent architecture generation, deployment, and API key management. All endpoints stream real-time responses over WebSocket connections.

Base URL: wss://api.qubitz.ai


Authentication

Getting API Keys

API keys are provisioned through the Qubitz platform. Sign in at qubitz.ai and navigate to your project settings to generate keys.

There are two key scopes:

ScopePrefixEndpoints
UCTqk_uct_/research, /chat
ControlHubqk_ch_/getspec, /updatespec, /deploy, /createapikey, /deleteapikey

Authenticating Requests

Pass your API key as a query parameter when connecting:

wss://api.qubitz.ai/<endpoint>?api_key=<your_api_key>

If the key is missing, invalid, or lacks the required scope, the connection is rejected with WebSocket close code 1008.


Endpoints

POST /research

Run an AI-powered deep research pipeline on any topic. A multi-agent system performs web research, synthesizes findings, identifies AI use cases for the given company, and produces a comprehensive research report with executive summary, market analysis, and actionable recommendations. Outputs are uploaded to S3 as both Markdown and PDF, along with a scored list of AI use cases tailored to the company.

Scope: UCT

Connect: wss://api.qubitz.ai/research?api_key=qk_uct_...

Request Payload

{
  "prompt": "Latest AI Trends 2026",
  "company_name": "TestCompany",
  "company_url": "https://example.com/",
  "user_id": "user123",
  "session_id": "session456"
}
FieldTypeRequiredDescription
promptstringYesResearch topic or query
company_namestringYesCompany name for focused research
company_urlstringYesCompany website URL
user_idstringYesYour user ID
session_idstringYesSession identifier

Response Stream

Messages arrive in this general order:

1. Progress Updates

{ "type": "status", "message": "Starting multi-agent research system...", "session_id": "..." }

2. Agent Progress

{ "type": "multiagent_step", "step": "research", "message": "Researching sources...", "session_id": "..." }
{ "type": "multiagent_progress", "step": "analysis", "session_id": "..." }

3. S3 Upload Notifications

{
  "type": "s3_upload_complete",
  "file_type": "deep_research_markdown",
  "s3_url": "https://qubitz-research-reports.s3.amazonaws.com/.../report.md",
  "session_id": "..."
}

Possible file_type values: markdown, pdf, deep_research_markdown, deep_research_pdf, AI_discovery_markdown, AI_discovery_pdf, use_cases_pdf, use_cases_md

4. Use Cases

{
  "type": "use_cases_complete",
  "use_cases": [
    {
      "id": "uc_1",
      "title": "Quantum-Safe Payment Processing",
      "description": "...",
      "business_value": "...",
      "impact_score": "High",
      "implementation": "...",
      "estimated_roi": "...",
      "alignment_score": "High"
    }
  ],
  "total_use_cases": 5,
  "session_id": "..."
}

5. Completion

{
  "type": "complete",
  "project_id": "project21",
  "user_id": "user123",
  "s3_deep_research_report_url": "https://...",
  "s3_deep_research_pdf_url": "https://...",
  "s3_AI_discovery_report_url": "https://...",
  "s3_AI_discovery_pdf_url": "https://...",
  "s3_use_cases_pdf_url": "https://...",
  "s3_use_cases_md_url": "https://...",
  "all_s3_urls": {
    "deep_research_report_url": "https://...",
    "deep_research_pdf_url": "https://...",
    "AI_discovery_report_url": "https://...",
    "AI_discovery_pdf_url": "https://...",
    "use_cases_pdf_url": "https://...",
    "use_cases_md_url": "https://..."
  },
  "session_id": "..."
}

Keepalive (periodic, during long operations):

{ "type": "keepalive", "timestamp": 1710000000, "message": "Processing..." }

Error:

{ "type": "error", "error": "INVALID_QUERY", "message": "Query validation failed: ...", "session_id": "..." }

POST /chat

Have a conversational Q&A session about a previously generated research report. The AI reads the full report (from S3 or raw text) and answers follow-up questions, summarizes sections, extracts insights, or performs additional web searches when needed. Supports multi-turn conversations with session-based token tracking.

Scope: UCT

Connect: wss://api.qubitz.ai/chat?api_key=qk_uct_...

Request Payload

{
  "messages": [
    { "role": "user", "content": "Summarize the key findings from the report" }
  ],
  "s3_report_url": "https://qubitz-research-reports.s3.amazonaws.com/.../report.md",
  "user_id": "user123",
  "session_id": "session456",
  "project_id": "project21"
}
FieldTypeRequiredDescription
messagesarrayYesConversation messages (role: "user" or "assistant")
user_idstringYesYour user ID
session_idstringYesChat session identifier
s3_report_urlstringYes*S3 URL of the research report
reportstringYes*Raw markdown content of the report
project_idstringNoProject identifier
company_namestringNoCompany name context
token_limitnumberNoMax token limit (default: 250000)

*Provide either s3_report_url or report, not both.

Response Stream

1. Status

{ "type": "chat_status", "message": "Processing chat request...", "session_id": "..." }

2. Streaming Response

{ "type": "chat_chunk", "chunk": "The report highlights three key...", "is_final": false, "session_id": "..." }

Chunks arrive sequentially. Concatenate all chunk values to build the full response.

3. Completion

{
  "type": "chat_complete",
  "success": true,
  "response": {
    "metadata": {
      "tools_used": {
        "web_search": ["query1", "query2"],
        "report_generated": { "success": false }
      }
    },
    "token_usage": {
      "input_tokens": 15000,
      "output_tokens": 2000,
      "total_tokens": 17000
    }
  },
  "session_info": {
    "user_id": "user123",
    "session_id": "session456",
    "message_count": 3,
    "token_usage": {
      "input_tokens": 15000,
      "output_tokens": 2000,
      "total_tokens": 17000,
      "limit": 250000,
      "limit_reached": false
    }
  }
}

Error:

{ "type": "chat_error", "error": "TOKEN_LIMIT_EXCEEDED", "message": "...", "session_id": "..." }

POST /getspec

Generate a complete multi-agent architecture specification from a use case. Given a use case name, description, and optionally a research report for context, the AI designs an end-to-end agent system — defining each agent's role, model, system prompt, tools, and memory strategy, plus a gateway configuration for API access. The resulting spec is saved and can be refined with /updatespec or deployed with /deploy.

Scope: ControlHub

Connect: wss://api.qubitz.ai/getspec?api_key=qk_ch_...

Request Payload

{
  "user_id": "user123",
  "project_id": "project21",
  "use_case_name": "Automated Financial Research Platform",
  "use_case_description": "Investment firms conducting market research face challenges with information accuracy and research scalability.",
  "s3_uri": "https://qubitz-research-reports.s3.amazonaws.com/.../report.md"
}
FieldTypeRequiredDescription
user_idstringYesYour user ID
project_idstringYesProject identifier
use_case_namestringYesName of the use case
use_case_descriptionstringYesDetailed description of the use case
s3_uristringNoS3 URL of a research report for additional context
session_idstringNoSession identifier

Response Stream

1. Acknowledgment

{
  "type": "ack",
  "data": { "user_id": "user123", "session_id": "...", "project_id": "project21", "action": "generate", "status": "processing" }
}

2. Streaming Spec Generation

{ "type": "stream_start", "data": { "message": "Generating architecture specification...", "model": "claude-sonnet-4-5-20250929" } }
{ "type": "stream_chunk", "data": { "chunk": "Based on the use case...", "chunk_index": 0 } }
{ "type": "stream_end", "data": { "total_chunks": 42, "completion_time": 8.5 } }

3. Final Architecture

{
  "type": "architecture",
  "data": {
    "user_id": "user123",
    "project_id": "project21",
    "architecture": {
      "agents_config": {
        "research_agent": {
          "name": "Research Agent",
          "description": "Conducts market research and data gathering",
          "model": "anthropic.claude-sonnet-4-5-20250929-v1:0",
          "prompt": "You are a research agent...",
          "tools": ["web_search", "document_reader"],
          "memory": { "enabled": true, "strategies": ["summary"] }
        },
        "analysis_agent": {
          "name": "Analysis Agent",
          "description": "Analyzes gathered data...",
          "model": "anthropic.claude-sonnet-4-5-20250929-v1:0",
          "prompt": "You are an analysis agent...",
          "tools": ["calculator", "data_viz"],
          "memory": { "enabled": true, "strategies": ["summary"] }
        }
      },
      "gateway_config": { "provider": "api_gateway", "targets": [] }
    },
    "status": "pending"
  }
}

Keepalive:

{ "type": "keepalive", "data": { "message": "Processing in progress... (15s)", "elapsed_seconds": 15 } }

Error:

{ "type": "error", "data": { "error": "generation_failed", "message": "..." } }

POST /updatespec

Modify an existing multi-agent architecture spec using natural language instructions. Describe what you want to change (e.g., "add a security agent", "switch the research agent to a different model", "remove the analytics agent") and the AI will regenerate the spec with your changes applied while preserving the rest of the architecture.

Scope: ControlHub

Connect: wss://api.qubitz.ai/updatespec?api_key=qk_ch_...

Request Payload

{
  "user_id": "user123",
  "project_id": "project21",
  "user_input": "Add a security agent that validates all API calls and enforces rate limiting"
}
FieldTypeRequiredDescription
user_idstringYesYour user ID
project_idstringYesProject identifier (must have an existing spec)
user_inputstringYesNatural language description of the changes

Response Stream

Same message types as /getspec: ack → stream_start → stream_chunk → stream_end → architecture

The returned architecture contains the full updated spec.


POST /deploy

Deploy a generated multi-agent architecture to AWS as a live, production-ready service. The system generates CDK infrastructure code, pushes it to a GitHub repository, and triggers a GitHub Actions CI/CD pipeline that provisions API Gateway, Lambda, and all required AWS resources. You get a live agent_endpoint URL and a GitHub repo with the full source code.

Scope: ControlHub

Connect: wss://api.qubitz.ai/deploy?api_key=qk_ch_...

Request Payload

{
  "user_id": "user123",
  "project_id": "project21"
}
FieldTypeRequiredDescription
user_idstringYesYour user ID
project_idstringYesProject identifier (must have an approved spec)
github_usernamestringNoGitHub username to add as collaborator on the repo

Response Stream

1. Deployment Started

{
  "type": "deployment_started",
  "data": {
    "status": "started",
    "message": "Deployment started. Generating infrastructure and pushing to GitHub...",
    "user_id": "user123",
    "project_id": "project21"
  }
}

2. Code Pushed (first deployment_complete)

{
  "type": "deployment_complete",
  "data": {
    "status": "success",
    "deployment_status": "deploying_via_cicd",
    "message": "Code pushed to Qubitz-202/my-app. GitHub Actions is deploying via CDK.",
    "github_repo": "https://github.com/Qubitz-202/my-app",
    "user_id": "user123",
    "project_id": "project21"
  }
}

3. CI/CD Progress

{ "type": "status", "data": { "status": "deploying", "message": "Deploy CDK - Deploy with CDK", "progress_percent": 65 } }

progress_percent goes from 0 to 100. Use this to render a progress bar.

4. Deployment Finished (second deployment_complete)

{
  "type": "deployment_complete",
  "data": {
    "status": "deployed",
    "deployment_status": "deployed",
    "message": "Deployment successful!",
    "agent_endpoint": "https://api.qubitz.ai/my_app/invoke",
    "github_repo": "https://github.com/Qubitz-202/my-app",
    "user_id": "user123",
    "project_id": "project21"
  }
}

5. Done

{ "type": "complete" }

Use deployment_status to differentiate the two deployment_complete messages:

  • "deploying_via_cicd" — code pushed, CI/CD running
  • "deployed" — fully deployed, agent_endpoint is live

Error:

{ "type": "error", "data": { "error": "no_architecture", "message": "No architecture spec found. Generate one first with /getspec." } }

POST /createapikey

Create an API key for your deployed application's API Gateway. After deploying with /deploy, use this to generate keys that grant external consumers access to your agent endpoint. Each key is tied to a usage plan for rate limiting and quota management.

Scope: ControlHub

Connect: wss://api.qubitz.ai/createapikey?api_key=qk_ch_...

Request Payload

{
  "user_id": "user123",
  "project_id": "project21",
  "key_name": "production-key"
}
FieldTypeRequiredDescription
user_idstringYesYour user ID
project_idstringYesProject identifier (must be deployed)
key_namestringNoFriendly name for the API key

Response

{
  "type": "api_key_created",
  "data": {
    "api_key_value": "aBcDeFgHiJkLmNoPqRsTuVwXyZ123456",
    "api_key_id": "abc123def",
    "usage_plan_id": "plan456",
    "api_endpoint": "https://api.qubitz.ai/my_app/invoke"
  }
}

Save api_key_id and usage_plan_id — you need them to delete the key later.


POST /deleteapikey

Revoke and delete an API key from your deployed application's API Gateway. Pass the api_key_id (and optionally usage_plan_id) returned from /createapikey to permanently remove access for that key.

Scope: ControlHub

Connect: wss://api.qubitz.ai/deleteapikey?api_key=qk_ch_...

Request Payload

{
  "user_id": "user123",
  "project_id": "project21",
  "api_key_id": "abc123def",
  "usage_plan_id": "plan456"
}
FieldTypeRequiredDescription
user_idstringYesYour user ID
project_idstringYesProject identifier
api_key_idstringYesAPI key ID from /createapikey response
usage_plan_idstringNoUsage plan ID from /createapikey response

Response

{
  "type": "api_key_deleted",
  "data": { "api_key_id": "abc123def" }
}

Integration

TypeScript

type QubitzMessage = {
  type: string;
  data?: Record<string, any>;
  message?: string;
  chunk?: string;
  [key: string]: any;
};

function connectQubitz(
  endpoint: string,
  apiKey: string,
  payload: Record<string, any>,
  handlers: {
    onMessage?: (msg: QubitzMessage) => void;
    onChunk?: (text: string) => void;
    onComplete?: (msg: QubitzMessage) => void;
    onError?: (msg: QubitzMessage) => void;
    onProgress?: (percent: number, message: string) => void;
  }
): WebSocket {
  const ws = new WebSocket(
    `wss://api.qubitz.ai/${endpoint}?api_key=${apiKey}`
  );

  ws.onopen = () => {
    ws.send(JSON.stringify(payload));
  };

  ws.onmessage = (event) => {
    const msg: QubitzMessage = JSON.parse(event.data);
    handlers.onMessage?.(msg);

    switch (msg.type) {
      // Research chunks
      case "stream_chunk":
        handlers.onChunk?.(msg.data?.chunk ?? "");
        break;

      // Chat chunks
      case "chat_chunk":
        handlers.onChunk?.(msg.chunk ?? "");
        break;

      // Spec generation chunks
      case "claude_chunk":
        handlers.onChunk?.(msg.chunk ?? "");
        break;

      // Deploy progress
      case "status":
        if (msg.data?.progress_percent !== undefined) {
          handlers.onProgress?.(msg.data.progress_percent, msg.data.message);
        }
        break;

      // Completion types
      case "complete":
      case "chat_complete":
      case "deployment_complete":
      case "architecture":
      case "use_cases_complete":
      case "api_key_created":
      case "api_key_deleted":
        handlers.onComplete?.(msg);
        break;

      // Errors
      case "error":
      case "chat_error":
        handlers.onError?.(msg);
        break;
    }
  };

  ws.onerror = (err) => {
    handlers.onError?.({ type: "error", message: "WebSocket error" });
  };

  return ws;
}

Example: Research

const ws = connectQubitz("research", "qk_uct_...", {
  prompt: "Latest AI Trends 2026",
  company_name: "TestCompany",
  company_url: "https://example.com/",
  user_id: "user123",
  session_id: "session456",
}, {
  onChunk: (text) => process.stdout.write(text),
  onComplete: (msg) => {
    if (msg.type === "use_cases_complete") {
      console.log(`\n${msg.use_cases.length} use cases generated`);
    }
    if (msg.type === "complete") {
      console.log("\nReport URLs:", msg.all_s3_urls);
      ws.close();
    }
  },
  onError: (msg) => console.error("Error:", msg.message),
});

Example: Chat

let response = "";

const ws = connectQubitz("chat", "qk_uct_...", {
  messages: [{ role: "user", content: "What are the key findings?" }],
  s3_report_url: "https://qubitz-research-reports.s3.amazonaws.com/.../report.md",
  user_id: "user123",
  session_id: "session456",
  project_id: "project21",
}, {
  onChunk: (text) => { response += text; },
  onComplete: (msg) => {
    if (msg.type === "chat_complete") {
      console.log("Full response:", response);
      console.log("Tokens used:", msg.response.token_usage.total_tokens);
      ws.close();
    }
  },
});

Example: Generate Spec → Deploy

// Step 1: Generate architecture spec
const specWs = connectQubitz("getspec", "qk_ch_...", {
  user_id: "user123",
  project_id: "project21",
  use_case_name: "Financial Research Platform",
  use_case_description: "AI-powered investment research...",
  s3_uri: "https://qubitz-research-reports.s3.amazonaws.com/.../report.md",
}, {
  onComplete: (msg) => {
    if (msg.type === "architecture") {
      console.log("Agents:", Object.keys(msg.data.architecture.agents_config));
      specWs.close();
      deployApp(); // proceed to deploy
    }
  },
});

// Step 2: Deploy
function deployApp() {
  const deployWs = connectQubitz("deploy", "qk_ch_...", {
    user_id: "user123",
    project_id: "project21",
  }, {
    onProgress: (pct, msg) => console.log(`[${pct}%] ${msg}`),
    onComplete: (msg) => {
      if (msg.type === "deployment_complete" && msg.data?.deployment_status === "deployed") {
        console.log("Live at:", msg.data.agent_endpoint);
        deployWs.close();
      }
    },
  });
}

Python

import asyncio
import json
import websockets


async def connect_qubitz(endpoint: str, api_key: str, payload: dict):
    """Connect to a Qubitz WebSocket endpoint and yield messages."""
    url = f"wss://api.qubitz.ai/{endpoint}?api_key={api_key}"

    async with websockets.connect(
        url,
        ping_interval=30,
        ping_timeout=300,
        close_timeout=60,
    ) as ws:
        await ws.send(json.dumps(payload))

        async for raw in ws:
            msg = json.loads(raw)
            yield msg

            if msg.get("type") in ("complete", "error", "chat_error"):
                break

Example: Research

async def run_research():
    async for msg in connect_qubitz("research", "qk_uct_...", {
        "prompt": "Latest AI Trends 2026",
        "company_name": "TestCompany",
        "company_url": "https://example.com/",
        "user_id": "user123",
        "session_id": "session456",
    }):
        match msg["type"]:
            case "status" | "multiagent_step":
                print(f"[{msg['type']}] {msg.get('message', '')}")
            case "s3_upload_complete":
                print(f"Uploaded: {msg['s3_url']}")
            case "use_cases_complete":
                for uc in msg["use_cases"]:
                    print(f"  - {uc['title']} ({uc['impact_score']})")
            case "complete":
                print(f"\nReport: {msg['s3_deep_research_report_url']}")
                print(f"PDF:    {msg['s3_deep_research_pdf_url']}")
            case "error":
                print(f"ERROR: {msg.get('message')}")

asyncio.run(run_research())

Example: Chat

async def chat_with_report():
    full_response = ""

    async for msg in connect_qubitz("chat", "qk_uct_...", {
        "messages": [{"role": "user", "content": "Summarize the key findings"}],
        "s3_report_url": "https://qubitz-research-reports.s3.amazonaws.com/.../report.md",
        "user_id": "user123",
        "session_id": "session456",
        "project_id": "project21",
    }):
        match msg["type"]:
            case "chat_chunk":
                full_response += msg.get("chunk", "")
                print(msg.get("chunk", ""), end="", flush=True)
            case "chat_complete":
                tokens = msg["response"]["token_usage"]["total_tokens"]
                print(f"\n\n--- {tokens} tokens used ---")

asyncio.run(chat_with_report())

Example: Generate Spec + Deploy

async def generate_and_deploy():
    # Step 1: Generate spec
    print("Generating architecture spec...")
    async for msg in connect_qubitz("getspec", "qk_ch_...", {
        "user_id": "user123",
        "project_id": "project21",
        "use_case_name": "Financial Research Platform",
        "use_case_description": "AI-powered investment research...",
        "s3_uri": "https://qubitz-research-reports.s3.amazonaws.com/.../report.md",
    }):
        if msg["type"] == "architecture":
            agents = msg["data"]["architecture"]["agents_config"]
            print(f"Generated {len(agents)} agents: {list(agents.keys())}")
            break

    # Step 2: Deploy
    print("\nDeploying...")
    async for msg in connect_qubitz("deploy", "qk_ch_...", {
        "user_id": "user123",
        "project_id": "project21",
    }):
        match msg["type"]:
            case "status" if "progress_percent" in msg.get("data", {}):
                print(f"  [{msg['data']['progress_percent']}%] {msg['data']['message']}")
            case "deployment_complete":
                data = msg["data"]
                if data.get("deployment_status") == "deployed":
                    print(f"\nLive at: {data['agent_endpoint']}")
                    print(f"GitHub:  {data['github_repo']}")

    # Step 3: Create API key for the deployed app
    print("\nCreating API key...")
    async for msg in connect_qubitz("createapikey", "qk_ch_...", {
        "user_id": "user123",
        "project_id": "project21",
        "key_name": "production-key",
    }):
        if msg["type"] == "api_key_created":
            data = msg["data"]
            print(f"API Key:  {data['api_key_value']}")
            print(f"Key ID:   {data['api_key_id']}")
            print(f"Endpoint: {data['api_endpoint']}")

asyncio.run(generate_and_deploy())

Common Message Types

These message types appear across multiple endpoints:

TypeDescription
keepalivePeriodic ping during long operations. No action needed.
errorSomething went wrong. Contains message with details.
completeOperation finished. Safe to close the connection.
statusProgress update. May contain progress_percent (0-100) for deploy.

Error Handling

All endpoints can return error messages. Always handle these:

{ "type": "error", "message": "No architecture spec found. Generate one first with /getspec." }

Common error scenarios:

  • Invalid/expired API key — Connection rejected with code 1008
  • Wrong scope — UCT key used on ControlHub endpoint (code 1008)
  • No spec found — Calling /deploy before /getspec
  • Token limit exceeded — Chat session exceeded token budget
  • Query validation failed — Research topic rejected by safety filters

Rate Limits

WebSocket connections have a 60-minute idle timeout. Long-running operations (research, deploy) send keepalive messages to maintain the connection. No explicit rate limit on message frequency.