{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/classifier-dev/json-schema/classifier-dev-classify-response-schema.json",
  "title": "ClassifyResponse",
  "x-generated": "2026-10-29",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/classifier-dev-openapi.json#/components/schemas/ClassifyResponse",
  "type": "object",
  "properties": {
    "pricing": {
      "$ref": "#/$defs/ClassificationPricing"
    },
    "article": {
      "type": "object",
      "properties": {
        "url": {
          "type": "string"
        },
        "title": {
          "type": "string"
        },
        "markdown": {
          "type": "string"
        },
        "html": {
          "type": "string"
        }
      }
    },
    "tier": {
      "type": "string"
    },
    "model": {
      "type": "string",
      "description": "The model used for every result, or `mixed` when the batch used more than one model."
    },
    "modelsUsed": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Every model that served at least one result, in first-use order."
    },
    "results": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "dimensions": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/$defs/DimensionResult"
            },
            "description": "Dimensions mode: one field result per supplied dimension, in an input-ordered results array."
          },
          "label": {
            "type": "string"
          },
          "confidence": {
            "type": [
              "number",
              "null"
            ]
          },
          "scores": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {
              "type": "number"
            }
          },
          "unscored": {
            "type": "string"
          },
          "escalated": {
            "type": "boolean"
          },
          "labels": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Multi-label mode only, in place of `label`: every label scoring >= 0.7, most likely first."
          },
          "ms": {
            "type": "integer"
          },
          "model": {
            "type": "string"
          }
        }
      }
    },
    "usage": {
      "type": "object",
      "allOf": [
        {
          "$ref": "#/$defs/TokenUsage"
        }
      ],
      "properties": {
        "items": {
          "type": "integer",
          "description": "Dimensions mode: number of input items."
        },
        "dimensions": {
          "type": "integer",
          "description": "Dimensions mode: number of fields per item."
        },
        "fallback": {
          "type": "integer",
          "description": "Dimensions mode: fields served by the LLM fallback because Jev was unavailable."
        },
        "classifications": {
          "type": "integer",
          "description": "Decisions made. In dimensions mode, items multiplied by dimensions; each counts toward the quota."
        },
        "escalated": {
          "type": "integer",
          "description": "How many answers the smart tier re-asked."
        },
        "escalation_failed": {
          "type": "integer",
          "description": "Present only when some smart-tier re-asks could not reach the reasoning model; those results carry the fast answer without `escalated`."
        },
        "ms": {
          "type": "integer"
        }
      }
    }
  },
  "$defs": {
    "ClassificationPricing": {
      "type": "object",
      "description": "USD customer pricing, separate from upstream provider spend. total_usd is zero for unbilled requests, null when unknown, and before credit rounding. Pending settlement is not a receipt. Ordinary pricing.input_tokens includes billable primary calls; Jev long context uses original cl100k_base context tokens summed once across inputs at $0.084/M, independent of dimensions and actual screening/final usage. Plain-text responses and TypeSafe-compatible responses retain their existing shapes.",
      "properties": {
        "scrape_requests": {
          "type": "integer",
          "minimum": 0,
          "maximum": 1
        },
        "usd_per_scrape": {
          "type": "number",
          "const": 0.0022
        },
        "scrape_usd": {
          "type": "number",
          "description": "Retained scrape charge, including on errors after a billed or uncertain provider attempt."
        },
        "classification_usd": {
          "type": [
            "number",
            "null"
          ]
        },
        "currency": {
          "const": "USD"
        },
        "rate_version": {
          "type": "string"
        },
        "basis": {
          "type": "string",
          "const": "original_context_tokens",
          "description": "Present for Jev long context."
        },
        "tokenizer": {
          "type": "string",
          "const": "cl100k_base",
          "description": "Present for Jev long-context billing."
        },
        "billing_status": {
          "enum": [
            "not_billed",
            "pending",
            "settled",
            "review"
          ]
        },
        "total_usd": {
          "type": [
            "number",
            "null"
          ]
        },
        "estimated_usd": {
          "type": [
            "number",
            "null"
          ],
          "description": "Published classification price before free access or settlement; not an additional charge."
        },
        "input_tokens": {
          "type": [
            "integer",
            "null"
          ]
        },
        "escalations": {
          "type": "integer"
        },
        "input_usd_per_million": {
          "type": "number"
        },
        "usd_per_escalation": {
          "type": "number"
        },
        "models": {
          "type": "array",
          "description": "Legacy token-billed workspaces: the applied rate per provider/model, instead of the input-plus-escalation tariff.",
          "items": {
            "type": "object",
            "properties": {
              "provider": {
                "type": "string"
              },
              "model": {
                "type": "string"
              },
              "input_usd_per_million": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "output_usd_per_million": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "cached_input_usd_per_million": {
                "type": [
                  "number",
                  "null"
                ]
              }
            }
          }
        }
      }
    },
    "DimensionResult": {
      "type": "object",
      "required": [
        "label",
        "confidence",
        "scores",
        "model",
        "ms"
      ],
      "properties": {
        "label": {
          "type": "string"
        },
        "confidence": {
          "type": [
            "number",
            "null"
          ],
          "minimum": 0,
          "maximum": 1,
          "description": "Jev's distribution-derived confidence. Null when the provider returns no score or after smart escalation; not a literal probability of correctness."
        },
        "scores": {
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "description": "Model preference per supplied label; does not validate the input or guarantee correctness."
        },
        "model": {
          "type": "string"
        },
        "ms": {
          "type": "integer"
        },
        "escalated": {
          "type": "boolean"
        },
        "unscored": {
          "type": "string"
        }
      }
    },
    "LongContextUsage": {
      "type": "object",
      "description": "Jev long-context processing totals. Documents/context tokens count original inputs once; chunk and selection counts and phase usage accumulate across dimension passes, not necessarily unique passages. Calls count answered provider calls, not attempts. Unknown provider token counts remain null. When every original plus its rubric and labels fits the provider budget, all originals reach final Jev in full, counted by full_input_passes. Otherwise every input is screened and final Jev sees selected evidence; eligible whole chunks may be omitted when the final context budget fills. No guarantee of universal accuracy.",
      "properties": {
        "context_tokens": {
          "type": "integer",
          "minimum": 0,
          "description": "Original input cl100k_base tokens summed once across inputs, independent of dimensions. Retail basis at $0.084/M, not actual screening/final usage."
        },
        "documents": {
          "type": "integer",
          "minimum": 0
        },
        "chunks": {
          "type": "integer",
          "minimum": 0
        },
        "screened_chunks": {
          "type": "integer",
          "minimum": 0
        },
        "eligible_chunks": {
          "type": "integer",
          "minimum": 0,
          "description": "Relevant or uncertain chunks eligible for final classification, including opposing evidence and exceptions."
        },
        "selected_chunks": {
          "type": "integer",
          "minimum": 0
        },
        "omitted_chunks": {
          "type": "integer",
          "minimum": 0,
          "description": "Eligible chunks omitted from final evidence due to context limits."
        },
        "full_input_passes": {
          "type": "integer",
          "minimum": 0,
          "description": "Successful final passes over complete originals when every input in the batch fits the Jev wire budget including rubric and labels. Counts document × dimension passes; these passes skip screening and omit no text. Original-context pricing is unchanged."
        },
        "screening_input_tokens": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0
        },
        "final_input_tokens": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0
        },
        "screening_calls": {
          "type": "integer",
          "minimum": 0
        },
        "final_calls": {
          "type": "integer",
          "minimum": 0
        },
        "screening_ms": {
          "type": "number",
          "minimum": 0
        },
        "final_ms": {
          "type": "number",
          "minimum": 0
        },
        "tokenizer": {
          "type": "string",
          "const": "cl100k_base"
        }
      }
    },
    "TokenUsage": {
      "type": "object",
      "properties": {
        "long_context": {
          "$ref": "#/$defs/LongContextUsage"
        },
        "input_tokens": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Provider-reported input tokens across all answered calls, including smart escalation. Null if any count is unavailable."
        },
        "output_tokens": {
          "type": [
            "integer",
            "null"
          ]
        },
        "total_tokens": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Input plus output; null if either is unknown."
        },
        "cached_input_tokens": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Subset of input tokens, never added again to total_tokens."
        },
        "models": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "provider": {
                "type": "string"
              },
              "model": {
                "type": "string"
              },
              "calls": {
                "type": "integer"
              },
              "input_tokens": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "output_tokens": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "cached_input_tokens": {
                "type": [
                  "integer",
                  "null"
                ]
              }
            }
          }
        }
      }
    }
  }
}