Sign up to get an API key

API Reference

Programmatic access to Axion's forecasting platform. Send a question; Axion runs an orchestrator and a team of research agents (web search, market data, SEC filings, Fermi estimates) that reason in public, cite their evidence, and return graded probabilistic forecasts.

Getting started

  1. Create an account at axion.eternis.ai, then create an API key on the API Keys page. Any Axion account can create keys. No paid subscription tier required.
  2. Add credits before your first call. API usage is billed separately from the Axion monthly plan, in prepaid credits, and new accounts start at a zero balance. Purchases are self-serve via Stripe: $1 buys 100 credits, $50 minimum.
  3. Call the API with your key as a Bearer token (see Authentication). A positive credit balance is required to start a forecast.

Authentication

All endpoints require an API key passed as a Bearer token in the Authorization header:

Authorization: Bearer axn_sk_...

API keys are created and managed on the API Keys page. Any signed-in account can create a key. No paid plan required. Keys are shown once at creation and cannot be retrieved later.

Base URL

https://axion-main-api-axion---productionus.us-east-1.gists.org

Credits

API usage is billed separately from the Axion monthly plan. Users pre-purchase credits before usage.

  • $1 = 100 credits
  • Minimum purchase: $50 (5,000 credits)
  • Credits are deducted per message based on token usage across all models
ModelInput rateOutput rateCached rate
Opus 4.87503,75075
Sonnet 4.64502,25045

Rates are per 1M tokens. A single thread may use multiple models (coordinator + agents), so costs accumulate across all calls. Negative balances are allowed to guarantee delivery of in-progress results.

Limits

  • Maximum 10 concurrent in-progress threads per user

Coding agents

This reference is built to drop straight into a coding agent (Claude Code, Cursor, and similar). At the top of this page, use Copy as Markdown to copy the full reference formatted for LLMs, or Copy as Text for a plain-text version. Paste it into your agent's context and it has everything it needs to write a correct integration: authentication, request and response shapes, polling, and error handling.

A prompt that works well:

Here are the Axion API docs. Write a <language> client that creates a
forecast, polls until it completes, and prints each forecast with its
probability. Read the API key from an AXION_API_KEY environment variable.
POST/forecasts

Start a new forecast thread, or send a follow-up message to an existing one. Requires a positive API credit balance.

Request body

FieldTypeRequiredDescription
inputstringrequiredThe question or analysis prompt.
idstringoptionalExisting thread ID for follow-up messages. Not allowed with mode=decision.
modestringoptionalRun type. Omit (default) for a forecast; decision runs one-shot Decision Mode (admin only). See Decision Mode.
max_forecastsintegeroptionalNumber of forecasts to generate (1-10). Default 1. Not allowed with mode=decision.
effortstringoptionalAnalysis depth: low, medium, high, or xhigh. Default medium.
tierstringoptionalCost tier: default or scout. Scout runs a multi-model fusion panel — lower cost, slower — billed at fusion cost. Requires the costTiers entitlement on your account (403 otherwise). Frozen at thread creation: on follow-up (id set) omit it to keep the thread's tier; a conflicting value is rejected. Not allowed with mode: "decision".
monitoringobjectoptionalMonitoring cadence for the live decision. Only valid with mode: "decision". See Decision Mode.
webhook_urlstringoptionalURL to receive a POST callback on completion or failure.
json
{
  "input": "Will NVIDIA's data center revenue exceed $40B in Q1 2026?",
  "max_forecasts": 3,
  "effort": "high"
}

Response 201

json
{
  "id": "thread_abc123",
  "input": "Will NVIDIA's data center revenue exceed $40B in Q1 2026?",
  "preliminary_result": null,
  "status": "starting"
}
GET/forecasts/{thread_id}

Poll the status and results of a forecast thread.

Status values

startingin_progresscompletedfailed

Response 200

json
{
  "id": "thread_abc123",
  "input": "Will NVIDIA's data center revenue exceed $40B in Q1 2026?",
  "preliminary_result": "Early read: data-center momentum and hyperscaler capex point above $40B, but HBM supply is the swing factor. Refining with filings and channel checks…",
  "status": "completed",
  "result": "NVIDIA's data-center segment has grown for six straight quarters, reaching $35.6B in Q4 FY25. The Blackwell ramp and committed hyperscaler capex support a Q1 2026 figure above $40B; the main downside is HBM3E supply. On balance the threshold is more likely than not to be cleared…",
  "credits_consumed": 4231,
  "agents_progress": [
    { "slug": "web-search", "progress": 1.0, "turn": 12, "action": "done" },
    { "slug": "sec-filings", "progress": 1.0, "turn": 8, "action": "done" }
  ],
  "forecasts": [
    {
      "forecast_text": "NVIDIA data center revenue will exceed $40B in Q1 2026",
      "probability": 0.72,
      "confidence_lower": 0.55,
      "confidence_upper": 0.85,
      "resolution_date": "2026-07-15",
      "reasoning": "Q4 FY25 data-center revenue was $35.6B (+16% QoQ). Blackwell shipments and hyperscaler capex guidance imply continued double-digit sequential growth, placing $40B within reach absent a supply shock…",
      "concludes_at": "2026-07-15",
      "is_concluded": false,
      "outcome": null,
      "outcome_reasoning": null,
      "created_at": "2026-04-14T10:30:00Z"
    }
  ],
  "artifacts": [
    { "component_name": "RevenueChart", "props": "{\"data\": [...]}" }
  ]
}
GET/forecasts

List all forecast threads for your account.

Response 200

json
{
  "forecasts": [
    {
      "id": "thread_abc123",
      "input": "Will NVIDIA's data center revenue...",
      "status": "completed",
      "credits_consumed": 4231,
      "created_at": "2026-04-14T10:30:00Z"
    }
  ]
}
POST/forecasts/{thread_id}/stop

Cancel an in-progress forecast. Credits consumed up to cancellation are still charged.

Response 200

json
{ "success": true }
POST/forecasts/{thread_id}/share

Make a forecast thread publicly viewable. Returns a relative share URL.

Response 200

json
{ "success": true, "share_url": "/share/thread_abc123" }
POST/forecasts/{thread_id}/unshare

Revoke public access to a previously shared forecast thread.

Response 200

json
{ "success": true }
DELETE/forecasts/{thread_id}

Delete a forecast thread.

Response 200

json
{ "success": true }
GET/account/balance

Returns your current credit balance.

Response 200

json
{ "credits": 3750 }
POST/account/credits/purchase

Create a Stripe Checkout session for a one-time credit purchase. Minimum amount is $50.

Request body

json
{ "amount": 50 }

Response 200

json
{ "checkout_url": "https://checkout.stripe.com/c/pay/cs_..." }

Decision Mode

Decision Mode turns one description of a real decision into a live decision model — the alternatives, the value function that scores them, and the forecasts that drive the outcome — then keeps it current as new evidence arrives. In the app it runs as a conversation. Over the API it runs in one shot: submit the full description once. There are no follow-up questions; the run infers any missing details (a name, a deadline, the status-quo option) from your input and states the assumptions it made in the summary.

Decision Mode is restricted to admins. A non-admin key receives 403 on both create and poll.

Submit with mode: "decision". The request takes input, webhook_url, and effort like a forecast; id and max_forecasts do not apply. One call does everything: the run assembles the model, propagates it into the live decision store, and arms continuous monitoring. There is no second step.

json
{
  "input": "We can extend our Series A runway by cutting the new EU expansion, or raise a bridge now at a lower valuation. Decide by end of Q3. We care most about 18-month survival, then growth.",
  "mode": "decision",
  "effort": "high",
  "monitoring": { "cron": "0 6 * * *", "timezone": "America/New_York" }
}

Monitoring

A live decision is monitored daily by default: the backend re-reads evidence on a schedule and folds it into the decision nodes, so each poll reflects the current recommendation. Override the cadence with a monitoring object. It is only valid with mode: "decision".

FieldTypeRequiredDescription
enabledbooleanoptionalWhether to monitor the decision. Default true.
cronstringoptionalSchedule in cron syntax. Default 0 6 * * * (daily at 06:00).
timezonestringoptionalIANA timezone the schedule runs in. Default America/New_York.

Polling

Poll GET /forecasts/{thread_id}. For a decision run the signal to watch is the decision envelope's state, not the top-level status: the decision is usable the moment state reaches live, which can happen before — and independently of — the thread's status settling to completed. Poll until state is live (or the run reports failed). The decision field is an envelope with a state:

  • none — the run has not produced a decision model yet, or it completed without one.
  • draft — the model is assembled and about to go live. Transient.
  • live — the model is propagated and monitored. The fields below are populated.

result holds the written summary once the run produces one; it may still be empty while the decision is already live, so don't gate on it. A live decision is folded fresh on every poll, so computed reflects the latest evidence and updated_at advances as monitoring moves the nodes.

json
{
  "id": "thread_abc123",
  "status": "completed",
  "result": "Two alternatives modeled against 18-month survival and growth. Cutting EU expansion preserves runway with lower upside; the bridge raise funds growth at dilution cost…",
  "decision": {
    "state": "live",
    "decision_id": "dec_abc123",
    "updated_at": "2026-06-29T06:00:00Z",
    "monitoring": { "enabled": true, "cron": "0 6 * * *", "timezone": "America/New_York" },
    "computed": {
      "recommendation": {
        "top_id": "alt_cut",
        "runner_up_id": "alt_bridge",
        "margin_pp": 12.4,
        "flipped_from_baseline": false
      },
      "gate": "release",
      "launch_p": 0.62,
      "change_type": "no_material_change",
      "confidence": 0.71,
      "confidence_delta_pp": 3.2,
      "scored": [
        {
          "id": "alt_cut", "label": "Cut EU expansion", "score": 0.62, "allocation": 1.0,
          "history": [
            { "date": "2026-06-20", "allocation": 0.8 },
            { "date": "2026-06-29", "allocation": 1.0 }
          ],
          "changes": [
            {
              "date": "2026-06-29", "from_allocation": 0.8, "to_allocation": 1.0,
              "trigger_forecast_id": "fc_survive", "evidence_ids": ["ev_1"],
              "change_type": "budget_shift"
            }
          ]
        },
        { "id": "alt_bridge", "label": "Raise a bridge round", "score": 0.5, "allocation": 0.0, "history": [], "changes": [] }
      ],
      "forecasts": [
        {
          "id": "fc_survive", "label": "Company survives the next 18 months",
          "current_probability": 0.78, "baseline_probability": 0.72, "delta_pp": 6.0,
          "initial_forecast_source": "axion_api",
          "history": [
            { "date": "2026-06-20", "p": 0.72, "evidence_ids": [] },
            { "date": "2026-06-29", "p": 0.78, "evidence_ids": ["ev_1"] }
          ]
        }
      ]
    },
    "events": [
      { "id": "ev_1", "day": 1, "date": "2026-06-29", "kind": "evidence",
        "setForecast": { "id": "fc_survive", "p": 0.78 } }
    ],
    "pack": { "pack_version": "1", "decision_nodes": [] }
  }
}

computed is at full parity with the web app — everything the UI renders, the API returns: recommendation (top alternative, runner-up, margin, and flipped_from_baseline); the confidence gate (release, review, defer, or hold) with its launch_p; the decision-level change_type (no_material_change, ranking_change, budget_shift, gate_state_change, or confidence_change); confidence and its signed move (confidence_delta_pp); every scored alternative with its allocation history and per-option changes; and each driving forecast's current and baseline probability, delta_pp, initial_forecast_source (llm_prior or axion_api), history trajectory, and belief state. On a just-minted decision the deltas are 0 and per-option changes are empty; each alternative's history carries a single initial allocation point, while forecast trajectories stay empty until the first monitoring cycle records evidence. events is the raw evidence-ingest log behind every change — omitted until the first monitoring cycle records evidence; once present it is an array of ingest events (each a kind, date, and the forecast or weight move it applied). pack carries the full decision model and is abridged above. Decision Mode charges credits the same way a forecast does.

Webhooks

If webhook_url is provided when creating a forecast, Axion sends a POST request to that URL when the thread reaches a terminal state (completed or failed). The payload matches the GET /forecasts/{thread_id} response.

Delivery is best-effort with up to 3 retries. Poll as a fallback if you need guaranteed delivery.

Errors

All errors return a JSON body with an error field:

json
{ "error": "insufficient credits" }
StatusMeaning
400Invalid request
401Invalid or missing API key
402Insufficient credits
403Restricted to admins (Decision Mode)
404Thread not found
422Invalid request body
429Too many concurrent threads (max 10)
500Internal error

Example: poll until complete

python
import requests
import time

API_KEY = "axn_sk_..."
BASE = "https://axion-main-api-axion---productionus.us-east-1.gists.org"
headers = {"Authorization": f"Bearer {API_KEY}"}

# Create
r = requests.post(f"{BASE}/forecasts", headers=headers, json={
    "input": "Will the Fed cut rates in June 2026?",
    "effort": "high"
})
thread_id = r.json()["id"]

# Poll
while True:
    r = requests.get(f"{BASE}/forecasts/{thread_id}", headers=headers)
    data = r.json()
    print(f"Status: {data['status']}")
    if data["status"] in ("completed", "failed"):
        break
    time.sleep(5)

# Result
for f in data["forecasts"]:
    print(f"{f['forecast_text']}: {f['probability']}")

Eternis Inc.