{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/classifier-dev/json-schema/classifier-dev-classify-request-schema.json",
  "title": "ClassifyRequest",
  "description": "Long-context limits count documents × dimensions, or documents × labels in multi-label mode, as decisions (maximum 32). Long-context instructions are limited to 4,000 characters and labels to 200 characters each. Existing dedicated enterprise/operator access remains a trusted operational exception to the public funding requirement.",
  "x-generated": "2026-10-29",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/classifier-dev-openapi.json#/components/schemas/ClassifyRequest",
  "type": "object",
  "oneOf": [
    {
      "required": [
        "labels"
      ],
      "not": {
        "required": [
          "dimensions"
        ]
      }
    },
    {
      "required": [
        "dimensions"
      ],
      "not": {
        "anyOf": [
          {
            "required": [
              "labels"
            ]
          },
          {
            "required": [
              "multi"
            ]
          },
          {
            "required": [
              "max_labels"
            ]
          }
        ]
      }
    }
  ],
  "dependentRequired": {
    "include": [
      "url"
    ]
  },
  "allOf": [
    {
      "if": {
        "required": [
          "url"
        ]
      },
      "then": {
        "not": {
          "anyOf": [
            {
              "required": [
                "input"
              ]
            },
            {
              "required": [
                "inputs"
              ]
            },
            {
              "required": [
                "items"
              ]
            }
          ]
        }
      }
    }
  ],
  "properties": {
    "url": {
      "type": "string",
      "format": "uri",
      "maxLength": 8192,
      "description": "One public HTTP(S) URL instead of input/inputs/items. Requires a funded workspace key and sufficient balance. Context.dev scrapes once for $0.0022 per provider-billed attempt plus classification. Only Jev; long articles use Fast tier. No OCR. Up to 8 MB response and 250,000 tokens, never silently truncated. Successful scrapes and uncertain dispatched attempts remain charged even if classification fails; inspect pricing on errors."
    },
    "include": {
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "markdown",
          "html"
        ]
      },
      "description": "With url only: opt into article.markdown and/or article.html. Both formats share one scrape; no extra fee. Omit for compact classification results. Treat HTML as untrusted."
    },
    "model": {
      "type": "string",
      "enum": [
        "jev",
        "laya",
        "kev",
        "chunklaya"
      ],
      "description": "Defaults to Jev unless processing implies Laya. Default/explicit jev inputs over 32,000 characters use paid Fast-only Jev long context. When every input plus its rubric and labels fits the provider budget, final Jev reads all originals in full. Otherwise every input uses 600-token Chonkie chunks, parallel evidence screening and final Jev over whole eligible chunks in source order, bounded by 20,000 cl100k_base tokens and a conservative provider estimate. Eligible evidence may be omitted; usage.long_context discloses selection. Requires paid workspace balance or active paid subscription, not signup credit. Synchronous limits: 250,000 original cl100k_base tokens, 20 documents, 32 decisions, 1 MB body. One whole document on POST / or /v1/classify supports 10M tokens and 100 MB as a background job. Price: $0.084/M original context tokens summed once across inputs, independent of dimensions and actual inference usage. Explicit chunklaya retains the legacy opt-in (4,000,000 characters/input, 20 inputs, subject to 1 MB body; chunklaya/multilingual results; no Smart). Laya and Kev are experimental Beam models with 512-token and 8,192-token contexts respectively, 2–16 short labels, text ≤2,000 characters and instructions ≤400 characters. Results use jev/laya or jev/kev; Jev calibration claims do not apply."
    },
    "processing": {
      "type": "string",
      "enum": [
        "fast",
        "bulk"
      ],
      "description": "Implies Laya when model is omitted. Accepted but has no effect with explicit model jev, which handles batching automatically. When omitted for Laya, automatically selects fast for one decision with up to 4 yes/no questions, otherwise bulk. Explicit Laya lanes are honored. Fast allows 60 questions/min and 2,000/day per caller. Bulk chunks batches up to 1,000 questions per call, 1,000/min and 20,000/day. These caps also apply to paid/operator keys. Same model weights in both lanes. Overload returns 429; a cold bulk worker returns 503 with Retry-After. Smart review is independent."
    },
    "dimensions": {
      "type": "object",
      "minProperties": 1,
      "maxProperties": 20,
      "propertyNames": {
        "minLength": 1,
        "maxLength": 64,
        "pattern": "\\S"
      },
      "description": "Named dimensions. Each is a label array or {labels, instructions}. At most 1,000 item × dimension decisions; definitions at most 16,000 characters combined.",
      "additionalProperties": {
        "oneOf": [
          {
            "type": "array",
            "minItems": 2,
            "maxItems": 100,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "\\S"
            }
          },
          {
            "type": "object",
            "required": [
              "labels"
            ],
            "additionalProperties": false,
            "properties": {
              "labels": {
                "type": "array",
                "minItems": 2,
                "maxItems": 100,
                "uniqueItems": true,
                "items": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 200,
                  "pattern": "\\S"
                }
              },
              "instructions": {
                "type": "string",
                "maxLength": 4000
              }
            }
          }
        ]
      }
    },
    "items": {
      "type": "array",
      "minItems": 1,
      "maxItems": 1000,
      "items": {
        "type": "string",
        "minLength": 1
      },
      "description": "Alias for inputs. One-element arrays can use whole-document jobs (10M tokens/100 MB, labels only). Synchronous dimensions mode: Default/jev inputs above 32,000 characters use paid long context: at most 20 documents, 32 decisions and 250,000 original context tokens total, within a 1 MB body. Explicit chunklaya allows up to 4,000,000 characters/input within the body limit. Do not combine with input or inputs."
    },
    "input": {
      "type": "string",
      "description": "One complete document. POST / or /v1/classify automatically returns a background job above synchronous limits: up to 10M original tokens and 100 MB. No manual parts needed. Use Prefer: respond-async to request a job at any size. Provide this or inputs."
    },
    "inputs": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "maxItems": 1000,
      "description": "Up to 1,000 texts classified in one call, results in the same order. Synchronous long context allows 20 documents, 32 decisions and 250,000 original context tokens total within 1 MB. One-element arrays on POST / or /v1/classify support automatic jobs up to 10M tokens/100 MB. Public smart requests accept at most 200 so the batch fits its per-minute quota."
    },
    "labels": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "minItems": 2,
      "maxItems": 100,
      "description": "Semantic category names. 'urgent bug' classifies better than 'p0'."
    },
    "tier": {
      "type": "string",
      "enum": [
        "fast",
        "smart"
      ],
      "default": "fast",
      "description": "smart re-asks single-label answers below 0.7 confidence of a reasoning model; multi-label ignores it. Long context and explicit chunklaya refuse smart with 400 bad_tier. Read case-insensitively; any other value is a 400 bad_tier."
    },
    "instructions": {
      "type": "string",
      "description": "Extra criteria for the classifier."
    },
    "share_data": {
      "type": "boolean",
      "default": true,
      "description": "Synchronous classification request text, labels, instructions and model results are retained for model training and operator review in private Cloudflare storage by default. Shared requests receive double per-minute and daily classification quotas. Set share_data: false or X-Classifier-Share-Data: false to opt out and use standard limits. Share only data you have permission to contribute; do not include confidential or personal information. Redaction is best effort. Billing, spending caps and input-size limits still apply."
    },
    "multi": {
      "type": "boolean",
      "description": "Return every label that applies, with a score per label. true, \"true\", 1 and \"1\" all mean yes."
    },
    "max_labels": {
      "type": "integer",
      "minimum": 1,
      "description": "Cap on how many multi-label answers come back; implies multi. A numeric string is read; zero or less means no cap; a fraction is rounded down."
    }
  }
}