{
  "openapi": "3.1.0",
  "info": {
    "title": "Ask To It Decision API",
    "version": "1.0.0",
    "description": "Structured Jev decisions. Get a key at https://askto.it/developers/. Free keys allow 20 standard decisions per UTC day; funded passes cover additional reads and stress tests. Call this API from a server."
  },
  "servers": [{ "url": "https://askto.it" }],
  "components": {
    "securitySchemes": {
      "apiKey": { "type": "http", "scheme": "bearer", "bearerFormat": "askto_api_ token" }
    },
    "schemas": {
      "DecisionRequest": {
        "type": "object",
        "required": ["mode", "question", "context"],
        "properties": {
          "mode": { "type": "string", "enum": ["choice", "noul", "score"] },
          "question": { "type": "string", "minLength": 8, "maxLength": 300 },
          "context": { "type": "string", "minLength": 20, "maxLength": 2000 },
          "options": { "type": "array", "minItems": 2, "maxItems": 6, "items": { "type": "string", "minLength": 2, "maxLength": 100 }, "description": "Required for choice mode. Names must be distinct." },
          "levels": { "type": "array", "minItems": 3, "maxItems": 3, "items": { "type": "string", "minLength": 2, "maxLength": 100 }, "description": "Required for score mode, ordered low to high." },
          "depth": { "type": "string", "enum": ["standard", "stress"], "default": "standard", "description": "Stress costs 5 pass credits; standard uses the free allowance first, then 1 pass credit." }
        }
      },
      "DecisionResponse": {
        "type": "object",
        "required": ["mode", "question", "result", "signal", "contextSufficiency", "model", "evaluatedAt", "access", "timing"],
        "properties": {
          "mode": { "type": "string", "enum": ["choice", "noul", "score"] },
          "question": { "type": "string" },
          "signal": { "type": "string", "enum": ["directional", "yes", "no", "unclear", "needs-context"] },
          "result": { "type": "object", "description": "Choice: selected, confidence, probabilities. Noul: yesProbability. Score: score, confidence, probabilities." },
          "contextSufficiency": { "type": "number", "minimum": 0, "maximum": 1 },
          "model": { "type": "string" },
          "inputTokens": { "type": ["integer", "null"] },
          "evaluatedAt": { "type": "string", "format": "date-time" },
          "access": { "type": "object", "description": "Free: type and freeRemaining. Pass: type and passCredits." },
          "stress": { "type": ["object", "null"], "description": "Agreement, checks and pivot when a stress test was requested." },
          "timing": {
            "type": "object",
            "required": ["processingMs", "averageMsToday", "samplesToday"],
            "properties": {
              "processingMs": { "type": "integer", "description": "This request's server processing time, including Jev, excluding the caller network." },
              "averageMsToday": { "type": ["integer", "null"], "description": "Average successful API decision processing time in the current UTC day." },
              "samplesToday": { "type": ["integer", "null"] }
            }
          }
        }
      },
      "Error": { "type": "object", "required": ["error"], "properties": { "error": { "type": "string" }, "code": { "type": "string" } } }
    }
  },
  "paths": {
    "/v1/decisions": {
      "post": {
        "summary": "Make a structured decision",
        "security": [{ "apiKey": [] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DecisionRequest" } } } },
        "responses": {
          "200": { "description": "Decision with measured processing time", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DecisionResponse" } } } },
          "400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "Missing or revoked key" },
          "402": { "description": "Stress test requires a funded pass" },
          "429": { "description": "Daily free allowance exhausted or Jev busy" },
          "502": { "description": "Jev response unavailable or incomplete" },
          "503": { "description": "Decision service temporarily unavailable" },
          "504": { "description": "Decision timed out" }
        }
      }
    },
    "/v1/usage": {
      "get": {
        "summary": "Get today's API allowance and linked pass balance",
        "security": [{ "apiKey": [] }],
        "responses": { "200": { "description": "UTC day, free limit and remaining, pass credits" }, "401": { "description": "Missing or revoked key" } }
      }
    },
    "/v1/metrics": {
      "get": {
        "summary": "Get measured successful decision processing times for the current UTC day",
        "responses": { "200": { "description": "Overall, web and API sample counts and mean milliseconds; null when no samples" } }
      }
    },
    "/v1/key": {
      "delete": {
        "summary": "Revoke the current API key",
        "security": [{ "apiKey": [] }],
        "responses": { "200": { "description": "Key revoked" }, "401": { "description": "Missing or revoked key" } }
      }
    }
  }
}
