Documentation

API Reference

Every endpoint documented with request and response schemas.

Base URL

All API requests are made to https://engine.debatetalk.ai. The debate streaming endpoint lives at the root path with no versioning prefix. All account management endpoints use the /v1/ prefix.

text
https://engine.debatetalk.ai/debate        # Debate streaming
https://engine.debatetalk.ai/v1/user/profile  # Management endpoints
The /debate endpoint intentionally has no version prefix. Its response shape is the SSE event stream, which is versioned implicitly by the type field on each event. All other endpoints are under /v1/.

Authentication

DebateTalk supports two authentication methods depending on your integration context. Both are passed as a standard HTTP Authorization bearer header.

Session Token (Supabase)

When building on top of the DebateTalk dashboard or integrating server-side with Supabase Auth, pass your Supabase session JWT directly. The token is issued after the user signs in via the dashboard or via the Supabase auth client library.

http
Authorization: Bearer YOUR_SUPABASE_JWT

Session tokens are short-lived and automatically refreshed by the Supabase client. All management endpoints (/v1/user/*, /v1/models/*) require a session token.

API Key

For programmatic, server-to-server integrations you can use a DebateTalk API key. API keys are created in the dashboard under Settings. Pass the key as the bearer token:

http
Authorization: Bearer dt_YOUR_API_KEY

API keys are scoped to specific operations and can carry an optional expiration date. The only operations an API key authorises are running debates (POST /debate,GET /debate) and requesting model recommendations (POST /v1/models/recommend). Management endpoints always require a session token and will reject API key auth with 403 Forbidden.

Free accounts cannot create API keys. Pro accounts can hold up to 2 active keys. Enterprise accounts have no key limit.

API keys are prefixed with dt_ so they are easy to identify and can be detected by secret-scanning tools in your CI pipeline.

Unauthenticated Requests

The debate endpoint accepts requests with no Authorization header at all. Unauthenticated debates are rate-limited at the IP level. They are not saved to debate history and no token usage is attributed to any account.

Rate Limits

Rate limit violations always return HTTP 429 with a standard error body. Theerror.code is rate_limited.

Unauthenticated requests are limited to 3 debates per hour per IP address. Free accounts are limited to 5 debates per day total. The dashboard shows a CAPTCHA prompt after 3 debates in a single day on the Free plan. Pro and Enterprise accounts have no debate rate limit.

The POST /v1/auth/check-provider endpoint is separately rate-limited to 10 requests per minute per IP address, regardless of authentication status.

Rate limits are enforced per account when authenticated and per IP address for unauthenticated requests. If you are running debates from a shared IP (NAT, corporate proxy) consider authenticating to get per-account limits.

Error Format

All non-streaming endpoints return errors as JSON with HTTP 4xx or 5xx status codes. Every error body has the same shape:

json
{
  "error": {
    "code": "error_code_string",
    "message": "Human-readable description",
    "details": {}
  }
}

The details object is optional and may carry field-level validation errors or additional context. It is always an object, never null.

Common error codes:

Parameters

NameTypeRequiredDescription
unauthorizedstringNoNo valid credential was provided or the credential has expired.
forbiddenstringNoThe credential is valid but does not have permission for this operation. API keys will receive this on management endpoints.
not_foundstringNoThe requested resource does not exist or is not accessible to the caller.
rate_limitedstringNoThe caller has exceeded their allowed request rate. See the Rate Limits section.
validation_errorstringNoThe request body or query parameters failed schema validation. Check details for field-level messages.
tier_limit_exceededstringNoThe operation requires a higher plan tier than the account currently has.
insufficient_creditsstringNoThe Pro account does not have enough credit balance to run the requested debate.
debate_not_foundstringNoNo debate with the given ID exists for this account.
key_not_foundstringNoNo API key with the given ID exists for this account.
Streaming errors (during an active SSE connection) are delivered as an errorSSE event rather than an HTTP error status. See the SSE Event Reference section for the event shape.

Debate Streaming

The debate endpoint is the core of the DebateTalk API. It streams a full multi-model debate as a sequence of Server-Sent Events (SSE). The connection stays open until the debate completes or an error occurs. The final event is always of type final.

Two HTTP methods are available depending on question length. Both return the same SSE stream.

GEThttps://engine.debatetalk.ai/debateAuth optional

Stream a debate for questions up to 2,000 characters. Pass the question as a URL query parameter.

Parameters

NameTypeRequiredDescription
questionstringYesThe debate question. Maximum 2,000 characters.
POSThttps://engine.debatetalk.ai/debateAuth optional

Stream a debate for longer questions up to 100,000 characters. Pass the question in the JSON body.

Parameters

NameTypeRequiredDescription
questionstringYesThe debate question. Must be between 1 and 100,000 characters.
json
{ "question": "string (1 to 100,000 characters)" }

The response Content-Type is text/event-stream. Each event is a UTF-8 line in the format data: {...}\n\n. The following example shows how to consume the stream in a browser or Node.js environment:

js
const response = await fetch("https://engine.debatetalk.ai/debate", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_TOKEN"
  },
  body: JSON.stringify({ question: "Should remote work be the default for knowledge workers?" })
})

const reader = response.body.getReader()
const decoder = new TextDecoder()

while (true) {
  const { done, value } = await reader.read()
  if (done) break
  const text = decoder.decode(value)
  // Each SSE line is: "data: {...}\n\n"
  for (const line of text.split("\n")) {
    if (line.startsWith("data: ")) {
      const event = JSON.parse(line.slice(6))
      console.log(event.type, event.data)
    }
  }
}
If the Authorization header is omitted, the debate runs without attribution. Authenticated debates are saved to history and billed against the account's credit balance (Pro) or counted toward the daily limit (Free).

SSE Event Reference

Every SSE message is a JSON object with a type field and an optionaldata object. Events arrive in a deterministic order within a debate. The sequence is: debate_created => classification => debate_start => one or more round groups (round_start,model_response per model, consensus_check, consensus) => synthesis_start => synthesis => accuracy => final.

debate_created

The first event emitted. Contains the server-assigned debate ID and the generated title derived from the question. Store the debate_id if you need to retrieve the full record from the history API after the stream closes.

json
{
  "type": "debate_created",
  "data": {
    "debate_id": "uuid",
    "title": "Should remote work be the default for knowledge workers?"
  }
}

classification

Emitted after the question has been classified. The question_type is one of the DebateTalk question domains (Normative, Factual, Predictive, Business, etc.). The termination_trigger determines the consensus condition that, when met, ends the debate early. See the How Debates Work page for the full list of triggers.

json
{
  "type": "classification",
  "data": {
    "question_type": "Normative",
    "termination_trigger": "Value Alignment"
  }
}

debate_start

Emitted once before the first round. Lists the model display names selected for this debate and the maximum number of rounds the debate can run before synthesis is forced.

json
{
  "type": "debate_start",
  "data": {
    "models": ["claude-opus-4-6", "gpt-5-4", "gemini-3-1-pro"],
    "max_rounds": 4
  }
}

round_start

Emitted at the beginning of each round. The phase is "blind" for round 1, in which models respond without seeing each other's answers. All subsequent rounds have phase "deliberation".

json
{
  "type": "round_start",
  "data": {
    "round": 1,
    "phase": "blind"
  }
}

model_response

Emitted once per model that completes a round. The structure of thedata payload differs between the blind round and deliberation rounds.

Round 1 (blind phase) response shape:

json
{
  "type": "model_response",
  "data": {
    "round": 1,
    "name": "Model A",
    "answer": "Remote work should be the default for knowledge workers because...",
    "key_claims": [
      { "claim": "Productivity increases for focused work", "confidence": 0.85 },
      { "claim": "Collaboration suffers for complex team projects", "confidence": 0.72 }
    ],
    "confidence": 0.78
  }
}

Deliberation round response shape (round 2 and beyond):

json
{
  "type": "model_response",
  "data": {
    "round": 2,
    "name": "Model A",
    "answer": "I maintain that remote work should be the default, though I now weight...",
    "key_claims": [
      { "claim": "Productivity increases for focused work", "confidence": 0.88, "changed": false },
      { "claim": "Hybrid models outperform pure remote for mentorship", "confidence": 0.80, "changed": true, "reason": "Model B raised compelling evidence about junior developer outcomes" }
    ],
    "confidence": 0.82,
    "what_i_learned": "Model B's point about onboarding and mentorship is well-supported",
    "what_i_corrected": "I understated the cost of remote work for early-career employees",
    "still_disagree_on": "Whether in-office mandates are necessary for culture"
  }
}

In deliberation rounds, each entry in key_claims gains achanged boolean. When changed is true, areason string is also present explaining what prompted the update. The top-level fields what_i_learned, what_i_corrected, andstill_disagree_on are present only in deliberation rounds.

model_skipped

Emitted when a model is dropped from a round because its latency is consistently slower than the other models in the panel. The debate continues without that model for the remainder of the round. If the model recovers in a later round it may be reintroduced.

json
{
  "type": "model_skipped",
  "data": {
    "name": "Model C",
    "reason": "latency"
  }
}

consensus_check

Emitted when the adjudicator begins evaluating whether consensus has been reached after a round. This event carries no data payload.

json
{ "type": "consensus_check" }

consensus

Emitted after each round with the result of the consensus evaluation.reached is true when the termination trigger fires and the debate ends early. The scores object contains the four sub-scores (0 to 25 each) used to compute overall consensus. A total above roughly 70 typically triggers termination depending on the question type.

json
{
  "type": "consensus",
  "data": {
    "round": 1,
    "reached": false,
    "scores": {
      "stance_alignment": 18,
      "empirical_overlap": 15,
      "framework_agreement": 14,
      "confidence_convergence": 16
    }
  }
}

synthesis_start

Emitted when the synthesizer model begins producing the final answer. No data payload is present.

json
{ "type": "synthesis_start" }

synthesis

Contains the synthesized final answer produced by the synthesizer model. Thesynthesis string is a prose summary of what the panel collectively concluded, including areas of remaining disagreement.

json
{
  "type": "synthesis",
  "data": {
    "synthesis": "The panel reached consensus that remote work should be the default for knowledge workers performing focused individual tasks, with structured in-person time reserved for onboarding, mentorship, and complex collaborative work. Pure remote-first policies were found to disadvantage early-career employees disproportionately."
  }
}

accuracy

Contains accuracy scores for each debater as evaluated by the adjudicator.factual_accuracy measures claim correctness. logical_consistency measures internal argument coherence. evidence_quality measures how well claims were supported. trajectory_score measures how productively the model updated its position across rounds.

json
{
  "type": "accuracy",
  "data": {
    "scores": [
      {
        "name": "Model A",
        "factual_accuracy": 82,
        "logical_consistency": 88,
        "evidence_quality": 79,
        "trajectory_score": 85
      },
      {
        "name": "Model B",
        "factual_accuracy": 91,
        "logical_consistency": 84,
        "evidence_quality": 90,
        "trajectory_score": 78
      }
    ]
  }
}

final

The last event in every debate, always present regardless of how the debate ended. Contains a complete summary including the full token usage breakdown and cost. Once you receive this event the stream will close.

json
{
  "type": "final",
  "data": {
    "debate_id": "uuid",
    "question": "Should remote work be the default for knowledge workers?",
    "rounds_completed": 2,
    "max_rounds": 4,
    "consensus_reached": true,
    "synthesis": "The panel reached consensus that...",
    "models": ["Model A", "Model B", "Model C"],
    "token_usage": {
      "Model A": { "prompt_tokens": 2400, "completion_tokens": 800 },
      "Model B": { "prompt_tokens": 2350, "completion_tokens": 920 }
    },
    "cost_usd": 0.042
  }
}

error

Emitted when a fatal error occurs during the stream. After this event the connection closes. The code field matches the standard error codes documented in the Error Format section.

json
{
  "type": "error",
  "data": {
    "code": "rate_limited",
    "message": "You have reached your daily debate limit."
  }
}

User Profile

GET/v1/user/profileAuth required

Retrieve the authenticated user's profile.

json
{
  "id": "uuid",
  "email": "user@example.com",
  "display_name": "Alice",
  "tier": "pro",
  "created_at": "2026-01-15T10:00:00Z",
  "updated_at": "2026-03-20T14:30:00Z"
}
PATCH/v1/user/profileAuth required

Update the user's display name.

Parameters

NameTypeRequiredDescription
display_namestringYesThe new display name for the account.

The response has the same shape as the GET /v1/user/profile response, reflecting the updated values.

Model Configuration

GET/v1/user/model-configAuth required

Get the user's current model configuration and the full list of available models.

The response contains three top-level keys. config is the user's saved debate configuration. tier_limits describes what the account's plan permits. available_models is the full catalogue with pricing and accessibility for this account.

json
{
  "config": {
    "auto_mode": true,
    "num_debaters": 3,
    "debaters": ["model-id-1", "model-id-2", "model-id-3"],
    "adjudicator": "model-id",
    "synthesizer": "model-id",
    "max_rounds": 4
  },
  "tier_limits": {
    "max_debaters": 5,
    "max_rounds": 4,
    "adjudicator_is_algorithmic_only": false
  },
  "available_models": [
    {
      "id": "model-id",
      "display_name": "Claude Opus",
      "provider": "Anthropic",
      "context_window": 200000,
      "tier_required": "free",
      "is_accessible": true,
      "cost_per_million_input_tokens": 15.0,
      "cost_per_million_output_tokens": 75.0
    }
  ]
}

The is_accessible field on each model is true when the model is available to the caller's current plan tier. Models withtier_required: "pro" will have is_accessible: false for Free accounts.

PUT/v1/user/model-configAuth required

Save a new model configuration. All fields are required when not using auto mode.

Parameters

NameTypeRequiredDescription
auto_modebooleanYesWhen true, the smart router selects models automatically and the other fields are ignored.
num_debatersintegerYesNumber of debater models. Must be between 2 and the plan's max_debaters limit.
debatersstring[]YesArray of model IDs to use as debaters. Length must match num_debaters.
adjudicatorstringYesModel ID to use as the adjudicator.
synthesizerstringYesModel ID to use as the synthesizer.
max_roundsintegerYesMaximum number of debate rounds before synthesis is forced. Must not exceed the plan's max_rounds limit.
json
{
  "auto_mode": false,
  "num_debaters": 3,
  "debaters": ["model-id-1", "model-id-2", "model-id-3"],
  "adjudicator": "model-id",
  "synthesizer": "model-id",
  "max_rounds": 3
}

The response returns the saved configuration in the same shape as theconfig field from GET /v1/user/model-config.

Cost Estimation

Use this endpoint to preview the expected cost of a debate before running it. This is useful for Pro accounts that want to verify they have sufficient credits before initiating a long debate with expensive models.

POST/v1/user/estimate-costAuth required

Estimate the cost of a debate with a given configuration before running it.

Parameters

NameTypeRequiredDescription
auto_modebooleanYesWhen true, the estimate is based on the smart router's typical model selection for an average question.
debatersstring[]NoModel IDs for the debaters. Required when auto_mode is false.
adjudicatorstringNoModel ID for the adjudicator. Required when auto_mode is false.
synthesizerstringNoModel ID for the synthesizer. Required when auto_mode is false.
roundsintegerYesNumber of rounds to estimate for.
json
{
  "auto_mode": false,
  "debaters": ["model-id-1", "model-id-2"],
  "adjudicator": "model-id",
  "synthesizer": "model-id",
  "rounds": 3
}

Response:

json
{
  "estimated_cost_usd": 0.085,
  "breakdown": {
    "debaters": 0.062,
    "adjudicator": 0.012,
    "synthesizer": 0.011
  },
  "monthly_projection": {
    "debates_per_month": 100,
    "estimated_monthly_cost_usd": 8.50
  }
}
Cost estimates are based on average token counts for the selected models and round count. Actual cost will vary based on question complexity and the length of model responses.

Debate History

GET/v1/user/historyAuth required

List past debates with optional filters. Returns a paginated list in reverse chronological order.

Parameters

NameTypeRequiredDescription
pageintegerNoPage number. Defaults to 1.
limitintegerNoResults per page. Defaults to 20, maximum 100.
fromISO datetimeNoReturn only debates created at or after this timestamp.
toISO datetimeNoReturn only debates created at or before this timestamp.
statusstringNoFilter by debate status. One of: completed, failed, aborted.
searchstringNoFull-text search across the debate question content.
json
{
  "debates": [
    {
      "id": "uuid",
      "title": "Should remote work be the default?",
      "question": "Should remote work be the default for knowledge workers?",
      "status": "completed",
      "rounds_completed": 2,
      "consensus_reached": true,
      "models_used": ["Model A", "Model B", "Model C"],
      "cost_usd": 0.042,
      "created_at": "2026-03-20T10:00:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 147,
    "pages": 8
  }
}
GET/v1/user/history/:debate_idAuth required

Get the full record for a single debate, including the complete SSE event transcript.

The response extends the list item shape with four additional fields:events (the full ordered array of SSE event objects as they were streamed), synthesis (the final synthesized answer as a string),accuracy_scores (the accuracy evaluation array), andtoken_usage (the per-model token breakdown).

json
{
  "id": "uuid",
  "title": "Should remote work be the default?",
  "question": "Should remote work be the default for knowledge workers?",
  "status": "completed",
  "rounds_completed": 2,
  "consensus_reached": true,
  "models_used": ["Model A", "Model B", "Model C"],
  "cost_usd": 0.042,
  "created_at": "2026-03-20T10:00:00Z",
  "events": [...],
  "synthesis": "The panel concluded that...",
  "accuracy_scores": [...],
  "token_usage": {...}
}

Usage Statistics

GET/v1/user/usage?period=:periodAuth required

Get aggregated usage statistics for a given time period.

Valid values for period: current_month, last_month, last_7d, last_30d, all_time.

json
{
  "period": "current_month",
  "debates_run": 34,
  "debates_today": 2,
  "total_tokens": 1840000,
  "total_cost_usd": 3.42,
  "avg_cost_per_debate_usd": 0.101,
  "avg_rounds": 2.1,
  "consensus_rate": 0.82,
  "credit_balance_usd": 22.50
}

The credit_balance_usd field is only present in responses for Pro tier accounts.

GET/v1/user/usage/detailed?period=:periodAuth required

Get a day-by-day usage breakdown for a given time period.

Valid values for period: today, week, month, lastMonth.

json
{
  "period": "month",
  "daily": [
    {
      "date": "2026-03-01",
      "debates": 3,
      "tokens_in": 48000,
      "tokens_out": 12000,
      "cost_usd": 0.31
    }
  ]
}

Billing

GET/v1/user/billingAuth required

Get current billing information and available upgrade options.

The response shape varies by plan tier. Free accounts receive an upgrade URL. Pro accounts receive credit balance and auto-refill settings. Enterprise accounts receive a support contact.

Free tier response:

json
{
  "tier": "free",
  "upgrade_url": "https://app.debatetalk.ai/billing/upgrade"
}

Pro tier response:

json
{
  "tier": "pro",
  "credit_balance_usd": 22.50,
  "auto_refill_enabled": true,
  "auto_refill_amount_usd": 10.00,
  "auto_refill_threshold_usd": 5.00
}

Enterprise tier response:

json
{
  "tier": "enterprise",
  "support_contact": "enterprise@debatetalk.ai"
}

Credits

Credit endpoints are available exclusively to Pro tier accounts. Requests from Free or Enterprise accounts will receive 403 Forbidden with codetier_limit_exceeded.

GET/v1/user/creditsAuth required

Get the current credit balance and auto-refill configuration.

json
{
  "balance_usd": 22.50,
  "auto_refill_enabled": true,
  "auto_refill_amount_usd": 10.00,
  "auto_refill_threshold_usd": 5.00
}
GET/v1/user/credits/transactions?limit=50&offset=0Auth required

Get paginated credit transaction history.

Parameters

NameTypeRequiredDescription
limitintegerNoNumber of transactions to return. Defaults to 50.
offsetintegerNoNumber of transactions to skip for pagination. Defaults to 0.
json
{
  "transactions": [
    {
      "id": "uuid",
      "type": "debit",
      "amount_usd": -0.042,
      "balance_after_usd": 22.458,
      "description": "Debate: Should remote work be the default?",
      "debate_id": "uuid",
      "created_at": "2026-03-20T10:00:00Z"
    }
  ],
  "total": 147
}

The type field is one of three values. debit represents a debate cost charge. credit represents a refund or manual adjustment.topup represents credits purchased via checkout.

POST/v1/user/credits/checkoutAuth required

Create a Paddle checkout transaction to purchase credits.

Parameters

NameTypeRequiredDescription
amountnumberYesAmount in USD to purchase. Minimum $5.00, maximum $500.00.
json
{ "amount": 25.00 }

Response:

json
{ "transaction_id": "txn_..." }

Pass the returned transaction_id to the Paddle.js overlay to complete the payment. Credits are added to the account balance as soon as Paddle confirms the transaction.

PATCH/v1/user/credits/auto-refillAuth required

Enable or disable auto-refill and configure its threshold and amount.

Parameters

NameTypeRequiredDescription
enabledbooleanYesWhether auto-refill should be active.
amountnumberYesUSD amount to purchase each time auto-refill triggers.
thresholdnumberYesUSD balance level at which auto-refill activates.
json
{
  "enabled": true,
  "amount": 10.00,
  "threshold": 5.00
}

When enabled, the system will automatically initiate a Paddle purchase of amount USD using the account's saved payment method whenever the credit balance drops below threshold USD. The response has the same shape as GET /v1/user/credits.

API Keys

API key management is available to Pro and Enterprise accounts. Free accounts will receive 403 Forbidden with code tier_limit_exceeded on all key endpoints.

GET/v1/user/api-keysAuth required

List all API keys for the account.

json
{
  "keys": [
    {
      "id": "uuid",
      "name": "Production server",
      "prefix": "dt_live_abc123",
      "scopes": ["debate:run"],
      "is_active": true,
      "last_used_at": "2026-03-20T09:00:00Z",
      "expires_at": null,
      "created_at": "2026-01-10T00:00:00Z"
    }
  ]
}

The full key value is never returned by this endpoint. Only the prefix is exposed so you can identify which key is which.

POST/v1/user/api-keysAuth required

Create a new API key. The full key value is only returned in this response and cannot be retrieved again.

Parameters

NameTypeRequiredDescription
namestringYesA human-readable label for this key, e.g. "Production server".
scopesstring[]YesArray of permission scopes. Currently only debate:run is supported.
expires_atISO datetimeNoOptional expiration timestamp. Omit for a key with no expiry.
json
{
  "name": "Production server",
  "scopes": ["debate:run"],
  "expires_at": "2027-01-01T00:00:00Z"
}

Response:

json
{
  "id": "uuid",
  "name": "Production server",
  "key": "dt_live_abc123def456...",
  "prefix": "dt_live_abc123",
  "scopes": ["debate:run"],
  "created_at": "2026-03-20T00:00:00Z"
}
Store the full key value immediately. It will not be shown again.
DELETE/v1/user/api-keys/:key_idAuth required

Revoke an API key immediately. Any in-flight requests using this key will be rejected. Returns 204 No Content.

PATCH/v1/user/api-keys/:key_idAuth required

Update a key's name, active status, or expiration date. All fields are optional.

Parameters

NameTypeRequiredDescription
namestringNoNew display name for the key.
is_activebooleanNoSet to false to temporarily disable the key without revoking it.
expires_atISO datetimeNoNew expiration timestamp. Set to null to remove the expiration.
json
{
  "name": "Updated name",
  "is_active": false,
  "expires_at": "2027-06-01T00:00:00Z"
}

Sharing

Debates can be shared publicly via a token-based link. The shared URL exposes only the debate content. No user information, account details, or billing data is ever included in a shared debate response.

POST/v1/user/debates/:debate_id/shareAuth required

Generate a public share link for a debate.

Parameters

NameTypeRequiredDescription
expires_atISO datetimeNoOptional expiration time for the share link. Omit for a permanent link.
json
{
  "share_token": "abc123xyz",
  "share_url": "https://app.debatetalk.ai/shared/abc123xyz",
  "expires_at": null
}
GET/v1/public/debates/:share_tokenPublic

Retrieve a shared debate without authentication.

Returns the debate question, the list of models used, the full ordered SSE event transcript, the synthesis, and the accuracy scores. The response does not include the owner's user ID, email, display name, cost, or any account information.

Model Recommendation

This endpoint exposes the same model selection logic that Auto mode uses internally. Call it before starting a debate if you want to preview which models would be chosen for a given question, or to use the recommendation as a starting point for a manual configuration.

POST/v1/models/recommendAuth required

Ask the API to recommend an optimal model panel for a given question.

Parameters

NameTypeRequiredDescription
questionstringYesThe debate question to analyse.
num_debatersintegerYesHow many debater models to include in the recommendation.
json
{
  "question": "Will AI reach human-level reasoning by 2030?",
  "num_debaters": 3
}

Response:

json
{
  "question_type": "Prediction",
  "debaters": ["model-id-1", "model-id-2", "model-id-3"],
  "synthesizer": "model-id",
  "adjudicator": "model-id"
}

The question_type field is the classification the router assigned to the question. The returned model IDs can be passed directly toPUT /v1/user/model-config or to the debate endpoint after converting to the required request shape.

This endpoint is one of the two endpoints that accept API key authentication in addition to session tokens. The other is the debate endpoint itself.

Public Endpoints

These endpoints require no authentication and are safe to call from client-side code.

GET/v1/public/model-statusPublic

Get health and latency data for all active models.

Updated approximately every 5 minutes. The checks_24h field shows how many health checks were run in the past 24 hours. uptime_24h is the fraction of checks that returned a healthy response (1.0 = 100%).

json
{
  "models": [
    {
      "id": "model-id",
      "display_name": "Claude Opus",
      "provider": "Anthropic",
      "is_healthy": true,
      "latency_ms": 1240,
      "uptime_24h": 0.998,
      "avg_latency_24h_ms": 1180,
      "checks_24h": 288
    }
  ],
  "updated_at": "2026-03-29T12:00:00Z"
}
GET/healthPublic

Health check for the API server itself. Returns immediately with no database or model calls.

json
{ "status": "ok" }