openapi: "3.1.0"
info:
  title: "The Token Company Compression API"
  version: "2.2.0"
  summary: "Prompt compression for LLM inputs."
  description: "The Token Company compression API removes low-signal tokens from LLM prompts before\nthey reach the model. One call compresses your input; you pass the compressed text to\nany LLM (GPT, Claude, Gemini, or an OpenAI-compatible endpoint).\n\nCompression is deterministic and delete-only: nothing is summarized, paraphrased, or\ngenerated, so the text that reaches the model stays verbatim and in its original order.\nThat also means a given input and setting always produce the same output, which keeps\nyour prompt caches valid.\n\nAuthentication is a bearer API key. Request one at https://thetokencompany.com/contact.\n\nThis document describes the documented public surface. The Python and TypeScript SDKs\nwrap it, and expose additional convenience fields on their own response objects — see\nhttps://thetokencompany.com/docs/quickstart."
  termsOfService: "https://thetokencompany.com/terms-and-conditions"
  contact:
    name: "The Token Company"
    url: "https://thetokencompany.com/contact"
    email: "team@thetokencompany.com"
externalDocs:
  description: "Documentation"
  url: "https://thetokencompany.com/docs"
servers:
- url: "https://api.thetokencompany.com"
  description: "Production"
security:
- bearerAuth: []
tags:
- name: "compression"
  description: "Compress prompt text before sending it to an LLM."
paths:
  "/v1/compress":
    post:
      operationId: "compressText"
      summary: "Compress a text input"
      description: "Compresses a single input — a string, or an object or array that is JSON-encoded first — and returns the compressed text with before-and-after token counts. Send the result to any LLM in place of the original. Wrap any span in <ttc_safe> tags to exclude it from compression. Aggressiveness guidance: 0.05-0.2 for text the model must answer questions about, 0.5-0.8 for conversation history and background context. If the compression backend is unavailable the API returns the original input unchanged rather than failing, so a compression outage never breaks the calling flow."
      tags:
      - "compression"
      requestBody:
        required: true
        content:
          "application/json":
            schema:
              "$ref": "#/components/schemas/CompressionRequest"
            examples:
              basic:
                summary: "Light compression with bear-2"
                value:
                  model: "bear-2"
                  input: "Your long prompt text..."
                  compression_settings:
                    aggressiveness: 0.2
              protectedSpan:
                summary: "Excluding a span from compression"
                value:
                  model: "bear-2"
                  input: "compression applied here<ttc_safe>but not here</ttc_safe>"
                  compression_settings:
                    aggressiveness: 0.2
              perApp:
                summary: "Tagging usage with an app_id"
                value:
                  model: "bear-2"
                  input: "Your long prompt text..."
                  compression_settings:
                    aggressiveness: 0.2
                  app_id: "my-chatbot"
      responses:
        "200":
          description: "The compressed text and its token counts."
          content:
            "application/json":
              schema:
                "$ref": "#/components/schemas/CompressionResponse"
              examples:
                basic:
                  value:
                    output: "Compressed text here"
                    output_tokens: 5
                    original_input_tokens: 12
        "401":
          "$ref": "#/components/responses/Unauthorized"
        "402":
          "$ref": "#/components/responses/PaymentRequired"
        "413":
          "$ref": "#/components/responses/PayloadTooLarge"
        "422":
          "$ref": "#/components/responses/ValidationError"
        "429":
          "$ref": "#/components/responses/RateLimited"
        "500":
          "$ref": "#/components/responses/ServerError"
        "503":
          "$ref": "#/components/responses/DependencyUnavailable"
components:
  securitySchemes:
    bearerAuth:
      type: "http"
      scheme: "bearer"
      description: "An API key issued by The Token Company, sent as `Authorization: Bearer ttc-...`. Request one at https://thetokencompany.com/contact."
  responses:
    Unauthorized:
      description: "The API key is missing, invalid, or inactive."
      content:
        "application/json":
          schema:
            "$ref": "#/components/schemas/Error"
    PaymentRequired:
      description: "Insufficient balance on the account."
      content:
        "application/json":
          schema:
            "$ref": "#/components/schemas/Error"
    PayloadTooLarge:
      description: "The input exceeds the per-request token limit."
      content:
        "application/json":
          schema:
            "$ref": "#/components/schemas/Error"
    ValidationError:
      description: "The request body failed server-side validation. `detail` is an array with one entry per rejected field."
      content:
        "application/json":
          schema:
            "$ref": "#/components/schemas/ValidationErrorBody"
    RateLimited:
      description: "Too many requests. Retry after a pause."
      content:
        "application/json":
          schema:
            "$ref": "#/components/schemas/Error"
    ServerError:
      description: "Unexpected server error."
      content:
        "application/json":
          schema:
            "$ref": "#/components/schemas/Error"
    DependencyUnavailable:
      description: "A dependency the API needs is unavailable. Retry."
      content:
        "application/json":
          schema:
            "$ref": "#/components/schemas/Error"
  schemas:
    CompressionSettings:
      type: "object"
      description: "How hard to compress."
      properties:
        aggressiveness:
          type: "number"
          format: "float"
          exclusiveMinimum: 0
          exclusiveMaximum: 1
          description: "How much content to remove. Use 0.05-0.2 for text the model reads directly and answers questions about; 0.5-0.8 for conversation history and background context where exact wording matters less. Defaults to 0.2 when omitted."
    CompressionRequest:
      type: "object"
      description: "One input to compress, plus the settings to compress it with."
      properties:
        model:
          type: "string"
          description: "Compression model. `bear-2` is current and recommended; `bear-1.2` is the previous generation."
          examples:
          - "bear-2"
          - "bear-1.2"
        input:
          description: "The content to compress. Objects and arrays are JSON-encoded before compression. Must not be empty."
          oneOf:
          - type: "string"
          - type: "object"
            additionalProperties: true
          - type: "array"
            items: {}
        compression_settings:
          "$ref": "#/components/schemas/CompressionSettings"
        app_id:
          type: "string"
          maxLength: 255
          description: "Your own label for the calling application, so usage can be broken down per app. A per-request value overrides one set on the client."
      required:
      - "model"
      - "input"
    CompressionResponse:
      type: "object"
      description: "The compressed text and its token counts."
      properties:
        output:
          type: "string"
          description: "The compressed text, ready to send to any LLM."
        output_tokens:
          type: "integer"
          description: "Token count after compression."
        original_input_tokens:
          type: "integer"
          description: "Token count of the original input, before compression."
      required:
      - "output"
      - "output_tokens"
      - "original_input_tokens"
    Error:
      type: "object"
      description: "An error returned by the API."
      properties:
        detail:
          description: "A human-readable explanation. Most errors return a plain string; a 402 returns an object carrying `error` and `message`."
          oneOf:
          - type: "string"
          - type: "object"
            properties:
              error:
                type: "string"
                description: "Machine-readable error code, e.g. `account_suspended`."
              message:
                type: "string"
                description: "Human-readable explanation."
            additionalProperties: true
      required:
      - "detail"
    ValidationErrorBody:
      type: "object"
      description: "A request-body validation failure, in FastAPI's shape."
      properties:
        detail:
          type: "array"
          description: "One entry per field that failed validation."
          items:
            type: "object"
            description: "A single rejected field."
            properties:
              loc:
                type: "array"
                description: "Path to the offending field."
                items:
                  oneOf:
                  - type: "string"
                  - type: "integer"
              msg:
                type: "string"
                description: "What is wrong with it."
              type:
                type: "string"
                description: "Validation rule that failed."
            additionalProperties: true
      required:
      - "detail"
