{
  "openapi": "3.1.0",
  "info": {
    "title": "ScaleDown API",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://api.scaledown.xyz"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key"
      }
    }
  },
  "paths": {
    "/compress/raw/": {
      "post": {
        "summary": "Compress",
        "description": "Compress a prompt and context to reduce token usage while preserving semantic meaning.",
        "operationId": "compress",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["context", "prompt", "scaledown"],
                "properties": {
                  "context": {
                    "type": "string",
                    "description": "Background information, instructions, or supporting text that provides context for the prompt."
                  },
                  "prompt": {
                    "type": "string",
                    "description": "The main query or question to send to your AI model."
                  },
                  "scaledown": {
                    "type": "object",
                    "required": ["rate"],
                    "properties": {
                      "rate": {
                        "type": "string",
                        "description": "Compression aggressiveness. Use 'auto' or a number between 0 and 1 for the fraction of tokens to remove (e.g. 0.8 removes about 80% and keeps about 20%)."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful compression",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "results": {
                      "type": "object",
                      "properties": {
                        "success": { "type": "boolean" },
                        "compressed_prompt": { "type": "string", "description": "The compressed context." },
                        "original_prompt": { "type": "string", "description": "The prompt, unchanged." },
                        "original_prompt_tokens": { "type": "number" },
                        "compressed_prompt_tokens": { "type": "number" },
                        "compression_ratio": { "type": "number" }
                      }
                    },
                    "model_used": { "type": "string" },
                    "input_tokens": { "type": "number" },
                    "total_original_tokens": { "type": "number" },
                    "total_compressed_tokens": { "type": "number" },
                    "num_pairs_processed": { "type": "number" },
                    "num_successful": { "type": "number" },
                    "num_failed": { "type": "number" },
                    "successful": { "type": "boolean" },
                    "partially_successful": { "type": "boolean" },
                    "latency_ms": { "type": "number" },
                    "request_metadata": {
                      "type": "object",
                      "properties": {
                        "compression_time_ms": { "type": "number" },
                        "compression_rate": {
                          "oneOf": [
                            { "type": "string" },
                            { "type": "number" }
                          ]
                        },
                        "average_compression_ratio": { "type": "number" }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": { "description": "Malformed request body or missing required fields." },
          "401": { "description": "Missing or invalid x-api-key." },
          "429": { "description": "Rate limit exceeded." },
          "500": { "description": "Compression service unavailable." }
        }
      }
    },
    "/classify": {
      "post": {
        "summary": "Classify",
        "description": "Score text against a set of user-defined labels and return a softmax-normalised probability distribution.",
        "operationId": "classify",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["text", "labels"],
                "properties": {
                  "text": {
                    "type": "string",
                    "description": "The text to classify."
                  },
                  "labels": {
                    "type": "array",
                    "description": "One or more label definitions. Must contain at least one item.",
                    "items": {
                      "type": "object",
                      "required": ["name", "rubric"],
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "Short identifier for the label (e.g. \"medical\", \"billing\"). Used as the key in the scores response object."
                        },
                        "rubric": {
                          "type": "string",
                          "description": "A yes/no question the model uses to score the label. Phrased so that a \"yes\" answer means the label applies."
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful classification",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "top_label": {
                      "type": "string",
                      "description": "Name of the highest-scoring label."
                    },
                    "scores": {
                      "type": "object",
                      "description": "Map of label name to probability score. All values sum to 1.0.",
                      "additionalProperties": { "type": "number" }
                    },
                    "labels": {
                      "type": "array",
                      "description": "Full label list with name, score, and rubric, in the same order as the request.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "label": { "type": "string" },
                          "score": { "type": "number" },
                          "rubric": { "type": "string" }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "422": { "description": "Malformed request body or empty labels array." },
          "502": { "description": "Model service unavailable or returned an error." }
        }
      }
    },
    "/v1/scaledown": {
      "post": {
        "summary": "Decisions",
        "description": "Jev (TypeSafe)-compatible endpoint: answer typed choice/noul/score questions about a shared state object.",
        "operationId": "decisions",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["state", "questions"],
                "properties": {
                  "model": {
                    "type": "string",
                    "enum": ["classify-1"],
                    "default": "classify-1",
                    "description": "Optional. \"classify-1\" is the only supported value and also the default when omitted. Any other value returns 422."
                  },
                  "state": {
                    "description": "The item being decided on. A plain string is shorthand for {\"text\": \"...\"}.",
                    "oneOf": [
                      { "type": "string" },
                      {
                        "type": "object",
                        "description": "The item being decided on. Provide text, document, or both.",
                        "properties": {
                          "text": {
                            "type": "string",
                            "description": "The text to evaluate every question against."
                          },
                          "document": {
                            "type": "string",
                            "description": "A base64-encoded file to evaluate (image or PDF). Non-standard extension, not part of the Jev API."
                          },
                          "document_mime_type": {
                            "type": "string",
                            "description": "MIME type of document. Required when document is provided."
                          }
                        }
                      }
                    ]
                  },
                  "questions": {
                    "type": "object",
                    "description": "Map of question name to question definition. Must contain at least one entry.",
                    "additionalProperties": {
                      "type": "object",
                      "required": ["type"],
                      "properties": {
                        "type": {
                          "type": "string",
                          "enum": ["choice", "noul", "score"],
                          "description": "choice: pick one mutually-exclusive option from criteria. noul: independent yes/no question. score: an ordered-scale question, answered as a position on the scale."
                        },
                        "instructions": {
                          "type": "string",
                          "description": "Optional guidance for how to answer the question."
                        },
                        "criteria": {
                          "description": "Required for choice questions: object mapping option key to description (at least one entry). Required for score questions: ORDERED array of 2-10 level descriptions, lowest to highest (level index = array position). Ignored for noul questions.",
                          "oneOf": [
                            {
                              "type": "object",
                              "additionalProperties": { "type": "string" }
                            },
                            {
                              "type": "array",
                              "items": { "type": "string" },
                              "minItems": 2,
                              "maxItems": 10
                            }
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful decision",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "model": {
                      "type": "string",
                      "description": "Always \"classify-1\"."
                    },
                    "answers": {
                      "type": "object",
                      "description": "Map of question name to typed answer, matching the questions keys from the request.",
                      "additionalProperties": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "enum": ["choice", "noul", "score"]
                          },
                          "choice": {
                            "type": "string",
                            "description": "choice answers only: the chosen option key."
                          },
                          "probabilities": {
                            "type": "object",
                            "description": "choice/score answers only: map of option key (choice) or level index as a string (score) to probability. Sums to 1.0.",
                            "additionalProperties": { "type": "number" }
                          },
                          "confidence": {
                            "type": "number",
                            "description": "choice/score answers only: the chosen option's, or top level's, probability."
                          },
                          "noul": {
                            "type": "number",
                            "description": "noul answers only: P(yes), 0 to 1."
                          },
                          "score": {
                            "type": "number",
                            "description": "score answers only: probability-weighted expected value across level indices (sum of level_index * probability). A continuous position on the scale, not necessarily a whole level."
                          },
                          "legend": {
                            "type": "object",
                            "description": "score answers only: map of level index (as a string) to its criteria description, echoing the request's criteria back for display.",
                            "additionalProperties": { "type": "string" }
                          }
                        }
                      }
                    },
                    "usage": {
                      "type": "object",
                      "description": "Token usage and cost, summed across every internal call the request fanned out to.",
                      "properties": {
                        "input_tokens": { "type": "integer" },
                        "output_tokens": { "type": "integer" },
                        "cost": { "type": "number" }
                      }
                    }
                  }
                }
              }
            }
          },
          "402": { "description": "Insufficient credits." },
          "422": { "description": "Malformed request body, empty questions map, empty criteria on a choice question, a score question's criteria outside the 2-10 item range, neither state.text nor state.document provided, an unsupported model value, or the document could not be read." },
          "502": { "description": "Model service unavailable or returned an error." },
          "504": { "description": "Request timed out." }
        }
      }
    }
  }
}
