{
  "openapi": "3.1.0",
  "info": {
    "title": "Kranth API",
    "version": "0.1.0",
    "description": "Synthetic-audience simulation engine. Spin up adversarial AI personas,\nstream their reactions, and read the verdict \u2014 all via REST.\n\n## Auth\nBearer token in the `Authorization` header. Two sources work everywhere:\n  - **API keys** (`kr_live_\u2026`) minted at `/app/account`.\n  - **Nexus JWTs** \u2014 issued by `accounts.vylth.com` SSO. Same header, same routes.\n\n## Versioning\nAll routes are under `/v1/`. Breaking changes ship as `/v2/` (or a later\npath). Additive fields and new endpoints are not breaking. When a `/v1`\noperation is retired we send `Deprecation` (RFC 8594) and `Sunset`\n(RFC 8594) response headers for at least 90 days before the path 410s.\nThere is no version header; do not send one.\n\n## Rate limits\n`POST /v1/sims` is per-org tier-rate-limited; everything else is uncapped\nat the application layer. Every response includes `RateLimit` and\n`RateLimit-Policy` (RFC 9431) plus `X-RateLimit-*`. On overflow you get\nHTTP 429 + `Retry-After` in seconds.\n\n## Errors\nEvery error response is JSON:\n`{\"error\":\"<code>\",\"message\":\"<human-readable>\",\"hint\":\"<what to do>\"}`.\nStatus codes follow REST conventions \u2014 401 = bad auth, 402 = out of credits,\n404 = not found (or cross-org), 422 = validation, 429 = rate-limited,\n5xx = server fault (paste the `x-request-id` header into a support email).\n",
    "contact": {
      "name": "Kranth Support",
      "email": "support@kranth.com",
      "url": "https://kranth.com/contact"
    },
    "license": {
      "name": "Kranth Terms of Service",
      "url": "https://kranth.com/terms"
    }
  },
  "servers": [
    {
      "url": "https://api.kranth.ai",
      "description": "Production"
    },
    {
      "url": "https://api.kranth.com",
      "description": "Production (dot-com mirror)"
    }
  ],
  "tags": [
    {
      "name": "Sims",
      "description": "Submit, read, list, cancel, export simulations."
    },
    {
      "name": "Recon",
      "description": "Web-grounded research swarm \u2014 submit, read, stream, export cited market reports."
    },
    {
      "name": "API keys",
      "description": "Mint and revoke long-lived bearer keys for SDK callers."
    },
    {
      "name": "Webhooks",
      "description": "Outgoing HTTP callbacks. HMAC-SHA256-signed, Starter plan or higher. See the Webhook schema description for the signature-verification recipe."
    },
    {
      "name": "Identity",
      "description": "Who's signed in."
    },
    {
      "name": "Models",
      "description": "What LLMs the engine can dispatch to."
    },
    {
      "name": "Settings",
      "description": "Workspace name + training-opt-in default."
    },
    {
      "name": "Account",
      "description": "Workspace + account deletion."
    },
    {
      "name": "Billing",
      "description": "Plans, top-ups, usage, Stripe checkout & portal."
    },
    {
      "name": "Debates",
      "description": "Structured adversarial debate sessions \u2014 five jury modes, live SSE turns, voice playback, scored synthesis."
    },
    {
      "name": "Waitlist",
      "description": "Public email capture for the marketing page."
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/v1/health": {
      "get": {
        "operationId": "getV1Health",
        "description": "Liveness probe",
        "tags": [
          "Identity"
        ],
        "summary": "Liveness probe",
        "security": [],
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Service is up."
          }
        }
      }
    },
    "/v1/me": {
      "get": {
        "operationId": "getV1Me",
        "description": "Who am I?",
        "tags": [
          "Identity"
        ],
        "summary": "Who am I?",
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Resolved identity.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Me"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/models": {
      "get": {
        "operationId": "getV1Models",
        "description": "List models the engine supports",
        "tags": [
          "Models"
        ],
        "summary": "List models the engine supports",
        "security": [],
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Model catalog.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "models": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Model"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/sims": {
      "post": {
        "operationId": "postV1Sims",
        "description": "Submit a simulation",
        "tags": [
          "Sims"
        ],
        "summary": "Submit a simulation",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSimRequest"
              }
            }
          }
        },
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "202": {
            "description": "Sim accepted, persona generation queued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateSimResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "422": {
            "$ref": "#/components/responses/Validation"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "get": {
        "operationId": "getV1Sims",
        "description": "List your sims (paginated)",
        "tags": [
          "Sims"
        ],
        "summary": "List your sims (paginated)",
        "parameters": [
          {
            "in": "query",
            "name": "status",
            "schema": {
              "type": "string",
              "enum": [
                "queued",
                "running",
                "complete",
                "failed",
                "canceled"
              ]
            }
          },
          {
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "type": "integer",
              "default": 50,
              "maximum": 200
            }
          }
        ],
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Page of sims.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sims": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Sim"
                      }
                    },
                    "next_cursor": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/sims/{id}": {
      "get": {
        "operationId": "getV1SimsId",
        "description": "Read one sim",
        "tags": [
          "Sims"
        ],
        "summary": "Read one sim",
        "parameters": [
          {
            "$ref": "#/components/parameters/SimId"
          }
        ],
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Sim row.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Sim"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/sims/{id}/cancel": {
      "post": {
        "operationId": "postV1SimsIdCancel",
        "description": "Cancel a queued or running sim",
        "tags": [
          "Sims"
        ],
        "summary": "Cancel a queued or running sim",
        "parameters": [
          {
            "$ref": "#/components/parameters/SimId"
          }
        ],
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Cancellation accepted; refund posted if applicable."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/sims/{id}/export": {
      "get": {
        "operationId": "getV1SimsIdExport",
        "description": "Download sim as JSON",
        "tags": [
          "Sims"
        ],
        "summary": "Download sim as JSON",
        "parameters": [
          {
            "$ref": "#/components/parameters/SimId"
          }
        ],
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Full sim + reactions + verdict.",
            "content": {
              "application/json": {}
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/sims/{id}/stream-token": {
      "post": {
        "operationId": "postV1SimsIdStreamToken",
        "description": "Mint a short-lived stream token (for EventSource)",
        "tags": [
          "Sims"
        ],
        "summary": "Mint a short-lived stream token (for EventSource)",
        "parameters": [
          {
            "$ref": "#/components/parameters/SimId"
          }
        ],
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "HMAC-signed token, 5-minute TTL.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string"
                    },
                    "expires_in": {
                      "type": "integer",
                      "description": "Seconds"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/sims/{id}/events": {
      "get": {
        "operationId": "getV1SimsIdEvents",
        "description": "Server-Sent Events stream (real-time reactions)",
        "tags": [
          "Sims"
        ],
        "summary": "Server-Sent Events stream (real-time reactions)",
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/SimId"
          },
          {
            "in": "query",
            "name": "token",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "From `/sims/{id}/stream-token`."
          }
        ],
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "text/event-stream of `persona.ready`, `reaction.partial`,\n`reaction.complete`, `cluster.formed`, `sim.complete`, `sim.failed`\nenvelopes. 15s heartbeat keeps proxies from closing.\n",
            "content": {
              "text/event-stream": {}
            }
          },
          "400": {
            "description": "Missing or malformed token."
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/recon": {
      "post": {
        "operationId": "postV1Recon",
        "description": "Submit a recon run",
        "tags": [
          "Recon"
        ],
        "summary": "Submit a recon run",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateReconRequest"
              }
            }
          }
        },
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "202": {
            "description": "Recon accepted, research agents queued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateReconResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "422": {
            "$ref": "#/components/responses/Validation"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "get": {
        "operationId": "getV1Recon",
        "description": "List your recon runs",
        "tags": [
          "Recon"
        ],
        "summary": "List your recon runs",
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "List of recon runs.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "recons": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ReconSummary"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/recon/tiers": {
      "get": {
        "operationId": "getV1ReconTiers",
        "description": "List recon tiers",
        "tags": [
          "Recon"
        ],
        "summary": "List recon tiers",
        "security": [],
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Tier catalog with slugs, labels, worker counts, and credit prices.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ReconTier"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/recon/{id}": {
      "get": {
        "operationId": "getV1ReconId",
        "description": "Read one recon run (findings + sources + report)",
        "tags": [
          "Recon"
        ],
        "summary": "Read one recon run (findings + sources + report)",
        "parameters": [
          {
            "$ref": "#/components/parameters/ReconId"
          }
        ],
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Full recon run with findings, sources, and synthesized report.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReconDetail"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/recon/{id}/export": {
      "get": {
        "operationId": "getV1ReconIdExport",
        "description": "Download branded PDF report",
        "tags": [
          "Recon"
        ],
        "summary": "Download branded PDF report",
        "parameters": [
          {
            "$ref": "#/components/parameters/ReconId"
          }
        ],
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Branded Kranth PDF report. Only available when status = complete.",
            "content": {
              "application/pdf": {}
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/recon/{id}/stream-token": {
      "post": {
        "operationId": "postV1ReconIdStreamToken",
        "description": "Mint a short-lived stream token (for EventSource)",
        "tags": [
          "Recon"
        ],
        "summary": "Mint a short-lived stream token (for EventSource)",
        "parameters": [
          {
            "$ref": "#/components/parameters/ReconId"
          }
        ],
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "HMAC-signed token, 5-minute TTL.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string"
                    },
                    "expires_in": {
                      "type": "integer",
                      "description": "Seconds"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/recon/{id}/events": {
      "get": {
        "operationId": "getV1ReconIdEvents",
        "description": "Server-Sent Events stream (live research progress)",
        "tags": [
          "Recon"
        ],
        "summary": "Server-Sent Events stream (live research progress)",
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/ReconId"
          },
          {
            "in": "query",
            "name": "token",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "From `/recon/{id}/stream-token`."
          }
        ],
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "text/event-stream of `recon.started`, `agent.started`, `agent.complete`,\n`synthesizing`, `recon.complete`, `recon.failed` envelopes.\n15s heartbeat keeps proxies from closing.\n",
            "content": {
              "text/event-stream": {}
            }
          },
          "400": {
            "description": "Missing or malformed token."
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/debates": {
      "post": {
        "operationId": "postV1Debates",
        "description": "Create a debate",
        "tags": [
          "Debates"
        ],
        "summary": "Create a debate",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDebateRequest"
              }
            }
          }
        },
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "201": {
            "description": "Debate created and queued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DebateRow"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "422": {
            "$ref": "#/components/responses/Validation"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "get": {
        "operationId": "getV1Debates",
        "description": "List your debates",
        "tags": [
          "Debates"
        ],
        "summary": "List your debates",
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "List of debates with per-debate speaker previews.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "debates": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/DebateRow"
                      }
                    },
                    "speakers": {
                      "type": "object",
                      "description": "Map of debate_id \u2192 array of SpeakerPreview.",
                      "additionalProperties": {
                        "type": "array",
                        "items": {
                          "$ref": "#/components/schemas/SpeakerPreview"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/debates/{id}": {
      "get": {
        "operationId": "getV1DebatesId",
        "description": "Read one debate (with synthesis and audience reactions)",
        "tags": [
          "Debates"
        ],
        "summary": "Read one debate (with synthesis and audience reactions)",
        "parameters": [
          {
            "$ref": "#/components/parameters/DebateId"
          }
        ],
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Full debate row plus synthesis and audience reactions.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DebateDetail"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "operationId": "patchV1DebatesId",
        "description": "Update a debate (visibility)",
        "tags": [
          "Debates"
        ],
        "summary": "Update a debate (visibility)",
        "parameters": [
          {
            "$ref": "#/components/parameters/DebateId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "public": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Updated debate detail.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DebateDetail"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/debates/{id}/turns": {
      "get": {
        "operationId": "getV1DebatesIdTurns",
        "description": "List turns for a debate",
        "tags": [
          "Debates"
        ],
        "summary": "List turns for a debate",
        "parameters": [
          {
            "$ref": "#/components/parameters/DebateId"
          }
        ],
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Ordered turn list.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "turns": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/DebateTurn"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/debates/{id}/cancel": {
      "post": {
        "operationId": "postV1DebatesIdCancel",
        "description": "Cancel a queued or running debate",
        "tags": [
          "Debates"
        ],
        "summary": "Cancel a queued or running debate",
        "parameters": [
          {
            "$ref": "#/components/parameters/DebateId"
          }
        ],
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Cancellation accepted; refund posted if applicable."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/debates/{id}/export": {
      "get": {
        "operationId": "getV1DebatesIdExport",
        "description": "Download debate as JSON",
        "tags": [
          "Debates"
        ],
        "summary": "Download debate as JSON",
        "parameters": [
          {
            "$ref": "#/components/parameters/DebateId"
          }
        ],
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Full debate + turns + synthesis + audience reactions. Only available when status = complete.",
            "content": {
              "application/json": {}
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/debates/{id}/stream-token": {
      "post": {
        "operationId": "postV1DebatesIdStreamToken",
        "description": "Mint a short-lived stream token (for EventSource)",
        "tags": [
          "Debates"
        ],
        "summary": "Mint a short-lived stream token (for EventSource)",
        "parameters": [
          {
            "$ref": "#/components/parameters/DebateId"
          }
        ],
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "HMAC-signed token, 5-minute TTL.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string"
                    },
                    "expires_in": {
                      "type": "integer",
                      "description": "Seconds"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/debates/{id}/events": {
      "get": {
        "operationId": "getV1DebatesIdEvents",
        "description": "Server-Sent Events stream (live debate turns)",
        "tags": [
          "Debates"
        ],
        "summary": "Server-Sent Events stream (live debate turns)",
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/DebateId"
          },
          {
            "in": "query",
            "name": "token",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "From `/debates/{id}/stream-token`."
          }
        ],
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "text/event-stream of `debate.create`, `debate.update`, `debate.end`,\n`debate.complete`, `debate.failed` envelopes.\n15s heartbeat keeps proxies from closing.\n",
            "content": {
              "text/event-stream": {}
            }
          },
          "400": {
            "description": "Missing or malformed token."
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/api-keys": {
      "post": {
        "operationId": "postV1ApiKeys",
        "description": "Mint a new API key",
        "tags": [
          "API keys"
        ],
        "summary": "Mint a new API key",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 80
                  }
                }
              }
            }
          }
        },
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Full key returned ONCE. Save it; we only store the argon2id hash.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "name": {
                      "type": "string"
                    },
                    "prefix": {
                      "type": "string"
                    },
                    "key": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "get": {
        "operationId": "getV1ApiKeys",
        "description": "List your keys (no secret values)",
        "tags": [
          "API keys"
        ],
        "summary": "List your keys (no secret values)",
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Keys for this workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "keys": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ApiKey"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/api-keys/{id}": {
      "delete": {
        "operationId": "deleteV1ApiKeysId",
        "description": "Revoke a key",
        "tags": [
          "API keys"
        ],
        "summary": "Revoke a key",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "204": {
            "description": "Revoked."
          }
        }
      }
    },
    "/v1/webhooks": {
      "post": {
        "operationId": "postV1Webhooks",
        "tags": [
          "Webhooks"
        ],
        "summary": "Register an outgoing webhook endpoint",
        "description": "Requires the Starter plan or higher. Returns the signing secret exactly once \u2014 it is never retrievable again (only re-rotatable).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhookRequest"
              }
            }
          }
        },
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "201": {
            "description": "Endpoint created. Response includes signing_secret (one time only).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedWebhook"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "422": {
            "$ref": "#/components/responses/Validation"
          }
        }
      },
      "get": {
        "operationId": "getV1Webhooks",
        "tags": [
          "Webhooks"
        ],
        "summary": "List webhook endpoints",
        "description": "signing_secret is never included in list or read responses.",
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Endpoints for this workspace, newest first.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "webhooks": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Webhook"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/webhooks/{id}": {
      "parameters": [
        {
          "in": "path",
          "name": "id",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "patch": {
        "operationId": "patchV1WebhooksId",
        "description": "Update event subscriptions, or pause/resume delivery",
        "tags": [
          "Webhooks"
        ],
        "summary": "Update event subscriptions, or pause/resume delivery",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchWebhookRequest"
              }
            }
          }
        },
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Updated Webhook object.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/Validation"
          }
        }
      },
      "delete": {
        "operationId": "deleteV1WebhooksId",
        "tags": [
          "Webhooks"
        ],
        "summary": "Remove a webhook endpoint",
        "description": "Delivery history is not retained after deletion.",
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "204": {
            "description": "Removed."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/settings": {
      "get": {
        "operationId": "getV1Settings",
        "description": "Workspace settings",
        "tags": [
          "Settings"
        ],
        "summary": "Workspace settings",
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Current settings.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Settings"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "patchV1Settings",
        "description": "Update workspace name or training opt-in",
        "tags": [
          "Settings"
        ],
        "summary": "Update workspace name or training opt-in",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "training_opt_in": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "New settings state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Settings"
                }
              }
            }
          }
        }
      }
    },
    "/v1/account": {
      "delete": {
        "operationId": "deleteV1Account",
        "tags": [
          "Account"
        ],
        "summary": "Delete your account",
        "description": "Cascades sole-owned workspaces. Refuses while any owned workspace\nhas a non-free plan \u2014 cancel via /v1/billing/portal first.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "confirm"
                ],
                "properties": {
                  "confirm": {
                    "type": "string",
                    "enum": [
                      "delete my account"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "204": {
            "description": "Account erased."
          },
          "422": {
            "$ref": "#/components/responses/Validation"
          }
        }
      }
    },
    "/v1/orgs/me": {
      "delete": {
        "operationId": "deleteV1OrgsMe",
        "tags": [
          "Account"
        ],
        "summary": "Delete this workspace",
        "description": "Owner-only. Type the workspace slug to confirm. Refuses while plan \u2260 free.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "confirm"
                ],
                "properties": {
                  "confirm": {
                    "type": "string",
                    "description": "Workspace slug"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "204": {
            "description": "Workspace erased."
          },
          "403": {
            "description": "Not an owner."
          }
        }
      }
    },
    "/v1/usage": {
      "get": {
        "operationId": "getV1Usage",
        "description": "Credit usage this period",
        "tags": [
          "Billing"
        ],
        "summary": "Credit usage this period",
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Plan + cap + consumed + remaining.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Usage"
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing/checkout": {
      "post": {
        "operationId": "postV1BillingCheckout",
        "description": "Mint a Stripe Checkout URL for a plan",
        "tags": [
          "Billing"
        ],
        "summary": "Mint a Stripe Checkout URL for a plan",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "plan"
                ],
                "properties": {
                  "plan": {
                    "type": "string",
                    "enum": [
                      "starter",
                      "pro",
                      "scale"
                    ]
                  },
                  "billing_period": {
                    "type": "string",
                    "enum": [
                      "monthly",
                      "annual"
                    ]
                  },
                  "success_url": {
                    "type": "string",
                    "nullable": true
                  },
                  "cancel_url": {
                    "type": "string",
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Stripe-hosted URL to redirect the user to.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string",
                      "format": "uri"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing/portal": {
      "post": {
        "operationId": "postV1BillingPortal",
        "description": "Mint a Stripe Customer Portal URL",
        "tags": [
          "Billing"
        ],
        "summary": "Mint a Stripe Customer Portal URL",
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Stripe-hosted URL.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string",
                      "format": "uri"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing/topup": {
      "post": {
        "operationId": "postV1BillingTopup",
        "description": "Buy a one-shot credit pack",
        "tags": [
          "Billing"
        ],
        "summary": "Buy a one-shot credit pack",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "credits"
                ],
                "properties": {
                  "credits": {
                    "type": "integer",
                    "minimum": 50,
                    "maximum": 100000,
                    "description": "Any amount from 50 (list $10) upward. Not a fixed pack."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "200": {
            "description": "Stripe-hosted URL.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string",
                      "format": "uri"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/waitlist": {
      "post": {
        "operationId": "postV1Waitlist",
        "description": "Join the launch waitlist",
        "tags": [
          "Waitlist"
        ],
        "summary": "Join the launch waitlist",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "utm_source": {
                    "type": "string"
                  },
                  "utm_medium": {
                    "type": "string"
                  },
                  "utm_campaign": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "default": {
            "$ref": "#/components/responses/ApiError"
          },
          "204": {
            "description": "Signed up (or already on the list \u2014 idempotent)."
          },
          "422": {
            "$ref": "#/components/responses/Validation"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "kr_live_\u2026 or Nexus JWT"
      }
    },
    "parameters": {
      "SimId": {
        "in": "path",
        "name": "id",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "ReconId": {
        "in": "path",
        "name": "id",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "DebateId": {
        "in": "path",
        "name": "id",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    },
    "responses": {
      "ApiError": {
        "description": "Structured JSON error (code, message, hint).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing or invalid bearer.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Doesn't exist, or it belongs to another org (we don't distinguish).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "PaymentRequired": {
        "description": "Out of credits. Top up or upgrade.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Validation": {
        "description": "Request body failed validation.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Per-org rate limit exceeded.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        },
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer",
              "description": "Seconds before another POST is allowed."
            }
          },
          "RateLimit": {
            "schema": {
              "type": "string",
              "description": "RFC 9431 quota remaining in this window."
            }
          },
          "RateLimit-Policy": {
            "schema": {
              "type": "string",
              "description": "RFC 9431 policy (quota and window)."
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error",
          "message",
          "hint"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Machine-readable code.",
            "enum": [
              "validation_failed",
              "not_found",
              "unauthorized",
              "forbidden",
              "payment_required",
              "rate_limited",
              "database_unavailable",
              "not_configured",
              "database_error",
              "internal_error"
            ]
          },
          "message": {
            "type": "string",
            "description": "Human-readable sentence safe to show a user."
          },
          "hint": {
            "type": "string",
            "description": "What to change or where to read next."
          }
        }
      },
      "Me": {
        "type": "object",
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid"
          },
          "org_id": {
            "type": "string",
            "format": "uuid"
          },
          "auth_source": {
            "type": "string",
            "enum": [
              "api_key",
              "nexus"
            ]
          }
        }
      },
      "Model": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "sonnet-4-6"
          },
          "tier": {
            "type": "string",
            "example": "sonnet"
          },
          "display_name": {
            "type": "string",
            "example": "Claude Sonnet 4.6"
          },
          "provider": {
            "type": "string",
            "example": "anthropic"
          },
          "credits_per_100_personas": {
            "type": "integer"
          },
          "plan_min": {
            "type": "string"
          }
        }
      },
      "CreateSimRequest": {
        "type": "object",
        "required": [
          "idea_text",
          "persona_count",
          "model_id"
        ],
        "properties": {
          "idea_text": {
            "type": "string",
            "maxLength": 10000
          },
          "persona_count": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5000
          },
          "model_id": {
            "type": "string",
            "example": "sonnet-4-6"
          },
          "training_opt_in": {
            "type": "boolean",
            "nullable": true,
            "default": false
          },
          "bias_axes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true,
            "description": "Archetype/bias hints that weight persona sampling toward matching archetypes (e.g. [\"cfo\",\"finance\"]). Ignored when empty.",
            "example": [
              "cfo",
              "finance"
            ]
          },
          "confidence_mode": {
            "type": "boolean",
            "default": false,
            "description": "High-confidence mode. Resamples each persona's verdict 3x for a per-persona confidence score and a sim-level score band. Charges 3x credits. Off by default."
          },
          "public": {
            "type": "boolean",
            "nullable": true,
            "default": false,
            "description": "Pre-mark the sim as publicly readable. When true and the sim completes, it is viewable without auth at https://kranth.ai/s/{id} and `public_url` is returned. Also flippable later via PATCH /v1/sims/{id}. Off by default (sim ideas are confidential)."
          },
          "redact_input": {
            "type": "boolean",
            "nullable": true,
            "default": false,
            "description": "When true, the public page and OG share card omit the brief (`idea_text`) so the verdict can be shared without exposing the prompt. Off by default. Also flippable via PATCH /v1/sims/{id}."
          }
        }
      },
      "CreateSimResponse": {
        "type": "object",
        "properties": {
          "sim_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string"
          },
          "model_tier": {
            "type": "string"
          },
          "credits_charged": {
            "type": "integer"
          },
          "persona_count": {
            "type": "integer"
          },
          "public_url": {
            "type": "string",
            "nullable": true,
            "description": "Canonical public page URL (https://kranth.ai/s/{id}). Null unless the sim is both public and complete \u2014 always null at create time."
          }
        }
      },
      "Sim": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "org_id": {
            "type": "string",
            "format": "uuid"
          },
          "created_by": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "running",
              "complete",
              "failed",
              "canceled"
            ]
          },
          "idea_text": {
            "type": "string"
          },
          "persona_count": {
            "type": "integer"
          },
          "personas_done": {
            "type": "integer"
          },
          "model_tier": {
            "type": "string"
          },
          "credits_charged": {
            "type": "integer"
          },
          "avg_sentiment": {
            "type": "number",
            "nullable": true,
            "description": "Weighted average of every persona's sentiment (-1.0 hostile to +1.0 fully aligned; null while running). Hostile reactions (<= -0.3) count 1.5x. Convert to the 0-100 display score with (avg_sentiment + 1) * 50 \u2014 50 is neutral. A synthetic signal from an adversarial audience, not a prediction of real-world reception."
          },
          "error_message": {
            "type": "string",
            "nullable": true
          },
          "started_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "public": {
            "type": "boolean"
          },
          "redact_input": {
            "type": "boolean"
          },
          "public_url": {
            "type": "string",
            "nullable": true,
            "description": "Canonical public page URL (https://kranth.ai/s/{id}). Null unless the sim is both public and complete."
          }
        }
      },
      "ApiKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "prefix": {
            "type": "string"
          },
          "last_used_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "revoked_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Settings": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "training_opt_in": {
            "type": "boolean"
          },
          "plan_slug": {
            "type": "string"
          }
        }
      },
      "Usage": {
        "type": "object",
        "properties": {
          "plan": {
            "type": "string"
          },
          "monthly_cap": {
            "type": "integer"
          },
          "credits_consumed": {
            "type": "integer"
          },
          "credits_remaining": {
            "type": "integer"
          },
          "period_start": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CreateReconRequest": {
        "type": "object",
        "required": [
          "idea_text",
          "tier"
        ],
        "properties": {
          "idea_text": {
            "type": "string",
            "maxLength": 10000
          },
          "tier": {
            "type": "string",
            "enum": [
              "quick",
              "standard",
              "deep"
            ]
          },
          "audience": {
            "type": "string",
            "enum": [
              "founder",
              "researcher",
              "agency"
            ],
            "nullable": true
          },
          "company_url": {
            "type": "string",
            "nullable": true
          },
          "worker_model": {
            "type": "string",
            "nullable": true
          },
          "synth_model": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "CreateReconResponse": {
        "type": "object",
        "properties": {
          "recon_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string"
          },
          "tier": {
            "type": "string"
          },
          "credits_charged": {
            "type": "integer"
          }
        }
      },
      "ReconTier": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string",
            "example": "standard"
          },
          "label": {
            "type": "string",
            "example": "Standard"
          },
          "worker_count": {
            "type": "integer"
          },
          "price_credits": {
            "type": "integer"
          }
        }
      },
      "ReconSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "running",
              "complete",
              "failed"
            ]
          },
          "idea_text": {
            "type": "string"
          },
          "tier": {
            "type": "string"
          },
          "score": {
            "type": "integer",
            "nullable": true,
            "description": "0\u2013100 overall grounding score."
          },
          "credits_charged": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "supported": {
            "type": "integer",
            "nullable": true
          },
          "contradicted": {
            "type": "integer",
            "nullable": true
          },
          "neutral": {
            "type": "integer",
            "nullable": true
          },
          "source_domains": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "ReconCompetitor": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "what": {
            "type": "string"
          },
          "angle": {
            "type": "string"
          },
          "metric": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "business_model": {
            "type": "string"
          },
          "valuation": {
            "type": "string",
            "nullable": true
          },
          "revenue": {
            "type": "string",
            "nullable": true
          },
          "employees": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "ReconReport": {
        "type": "object",
        "properties": {
          "summary": {
            "type": "string"
          },
          "themes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "top_risks": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "competitors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ReconCompetitor"
            }
          }
        }
      },
      "ReconFinding": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "agent_role": {
            "type": "string"
          },
          "claim": {
            "type": "string"
          },
          "grounding": {
            "type": "integer",
            "enum": [
              -1,
              0,
              1
            ],
            "description": "1 = supported, 0 = neutral, -1 = contradicted."
          }
        }
      },
      "ReconSource": {
        "type": "object",
        "properties": {
          "finding_id": {
            "type": "string",
            "format": "uuid"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "title": {
            "type": "string"
          },
          "snippet": {
            "type": "string"
          }
        }
      },
      "ReconRun": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "running",
              "complete",
              "failed"
            ]
          },
          "idea_text": {
            "type": "string"
          },
          "tier": {
            "type": "string"
          },
          "score": {
            "type": "integer",
            "nullable": true
          },
          "credits_charged": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "supported": {
            "type": "integer",
            "nullable": true
          },
          "contradicted": {
            "type": "integer",
            "nullable": true
          },
          "neutral": {
            "type": "integer",
            "nullable": true
          },
          "source_domains": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "report": {
            "$ref": "#/components/schemas/ReconReport",
            "nullable": true
          }
        }
      },
      "ReconDetail": {
        "type": "object",
        "properties": {
          "run": {
            "$ref": "#/components/schemas/ReconRun"
          },
          "findings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ReconFinding"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ReconSource"
            }
          }
        }
      },
      "CreateDebateRequest": {
        "type": "object",
        "required": [
          "topic",
          "mode"
        ],
        "properties": {
          "topic": {
            "type": "string",
            "minLength": 1,
            "maxLength": 500
          },
          "mode": {
            "type": "string",
            "example": "parliament"
          },
          "participants": {
            "type": "integer",
            "nullable": true
          },
          "model_id": {
            "type": "string",
            "nullable": true
          },
          "training_opt_in": {
            "type": "boolean",
            "nullable": true
          },
          "public": {
            "type": "boolean",
            "nullable": true
          },
          "voice_enabled": {
            "type": "boolean",
            "nullable": true
          },
          "archetype_slugs": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          }
        }
      },
      "DebateRow": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "topic": {
            "type": "string"
          },
          "mode": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "running",
              "complete",
              "failed",
              "canceled"
            ]
          },
          "participants": {
            "type": "integer"
          },
          "max_turns": {
            "type": "integer"
          },
          "duration_secs": {
            "type": "integer"
          },
          "model_id": {
            "type": "string"
          },
          "error_message": {
            "type": "string",
            "nullable": true
          },
          "started_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "public": {
            "type": "boolean"
          },
          "turn_count": {
            "type": "integer"
          },
          "voice_enabled": {
            "type": "boolean"
          },
          "score": {
            "type": "integer",
            "nullable": true
          },
          "public_url": {
            "type": "string",
            "nullable": true,
            "description": "Canonical public page URL (https://kranth.ai/d/{id}). Null unless the debate is both public and complete."
          }
        }
      },
      "SpeakerPreview": {
        "type": "object",
        "properties": {
          "speaker_name": {
            "type": "string"
          },
          "speaker_username": {
            "type": "string"
          },
          "speaker_archetype": {
            "type": "string"
          }
        }
      },
      "DebateTurn": {
        "type": "object",
        "properties": {
          "speaker_id": {
            "type": "string"
          },
          "speaker_archetype": {
            "type": "string"
          },
          "speaker_name": {
            "type": "string"
          },
          "speaker_username": {
            "type": "string"
          },
          "role": {
            "type": "string"
          },
          "body": {
            "type": "string"
          },
          "emitted_at": {
            "type": "string",
            "format": "date-time"
          },
          "audio_url": {
            "type": "string",
            "nullable": true
          },
          "audio_voice_id": {
            "type": "string",
            "nullable": true
          },
          "audio_ms": {
            "type": "integer",
            "nullable": true
          }
        }
      },
      "DebateSynthesis": {
        "type": "object",
        "properties": {
          "score": {
            "type": "integer"
          },
          "pct_for": {
            "type": "integer"
          },
          "pct_against": {
            "type": "integer"
          },
          "pct_undecided": {
            "type": "integer"
          },
          "verdict_reasons": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "decisive_argument": {
            "type": "string"
          },
          "top_unrebutted": {
            "type": "string"
          },
          "summary": {
            "type": "string"
          },
          "key_arguments": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "key_objections": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "common_ground": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "strongest_turn": {
            "type": "string"
          },
          "model_id": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "AudienceReaction": {
        "type": "object",
        "properties": {
          "persona_id": {
            "type": "string"
          },
          "speaker_name": {
            "type": "string"
          },
          "archetype": {
            "type": "string"
          },
          "body": {
            "type": "string"
          },
          "sentiment": {
            "type": "number",
            "description": "Float sentiment score."
          },
          "sentiment_label": {
            "type": "string"
          },
          "turn_seq": {
            "type": "integer"
          }
        }
      },
      "DebateDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/DebateRow"
          },
          {
            "type": "object",
            "properties": {
              "synthesis": {
                "$ref": "#/components/schemas/DebateSynthesis",
                "nullable": true
              },
              "audience": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/AudienceReaction"
                }
              }
            }
          }
        ]
      },
      "WebhookEvent": {
        "type": "string",
        "description": "Canonical event name. Unknown values are rejected with 422 on both create and patch.",
        "enum": [
          "sim.complete",
          "sim.failed",
          "sim.canceled",
          "debate.complete",
          "recon.complete",
          "recon.failed",
          "plan.change",
          "credits.topup",
          "credits.low",
          "member.invite",
          "apikey.revoke"
        ]
      },
      "CreateWebhookRequest": {
        "type": "object",
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Must start with http(s)://. Rejected if it resolves to localhost / private / link-local / cloud-metadata addresses (SSRF guard, re-checked at every delivery via DNS re-resolution)."
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEvent"
            },
            "default": []
          }
        }
      },
      "PatchWebhookRequest": {
        "type": "object",
        "properties": {
          "active": {
            "type": "boolean",
            "nullable": true,
            "description": "false pauses delivery without deleting the endpoint."
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEvent"
            },
            "nullable": true,
            "description": "Replaces the full subscription list."
          }
        }
      },
      "WebhookDelivery": {
        "type": "object",
        "properties": {
          "ts": {
            "type": "string",
            "format": "date-time"
          },
          "status_code": {
            "type": "integer",
            "description": "0 = transport error / timeout, no response received."
          },
          "latency_ms": {
            "type": "integer"
          },
          "event": {
            "type": "string"
          }
        }
      },
      "Webhook": {
        "type": "object",
        "description": "Every delivery is HMAC-SHA256-signed with the endpoint's signing_secret, keyed over `v0:{x-kranth-timestamp}:{raw body}`, and sent as header `x-kranth-signature: v0=<hex>` alongside `x-kranth-event` and `x-kranth-timestamp` (unix seconds). Verify by recomputing the HMAC over the raw body and rejecting timestamps more than 300s old. 8s delivery timeout; on failure, retries fire at 5s / 30s / 300s (up to 3 retries). After 25 consecutive failed deliveries the endpoint is auto-disabled (active=false) \u2014 re-enable via PATCH.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEvent"
            }
          },
          "active": {
            "type": "boolean"
          },
          "last_delivered_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "last_response_code": {
            "type": "integer",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "success_count": {
            "type": "integer"
          },
          "fail_count": {
            "type": "integer"
          },
          "avg_response_ms": {
            "type": "integer"
          },
          "daily_deliveries": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "14 slots; not yet backfilled by a rollup worker (always zeros today)."
          },
          "recent": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookDelivery"
            },
            "description": "12 most recent delivery attempts, newest first."
          }
        }
      },
      "CreatedWebhook": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Webhook"
          },
          {
            "type": "object",
            "properties": {
              "signing_secret": {
                "type": "string",
                "description": "The HMAC signing key. Returned exactly once, on creation \u2014 store it immediately. Not retrievable again."
              }
            }
          }
        ]
      }
    }
  }
}
