{
  "components": {
    "schemas": {
      "AddPositionsRequest": {
        "description": "The body of ``POST /v1/portfolios/{id}/positions``: one or more positions to add.",
        "properties": {
          "positions": {
            "items": {
              "$ref": "#/components/schemas/PositionInput"
            },
            "minItems": 1,
            "title": "Positions",
            "type": "array"
          }
        },
        "required": [
          "positions"
        ],
        "title": "AddPositionsRequest",
        "type": "object"
      },
      "AlertList": {
        "description": "The response to ``GET /v1/portfolios/{id}/alerts``.",
        "properties": {
          "alerts": {
            "items": {
              "$ref": "#/components/schemas/AlertOut"
            },
            "title": "Alerts",
            "type": "array"
          }
        },
        "required": [
          "alerts"
        ],
        "title": "AlertList",
        "type": "object"
      },
      "AlertOut": {
        "description": "One covenant alert row (``asOf`` derives from the eval asOf; ``createdAt`` is metadata).",
        "properties": {
          "asOf": {
            "title": "Asof",
            "type": "string"
          },
          "createdAt": {
            "title": "Createdat",
            "type": "string"
          },
          "detail": {
            "title": "Detail",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "kind": {
            "title": "Kind",
            "type": "string"
          },
          "positionId": {
            "title": "Positionid",
            "type": "string"
          }
        },
        "required": [
          "id",
          "positionId",
          "kind",
          "detail",
          "asOf",
          "createdAt"
        ],
        "title": "AlertOut",
        "type": "object"
      },
      "BandOut": {
        "description": "A p10 <= p50 <= p90 triple (SoH percent, a collateral multiplier, or an INR value).",
        "properties": {
          "p10": {
            "title": "P10",
            "type": "number"
          },
          "p50": {
            "title": "P50",
            "type": "number"
          },
          "p90": {
            "title": "P90",
            "type": "number"
          }
        },
        "required": [
          "p10",
          "p50",
          "p90"
        ],
        "title": "BandOut",
        "type": "object"
      },
      "BehaviorDriver": {
        "additionalProperties": false,
        "description": "One usage driver behind the charging-behavior forward-risk read.\n\nReports a single observed usage habit (the DC fast-charge share, the mean depth of\ndischarge, or the mean pack temperature) as its observed value, a 0..100 sub-score\n(higher = harder use, a monotone map of the value), and a one-line rationale (see\nbehavior.py). Field aliases are camelCase to match the contract.",
        "properties": {
          "kind": {
            "enum": [
              "fast_charge",
              "depth_of_discharge",
              "thermal_exposure"
            ],
            "title": "Kind",
            "type": "string"
          },
          "label": {
            "minLength": 1,
            "title": "Label",
            "type": "string"
          },
          "observedValue": {
            "title": "Observedvalue",
            "type": "number"
          },
          "rationale": {
            "minLength": 1,
            "title": "Rationale",
            "type": "string"
          },
          "subScore": {
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Subscore",
            "type": "number"
          }
        },
        "required": [
          "kind",
          "label",
          "observedValue",
          "subScore",
          "rationale"
        ],
        "title": "BehaviorDriver",
        "type": "object"
      },
      "BehaviorRisk": {
        "additionalProperties": false,
        "description": "A HEURISTIC charging-behavior forward-risk read on top of the observed usage.\n\nMaps a pack's observed usage habits (the DC fast-charge share, the mean depth of\ndischarge, and the mean pack temperature) into a coarse tier and a continuous 0 to\n100 index for an insurer or lessor pricing a battery-behavior product. It is a\nLEADING read of how HARD the pack is being used, distinct from the current-state SoH\nand NOT feeding it or any other score product (see behavior.py).\n\nThis is NOT an actuarial premium, a probability of a claim, or a measured\ncapacity-loss rate: no claim or realized-degradation experience has been fit; the\nmapping curves are labeled working assumptions. ``basis`` states this verbatim and\ntravels with the read so the disclaimer cannot be dropped downstream. ``score`` is\nmonotonic with ``tier`` (a higher score never maps to a lower tier).",
        "properties": {
          "assumptions": {
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "title": "Assumptions",
            "type": "array"
          },
          "basis": {
            "minLength": 1,
            "title": "Basis",
            "type": "string"
          },
          "components": {
            "items": {
              "$ref": "#/components/schemas/BehaviorDriver"
            },
            "minItems": 1,
            "title": "Components",
            "type": "array"
          },
          "score": {
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Score",
            "type": "number"
          },
          "tier": {
            "enum": [
              "low",
              "moderate",
              "elevated",
              "high"
            ],
            "title": "Tier",
            "type": "string"
          }
        },
        "required": [
          "score",
          "tier",
          "components",
          "assumptions",
          "basis"
        ],
        "title": "BehaviorRisk",
        "type": "object"
      },
      "CertificateList": {
        "description": "The response to ``GET /v1/certificates``.",
        "properties": {
          "certificates": {
            "items": {
              "$ref": "#/components/schemas/CertificateListItem"
            },
            "title": "Certificates",
            "type": "array"
          }
        },
        "required": [
          "certificates"
        ],
        "title": "CertificateList",
        "type": "object"
      },
      "CertificateListItem": {
        "description": "One entry in the tenant's certificate list (non-secret fields).",
        "properties": {
          "certId": {
            "title": "Certid",
            "type": "string"
          },
          "grade": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Grade"
          },
          "issuedAt": {
            "title": "Issuedat",
            "type": "string"
          },
          "modelVersion": {
            "title": "Modelversion",
            "type": "string"
          },
          "packId": {
            "title": "Packid",
            "type": "string"
          },
          "sohBand": {
            "$ref": "#/components/schemas/SohBandOut"
          },
          "sohPercent": {
            "title": "Sohpercent",
            "type": "number"
          },
          "status": {
            "enum": [
              "active",
              "revoked"
            ],
            "title": "Status",
            "type": "string"
          },
          "verifyUrl": {
            "title": "Verifyurl",
            "type": "string"
          }
        },
        "required": [
          "certId",
          "verifyUrl",
          "packId",
          "sohPercent",
          "sohBand",
          "grade",
          "modelVersion",
          "issuedAt",
          "status"
        ],
        "title": "CertificateListItem",
        "type": "object"
      },
      "CollateralCurveIn": {
        "description": "Override the published health-to-value transform's knee/floor knobs (all optional).\n\nA documented piecewise-linear multiplier of SoH percent, NOT market data. See\n``lender_valuation.CollateralCurve`` for the exact shape.",
        "properties": {
          "floorFactor": {
            "anyOf": [
              {
                "maximum": 1.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Floorfactor"
          },
          "floorSohPct": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Floorsohpct"
          },
          "fullSohPct": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Fullsohpct"
          },
          "kneeFactor": {
            "anyOf": [
              {
                "maximum": 1.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Kneefactor"
          },
          "kneeSohPct": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Kneesohpct"
          }
        },
        "title": "CollateralCurveIn",
        "type": "object"
      },
      "ConfidenceBand": {
        "additionalProperties": false,
        "description": "SoH band in percent. Enforces p10 <= p50 <= p90 like the Zod refine.",
        "properties": {
          "p10": {
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "P10",
            "type": "number"
          },
          "p50": {
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "P50",
            "type": "number"
          },
          "p90": {
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "P90",
            "type": "number"
          }
        },
        "required": [
          "p10",
          "p50",
          "p90"
        ],
        "title": "ConfidenceBand",
        "type": "object"
      },
      "CreatePortfolioRequest": {
        "description": "The body of ``POST /v1/portfolios``: the lender's own portfolio label.",
        "properties": {
          "name": {
            "maxLength": 200,
            "minLength": 1,
            "title": "Name",
            "type": "string"
          }
        },
        "required": [
          "name"
        ],
        "title": "CreatePortfolioRequest",
        "type": "object"
      },
      "DegradationCurve": {
        "additionalProperties": false,
        "description": "Forward SoH projection across the loan tenure (at least two points).",
        "properties": {
          "packId": {
            "pattern": "^[0-9A-Z]{21}$",
            "title": "Packid",
            "type": "string"
          },
          "points": {
            "items": {
              "$ref": "#/components/schemas/DegradationPoint"
            },
            "minItems": 2,
            "title": "Points",
            "type": "array"
          }
        },
        "required": [
          "packId",
          "points"
        ],
        "title": "DegradationCurve",
        "type": "object"
      },
      "DegradationPoint": {
        "additionalProperties": false,
        "description": "One point on the forward degradation projection.",
        "properties": {
          "band": {
            "$ref": "#/components/schemas/ConfidenceBand"
          },
          "monthsFromNow": {
            "minimum": 0.0,
            "title": "Monthsfromnow",
            "type": "integer"
          },
          "sohPercent": {
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Sohpercent",
            "type": "number"
          }
        },
        "required": [
          "monthsFromNow",
          "sohPercent",
          "band"
        ],
        "title": "DegradationPoint",
        "type": "object"
      },
      "DriftPackIn": {
        "description": "One live pack for a drift batch: the SAME inline shape as /score.\n\nAn identity object plus the pack's observable history rows. The drift monitor\nuses one feature row per pack (the latest snapshot), consistent with how a pack\nis scored.",
        "properties": {
          "identity": {
            "$ref": "#/components/schemas/PackIdentityIn"
          },
          "observations": {
            "items": {
              "$ref": "#/components/schemas/ObservableRowIn"
            },
            "minItems": 1,
            "title": "Observations",
            "type": "array"
          }
        },
        "required": [
          "identity",
          "observations"
        ],
        "title": "DriftPackIn",
        "type": "object"
      },
      "DriftRequest": {
        "description": "A feature-drift request: a batch of inline live packs.\n\n``packs`` is a non-empty list of inline packs (identity + observations). The\nbatch's latest-snapshot feature rows are PSI-compared against the model's\nstored training-distribution reference.",
        "properties": {
          "packs": {
            "items": {
              "$ref": "#/components/schemas/DriftPackIn"
            },
            "minItems": 1,
            "title": "Packs",
            "type": "array"
          }
        },
        "required": [
          "packs"
        ],
        "title": "DriftRequest",
        "type": "object"
      },
      "EvaluateRequest": {
        "description": "The body of ``POST /v1/portfolios/{id}/evaluate``.\n\n``asOf`` is REQUIRED (an ISO-8601 instant): every alert's ``asOf`` and the telematics-silence\nage derive from it, so the evaluation is reproducible and never depends on the wall-clock.\n``silenceThresholdDays`` (default 30) and ``abuseMinSeverity`` (default HIGH) tune the\ncovenant checks.",
        "properties": {
          "abuseMinSeverity": {
            "default": "HIGH",
            "enum": [
              "LOW",
              "MEDIUM",
              "HIGH"
            ],
            "title": "Abuseminseverity",
            "type": "string"
          },
          "asOf": {
            "format": "date-time",
            "title": "Asof",
            "type": "string"
          },
          "silenceThresholdDays": {
            "default": 30.0,
            "minimum": 0.0,
            "title": "Silencethresholddays",
            "type": "number"
          }
        },
        "required": [
          "asOf"
        ],
        "title": "EvaluateRequest",
        "type": "object"
      },
      "EvaluateSummary": {
        "description": "The response to ``POST /v1/portfolios/{id}/evaluate``.\n\n``asOf`` is the canonical caller-supplied instant; ``positionsEvaluated`` is how many\npositions were scored (and metered as valuations); ``tierCounts`` is the risk-tier\ndistribution; ``breachCount`` is positions with a SoH-floor breach; ``newAlerts`` is the\ntotal alert rows emitted this run; ``alertsByKind`` breaks them down.",
        "properties": {
          "alertsByKind": {
            "additionalProperties": {
              "type": "integer"
            },
            "title": "Alertsbykind",
            "type": "object"
          },
          "asOf": {
            "title": "Asof",
            "type": "string"
          },
          "breachCount": {
            "title": "Breachcount",
            "type": "integer"
          },
          "newAlerts": {
            "title": "Newalerts",
            "type": "integer"
          },
          "portfolioId": {
            "title": "Portfolioid",
            "type": "string"
          },
          "positionsEvaluated": {
            "title": "Positionsevaluated",
            "type": "integer"
          },
          "tierCounts": {
            "additionalProperties": {
              "type": "integer"
            },
            "title": "Tiercounts",
            "type": "object"
          }
        },
        "required": [
          "portfolioId",
          "asOf",
          "positionsEvaluated",
          "tierCounts",
          "breachCount",
          "newAlerts",
          "alertsByKind"
        ],
        "title": "EvaluateSummary",
        "type": "object"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "title": "Detail",
            "type": "array"
          }
        },
        "title": "HTTPValidationError",
        "type": "object"
      },
      "HealthGrade": {
        "additionalProperties": false,
        "description": "A consumer-facing battery health grade for the used-EV marketplace.\n\nA plain-language SUMMARY of the assembled SoH estimate for a non-technical\nshopper: an A-F ``grade`` (a banding of the SoH median, capped down one step by\na HIGH-severity flag), an intuitive 0 to 100 ``health_score`` (the rounded SoH\nmedian), and a ``confidence`` read derived from the SoH band WIDTH (see\ngrade.py).\n\nThis is NOT a guarantee, a warranty, or a substitute for a physical inspection:\nthe grade and health score restate the model's SoH estimate and certify nothing\nabout the pack. ``basis`` states this verbatim and travels with the score so the\ndisclaimer cannot be dropped downstream. The ``grade`` is a monotone banding of\n``health_score`` except for the documented HIGH-severity flag cap.",
        "properties": {
          "basis": {
            "minLength": 1,
            "title": "Basis",
            "type": "string"
          },
          "confidence": {
            "enum": [
              "high",
              "medium",
              "low"
            ],
            "title": "Confidence",
            "type": "string"
          },
          "grade": {
            "enum": [
              "A",
              "B",
              "C",
              "D",
              "F"
            ],
            "title": "Grade",
            "type": "string"
          },
          "headline": {
            "minLength": 1,
            "title": "Headline",
            "type": "string"
          },
          "healthScore": {
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Healthscore",
            "type": "integer"
          }
        },
        "required": [
          "grade",
          "healthScore",
          "confidence",
          "headline",
          "basis"
        ],
        "title": "HealthGrade",
        "type": "object"
      },
      "InsuranceRisk": {
        "additionalProperties": false,
        "description": "A HEURISTIC insurance / collateral risk indicator on top of the score.\n\nMaps the assembled SoH estimate (its downside p10), the worst observable flag,\nand the near-term degradation rate into a coarse risk tier and a continuous 0\nto 100 index for an insurer pricing cover or a lender assessing the pack as\ncollateral (see risk.py).\n\nThis is NOT an actuarial premium, a probability of a claim, or a claims-based\nloss model: no claim frequency, severity, or recovery experience has been fit.\n``basis`` states this verbatim and travels with the score so the disclaimer\ncannot be dropped downstream. ``risk_score`` is monotonic with ``tier`` (a\nhigher score never maps to a lower tier).",
        "properties": {
          "basis": {
            "minLength": 1,
            "title": "Basis",
            "type": "string"
          },
          "rationale": {
            "items": {
              "type": "string"
            },
            "title": "Rationale",
            "type": "array"
          },
          "riskScore": {
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Riskscore",
            "type": "number"
          },
          "tier": {
            "enum": [
              "low",
              "moderate",
              "elevated",
              "high"
            ],
            "title": "Tier",
            "type": "string"
          }
        },
        "required": [
          "tier",
          "riskScore",
          "basis"
        ],
        "title": "InsuranceRisk",
        "type": "object"
      },
      "IssuedCertificate": {
        "description": "The response to ``POST /v1/certificates``: the freshly issued certificate.",
        "properties": {
          "certId": {
            "title": "Certid",
            "type": "string"
          },
          "grade": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Grade"
          },
          "issuedAt": {
            "title": "Issuedat",
            "type": "string"
          },
          "modelVersion": {
            "title": "Modelversion",
            "type": "string"
          },
          "packId": {
            "title": "Packid",
            "type": "string"
          },
          "sohBand": {
            "$ref": "#/components/schemas/SohBandOut"
          },
          "sohPercent": {
            "title": "Sohpercent",
            "type": "number"
          },
          "status": {
            "const": "active",
            "title": "Status",
            "type": "string"
          },
          "verifyUrl": {
            "title": "Verifyurl",
            "type": "string"
          }
        },
        "required": [
          "certId",
          "verifyUrl",
          "packId",
          "sohPercent",
          "sohBand",
          "grade",
          "modelVersion",
          "issuedAt",
          "status"
        ],
        "title": "IssuedCertificate",
        "type": "object"
      },
      "LenderConfig": {
        "description": "The lender's inputs to a valuation: the price basis, LTV policy, floor, and overrides.\n\n``baseValueInr`` is the lender's OWN current fair-value / price basis; without it Ionscore\nreturns factors only (no rupee figure). ``ltvPolicy`` is the lender's appetite;\n``sohFloorPct`` its covenant floor; the band / curve / uncertainty knobs are documented\noverrides of Ionscore's defaults. NONE of these is market data supplied by Ionscore.",
        "properties": {
          "baseValueInr": {
            "anyOf": [
              {
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Basevalueinr"
          },
          "collateralCurve": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CollateralCurveIn"
              },
              {
                "type": "null"
              }
            ]
          },
          "ltvPolicy": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LtvPolicyIn"
              },
              {
                "type": "null"
              }
            ]
          },
          "riskTierBands": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RiskTierBandsIn"
              },
              {
                "type": "null"
              }
            ]
          },
          "sohFloorPct": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Sohfloorpct"
          },
          "uncertaintyWidthPct": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Uncertaintywidthpct"
          }
        },
        "title": "LenderConfig",
        "type": "object"
      },
      "LtvPolicyIn": {
        "description": "The lender's LTV appetite: a max loan-to-value percent per risk tier (all optional).\n\nAny tier omitted falls back to Ionscore's conservative default table. This is the LENDER's\npolicy; Ionscore does not set LTV, it only surfaces the tier the policy is keyed on.",
        "properties": {
          "elevated": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Elevated"
          },
          "high": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "High"
          },
          "low": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Low"
          },
          "moderate": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Moderate"
          }
        },
        "title": "LtvPolicyIn",
        "type": "object"
      },
      "ObservableRowIn": {
        "additionalProperties": false,
        "description": "One observable snapshot row for an inline scoring request.\n\nField names mirror the simulator's observable table columns (without the\n``obs_`` prefix) so a caller can map telemetry directly.",
        "properties": {
          "coulombicEfficiency": {
            "title": "Coulombicefficiency",
            "type": "number"
          },
          "cumulativeChargeKwh": {
            "default": 0.0,
            "title": "Cumulativechargekwh",
            "type": "number"
          },
          "cumulativeDischargeKwh": {
            "default": 0.0,
            "title": "Cumulativedischargekwh",
            "type": "number"
          },
          "cycleCount": {
            "default": 0.0,
            "title": "Cyclecount",
            "type": "number"
          },
          "equivalentFullCycles": {
            "title": "Equivalentfullcycles",
            "type": "number"
          },
          "fastChargeFraction": {
            "title": "Fastchargefraction",
            "type": "number"
          },
          "hotHoursCumulative": {
            "default": 0.0,
            "title": "Hothourscumulative",
            "type": "number"
          },
          "meanDod": {
            "title": "Meandod",
            "type": "number"
          },
          "meanPackTempC": {
            "title": "Meanpacktempc",
            "type": "number"
          },
          "months": {
            "minimum": 0.0,
            "title": "Months",
            "type": "integer"
          },
          "naiveSohProxy": {
            "default": 100.0,
            "title": "Naivesohproxy",
            "type": "number"
          },
          "resistanceProxyOhm": {
            "title": "Resistanceproxyohm",
            "type": "number"
          },
          "resistanceRatio": {
            "title": "Resistanceratio",
            "type": "number"
          }
        },
        "required": [
          "months",
          "equivalentFullCycles",
          "meanDod",
          "fastChargeFraction",
          "resistanceProxyOhm",
          "resistanceRatio",
          "coulombicEfficiency",
          "meanPackTempC"
        ],
        "title": "ObservableRowIn",
        "type": "object"
      },
      "PackIdentityIn": {
        "additionalProperties": false,
        "description": "Static identity for an inline scoring request (contract field names).",
        "properties": {
          "chemistry": {
            "title": "Chemistry",
            "type": "string"
          },
          "climateZone": {
            "default": "TEMPERATE",
            "title": "Climatezone",
            "type": "string"
          },
          "packId": {
            "pattern": "^[0-9A-Z]{21}$",
            "title": "Packid",
            "type": "string"
          },
          "ratedCapacityKwh": {
            "exclusiveMinimum": 0.0,
            "title": "Ratedcapacitykwh",
            "type": "number"
          },
          "region": {
            "default": "Unknown",
            "title": "Region",
            "type": "string"
          },
          "segment": {
            "title": "Segment",
            "type": "string"
          }
        },
        "required": [
          "packId",
          "chemistry",
          "segment",
          "ratedCapacityKwh"
        ],
        "title": "PackIdentityIn",
        "type": "object"
      },
      "PackScore": {
        "additionalProperties": false,
        "description": "The bundled outputs for one pack, returned by POST /score.\n\nThis is a convenience envelope for the REST surface; its members are the\ncontract entities. Sub-project 3 can persist each member directly.\n\n``insurance_risk`` is the heuristic insurer / collateral-lender lens derived\nfrom the same assembled score (no new model); it is optional so an older\nartifact or a hand-built test stub can omit it.\n\n``health_grade`` is the consumer-facing used-EV-marketplace lens derived from\nthe same assembled score (no new model); like ``insurance_risk`` it is optional\nso an older artifact or a hand-built test stub can omit it.\n\n``behavior_risk`` is the heuristic charging-behavior FORWARD-risk read derived\nfrom the same observed usage habits (a LEADING read of how hard the pack is used,\ndistinct from and not feeding the SoH); like the other lenses it is optional so an\nolder artifact or a hand-built test stub can omit it.\n\n``second_life`` is the INDICATIVE second-life valuation derived from the same forward\ndegradation projection and identity (what the pack is worth as a used stationary-grade\nbattery after it leaves automotive service, NOT a UL-1974 certified grade); like the\nother lenses it is optional so an older artifact or a hand-built test stub can omit it.\n\n``warranty_loss_cost`` is the TECHNICAL warranty loss-cost derived from the same forward\ndegradation projection and identity (the breach probability against a guaranteed SoH floor and\nthe loss-cost it implies, NOT an actuarial premium or a certified claim probability); like the\nother lenses it is optional so an older artifact or a hand-built test stub can omit it.",
        "properties": {
          "behaviorRisk": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/BehaviorRisk"
              },
              {
                "type": "null"
              }
            ]
          },
          "degradation": {
            "$ref": "#/components/schemas/DegradationCurve"
          },
          "flags": {
            "items": {
              "$ref": "#/components/schemas/RiskFlag"
            },
            "title": "Flags",
            "type": "array"
          },
          "healthGrade": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/HealthGrade"
              },
              {
                "type": "null"
              }
            ]
          },
          "insuranceRisk": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/InsuranceRisk"
              },
              {
                "type": "null"
              }
            ]
          },
          "packId": {
            "pattern": "^[0-9A-Z]{21}$",
            "title": "Packid",
            "type": "string"
          },
          "residuals": {
            "items": {
              "$ref": "#/components/schemas/ResidualEstimate"
            },
            "minItems": 1,
            "title": "Residuals",
            "type": "array"
          },
          "score": {
            "$ref": "#/components/schemas/ScoreResult"
          },
          "secondLife": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SecondLifeValuation"
              },
              {
                "type": "null"
              }
            ]
          },
          "warrantyLossCost": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/WarrantyLossCost"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "packId",
          "score",
          "degradation",
          "residuals",
          "flags"
        ],
        "title": "PackScore",
        "type": "object"
      },
      "PortfolioDetail": {
        "description": "The response to ``GET /v1/portfolios/{id}``: identity plus the monitoring summary.",
        "properties": {
          "createdAt": {
            "title": "Createdat",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "summary": {
            "$ref": "#/components/schemas/PortfolioSummary"
          }
        },
        "required": [
          "id",
          "name",
          "createdAt",
          "summary"
        ],
        "title": "PortfolioDetail",
        "type": "object"
      },
      "PortfolioList": {
        "description": "The response to ``GET /v1/portfolios``.",
        "properties": {
          "portfolios": {
            "items": {
              "$ref": "#/components/schemas/PortfolioOut"
            },
            "title": "Portfolios",
            "type": "array"
          }
        },
        "required": [
          "portfolios"
        ],
        "title": "PortfolioList",
        "type": "object"
      },
      "PortfolioOut": {
        "description": "A portfolio's identity fields (``createdAt`` is storage metadata, not a scored artifact).",
        "properties": {
          "createdAt": {
            "title": "Createdat",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "name": {
            "title": "Name",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "createdAt"
        ],
        "title": "PortfolioOut",
        "type": "object"
      },
      "PortfolioSummary": {
        "description": "A portfolio's monitoring summary, read from the LAST evaluation (no re-scoring).\n\n``tierCounts`` and ``breachCount`` are computed from each position's stored last-evaluation\nSoH snapshot; ``evaluatedCount`` is how many positions have ever been evaluated;\n``alertCount`` is the portfolio's total covenant-alert rows.",
        "properties": {
          "alertCount": {
            "title": "Alertcount",
            "type": "integer"
          },
          "breachCount": {
            "title": "Breachcount",
            "type": "integer"
          },
          "evaluatedCount": {
            "title": "Evaluatedcount",
            "type": "integer"
          },
          "positionCount": {
            "title": "Positioncount",
            "type": "integer"
          },
          "tierCounts": {
            "additionalProperties": {
              "type": "integer"
            },
            "title": "Tiercounts",
            "type": "object"
          }
        },
        "required": [
          "positionCount",
          "evaluatedCount",
          "tierCounts",
          "breachCount",
          "alertCount"
        ],
        "title": "PortfolioSummary",
        "type": "object"
      },
      "PositionInput": {
        "description": "One position to add: a pack input (identical to /v1/score) plus the lender's loan terms.\n\nExactly one pack form: ``packId`` (sandbox) OR inline ``identity`` + ``observations``.\n``principalInr`` / ``tenureMonths`` are the lender's loan terms; ``sohFloorPct`` its covenant\nfloor; ``lastSnapshotAt`` the pack's last telemetry receipt (the telematics-silence covenant\nis measured against it). All optional except the pack form.",
        "properties": {
          "identity": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PackIdentityIn"
              },
              {
                "type": "null"
              }
            ]
          },
          "lastSnapshotAt": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Lastsnapshotat"
          },
          "observations": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/ObservableRowIn"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Observations"
          },
          "packId": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Packid"
          },
          "principalInr": {
            "anyOf": [
              {
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Principalinr"
          },
          "sohFloorPct": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Sohfloorpct"
          },
          "tenureMonths": {
            "anyOf": [
              {
                "minimum": 0.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tenuremonths"
          }
        },
        "title": "PositionInput",
        "type": "object"
      },
      "PositionList": {
        "description": "The response to the position add and list endpoints.",
        "properties": {
          "positions": {
            "items": {
              "$ref": "#/components/schemas/PositionOut"
            },
            "title": "Positions",
            "type": "array"
          }
        },
        "required": [
          "positions"
        ],
        "title": "PositionList",
        "type": "object"
      },
      "PositionOut": {
        "description": "One position's stored fields, including the last-evaluation SoH snapshot if any.",
        "properties": {
          "createdAt": {
            "title": "Createdat",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "inline": {
            "title": "Inline",
            "type": "boolean"
          },
          "lastSnapshotAt": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Lastsnapshotat"
          },
          "lastSoh": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Lastsoh"
          },
          "packId": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Packid"
          },
          "principalInr": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Principalinr"
          },
          "sohFloorPct": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Sohfloorpct"
          },
          "tenureMonths": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tenuremonths"
          }
        },
        "required": [
          "id",
          "packId",
          "inline",
          "principalInr",
          "tenureMonths",
          "sohFloorPct",
          "lastSnapshotAt",
          "lastSoh",
          "createdAt"
        ],
        "title": "PositionOut",
        "type": "object"
      },
      "PublicCertificate": {
        "description": "The response to the PUBLIC ``GET /verify/{cert_id}``: the certificate's public fields.\n\nExactly the fields a verifier may see: the public id, the scored pack id, the certified\nSoH (percent and band), the consumer grade, the model version, the canonical issuance\ntime, the live status, and the ``contentHash`` content-integrity checksum. NOTHING else\n(no tenant, no api-key material, no internal id, no full score JSON) is exposed.",
        "properties": {
          "certId": {
            "title": "Certid",
            "type": "string"
          },
          "contentHash": {
            "title": "Contenthash",
            "type": "string"
          },
          "grade": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Grade"
          },
          "issuedAt": {
            "title": "Issuedat",
            "type": "string"
          },
          "modelVersion": {
            "title": "Modelversion",
            "type": "string"
          },
          "packId": {
            "title": "Packid",
            "type": "string"
          },
          "sohBand": {
            "$ref": "#/components/schemas/SohBandOut"
          },
          "sohPercent": {
            "title": "Sohpercent",
            "type": "number"
          },
          "status": {
            "enum": [
              "active",
              "revoked"
            ],
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "certId",
          "packId",
          "sohPercent",
          "sohBand",
          "grade",
          "modelVersion",
          "issuedAt",
          "status",
          "contentHash"
        ],
        "title": "PublicCertificate",
        "type": "object"
      },
      "ReasonCode": {
        "additionalProperties": false,
        "description": "One model-attribution driver of the SoH estimate (occlusion attribution).\n\nProduced by occluding a single feature against a typical-pack baseline on the\nmedian model (see reasons.py). ``contribution`` is the signed SoH-point delta;\n``direction`` is \"lowers\" when it is negative and \"raises\" otherwise. This is a\nmodel-descriptive attribution, not a causal claim.",
        "properties": {
          "contribution": {
            "title": "Contribution",
            "type": "number"
          },
          "direction": {
            "enum": [
              "lowers",
              "raises"
            ],
            "title": "Direction",
            "type": "string"
          },
          "feature": {
            "minLength": 1,
            "title": "Feature",
            "type": "string"
          },
          "label": {
            "minLength": 1,
            "title": "Label",
            "type": "string"
          }
        },
        "required": [
          "feature",
          "label",
          "direction",
          "contribution"
        ],
        "title": "ReasonCode",
        "type": "object"
      },
      "ReasonCodeOut": {
        "description": "One driver of the assigned risk tier: a stable machine token plus a human message.",
        "properties": {
          "code": {
            "title": "Code",
            "type": "string"
          },
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "code",
          "message"
        ],
        "title": "ReasonCodeOut",
        "type": "object"
      },
      "ResidualEstimate": {
        "additionalProperties": false,
        "description": "Residual value at a horizon, with a band and labeled assumptions.",
        "properties": {
          "assumptions": {
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "title": "Assumptions",
            "type": "array"
          },
          "band": {
            "$ref": "#/components/schemas/ValueBand"
          },
          "horizonMonths": {
            "minimum": 0.0,
            "title": "Horizonmonths",
            "type": "integer"
          },
          "packId": {
            "pattern": "^[0-9A-Z]{21}$",
            "title": "Packid",
            "type": "string"
          },
          "residualValueInr": {
            "minimum": 0.0,
            "title": "Residualvalueinr",
            "type": "number"
          }
        },
        "required": [
          "packId",
          "horizonMonths",
          "residualValueInr",
          "band",
          "assumptions"
        ],
        "title": "ResidualEstimate",
        "type": "object"
      },
      "RevokeResult": {
        "description": "The response to ``POST /v1/certificates/{cert_id}/revoke``.",
        "properties": {
          "certId": {
            "title": "Certid",
            "type": "string"
          },
          "status": {
            "const": "revoked",
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "certId",
          "status"
        ],
        "title": "RevokeResult",
        "type": "object"
      },
      "RiskFlag": {
        "additionalProperties": false,
        "description": "An explainable threshold-rule flag with plain-English evidence.",
        "properties": {
          "evidence": {
            "minLength": 1,
            "title": "Evidence",
            "type": "string"
          },
          "kind": {
            "enum": [
              "THERMAL_ABUSE",
              "FAST_CHARGE_INTENSITY",
              "DEEP_CYCLING",
              "CALENDAR_AGING"
            ],
            "title": "Kind",
            "type": "string"
          },
          "packId": {
            "pattern": "^[0-9A-Z]{21}$",
            "title": "Packid",
            "type": "string"
          },
          "severity": {
            "enum": [
              "LOW",
              "MEDIUM",
              "HIGH"
            ],
            "title": "Severity",
            "type": "string"
          }
        },
        "required": [
          "packId",
          "kind",
          "severity",
          "evidence"
        ],
        "title": "RiskFlag",
        "type": "object"
      },
      "RiskTierBandsIn": {
        "description": "Override the P10-SoH thresholds (percent) for the base risk tier (all optional).",
        "properties": {
          "elevated": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Elevated"
          },
          "low": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Low"
          },
          "moderate": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Moderate"
          }
        },
        "title": "RiskTierBandsIn",
        "type": "object"
      },
      "ScoreRequest": {
        "description": "A scoring request: either a packId or an inline (identity + observations).",
        "properties": {
          "identity": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PackIdentityIn"
              },
              {
                "type": "null"
              }
            ]
          },
          "observations": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/ObservableRowIn"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Observations"
          },
          "packId": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Packid"
          }
        },
        "title": "ScoreRequest",
        "type": "object"
      },
      "ScoreResult": {
        "additionalProperties": false,
        "description": "State-of-Health now, with a confidence band (api-contract ScoreResult).",
        "properties": {
          "computedAt": {
            "format": "date-time",
            "title": "Computedat",
            "type": "string"
          },
          "modelVersion": {
            "minLength": 1,
            "title": "Modelversion",
            "type": "string"
          },
          "packId": {
            "pattern": "^[0-9A-Z]{21}$",
            "title": "Packid",
            "type": "string"
          },
          "reasonCodes": {
            "items": {
              "$ref": "#/components/schemas/ReasonCode"
            },
            "title": "Reasoncodes",
            "type": "array"
          },
          "sohBand": {
            "$ref": "#/components/schemas/ConfidenceBand"
          },
          "sohPercent": {
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Sohpercent",
            "type": "number"
          }
        },
        "required": [
          "packId",
          "sohPercent",
          "sohBand",
          "computedAt",
          "modelVersion"
        ],
        "title": "ScoreResult",
        "type": "object"
      },
      "SecondLifeValuation": {
        "additionalProperties": false,
        "description": "An INDICATIVE second-life valuation for a pack AFTER automotive service.\n\nExtends the residual-value story past the automotive replacement threshold: it estimates\nwhen the pack leaves automotive service (its projected SoH crossing the replacement floor)\nand what it is then worth as a used, stationary-grade second-life battery, floored at a\nscrap / materials value (see second_life.py). ``automotive_end_months`` is when it leaves\nservice; ``residual_capacity_pct`` (with its band) is the SoH at that point;\n``indicative_value_inr`` (with its ValueBand) is the second-life worth; ``grade`` is a\ncoarse suitability band (repurpose / marginal / recycle).\n\nThis is NOT a UL-1974 certified repurposing grade: a certified grade requires a physical\nteardown; this is a screening estimate on labeled working assumptions. ``basis`` states\nthis verbatim and travels with the valuation so the disclaimer cannot be dropped\ndownstream. It is computed after and independently of the residual value and feeds no other\nproduct. Like the other lenses it is optional so an older artifact or a hand-built stub can\nomit it.",
        "properties": {
          "assumptions": {
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "title": "Assumptions",
            "type": "array"
          },
          "automotiveEndAgeYears": {
            "minimum": 0.0,
            "title": "Automotiveendageyears",
            "type": "number"
          },
          "automotiveEndMonths": {
            "minimum": 0.0,
            "title": "Automotiveendmonths",
            "type": "integer"
          },
          "basis": {
            "minLength": 1,
            "title": "Basis",
            "type": "string"
          },
          "grade": {
            "enum": [
              "repurpose",
              "marginal",
              "recycle"
            ],
            "title": "Grade",
            "type": "string"
          },
          "indicativeValueInr": {
            "minimum": 0.0,
            "title": "Indicativevalueinr",
            "type": "number"
          },
          "residualCapacityBand": {
            "$ref": "#/components/schemas/ConfidenceBand"
          },
          "residualCapacityPct": {
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Residualcapacitypct",
            "type": "number"
          },
          "valueBand": {
            "$ref": "#/components/schemas/ValueBand"
          }
        },
        "required": [
          "automotiveEndMonths",
          "automotiveEndAgeYears",
          "residualCapacityPct",
          "residualCapacityBand",
          "indicativeValueInr",
          "valueBand",
          "grade",
          "assumptions",
          "basis"
        ],
        "title": "SecondLifeValuation",
        "type": "object"
      },
      "SohBandOut": {
        "description": "The certified State-of-Health confidence band, in percent.\n\n``p50`` is the headline SoH (the median, equal to ``sohPercent``); ``p10`` and ``p90``\nare the band edges. All three are covered by the certificate's content hash.",
        "properties": {
          "p10": {
            "title": "P10",
            "type": "number"
          },
          "p50": {
            "title": "P50",
            "type": "number"
          },
          "p90": {
            "title": "P90",
            "type": "number"
          }
        },
        "required": [
          "p10",
          "p50",
          "p90"
        ],
        "title": "SohBandOut",
        "type": "object"
      },
      "ValidationError": {
        "properties": {
          "ctx": {
            "title": "Context",
            "type": "object"
          },
          "input": {
            "title": "Input"
          },
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "title": "Location",
            "type": "array"
          },
          "msg": {
            "title": "Message",
            "type": "string"
          },
          "type": {
            "title": "Error Type",
            "type": "string"
          }
        },
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError",
        "type": "object"
      },
      "ValuationRequest": {
        "description": "A valuation request: a pack input (identical to /v1/score) + lender config + asOf.\n\n``packId`` (sandbox) OR inline ``identity`` + ``observations``, exactly like ``/v1/score``.\n``asOf`` is REQUIRED (an ISO-8601 instant): the valuation must be reproducible and must not\ndepend on the wall-clock, so ``valuedAt`` derives from it.",
        "properties": {
          "asOf": {
            "format": "date-time",
            "title": "Asof",
            "type": "string"
          },
          "identity": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PackIdentityIn"
              },
              {
                "type": "null"
              }
            ]
          },
          "lenderConfig": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LenderConfig"
              },
              {
                "type": "null"
              }
            ]
          },
          "observations": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/ObservableRowIn"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Observations"
          },
          "packId": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Packid"
          }
        },
        "required": [
          "asOf"
        ],
        "title": "ValuationRequest",
        "type": "object"
      },
      "ValuationResponse": {
        "description": "The honest valuation outputs for one scored pack.\n\nOURS (calibrated): ``sohBand``, ``grade``, ``riskTier``, ``collateralFactor`` (a published\ntransform). The LENDER's: ``suggestedMaxLtvPct`` (from its LTV policy). DERIVED only when the\nlender supplied ``baseValueInr``: ``collateralValueInr`` = basis * factor,\n``pessimisticCollateralInr`` (the P10-based downside), and ``suggestedMaxLoanValueInr`` (the\nLTV applied to the pessimistic collateral). With no basis those three are null and ``notes``\nexplains that INR requires the lender's price basis. ``valuedAt`` derives from the caller's\n``asOf`` (no wall-clock). ``basis`` is the fixed honesty disclaimer.",
        "properties": {
          "basis": {
            "title": "Basis",
            "type": "string"
          },
          "collateralFactor": {
            "$ref": "#/components/schemas/BandOut"
          },
          "collateralValueInr": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/BandOut"
              },
              {
                "type": "null"
              }
            ]
          },
          "grade": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Grade"
          },
          "modelVersion": {
            "title": "Modelversion",
            "type": "string"
          },
          "notes": {
            "items": {
              "type": "string"
            },
            "title": "Notes",
            "type": "array"
          },
          "packId": {
            "title": "Packid",
            "type": "string"
          },
          "pessimisticCollateralInr": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Pessimisticcollateralinr"
          },
          "reasonCodes": {
            "items": {
              "$ref": "#/components/schemas/ReasonCodeOut"
            },
            "title": "Reasoncodes",
            "type": "array"
          },
          "riskTier": {
            "title": "Risktier",
            "type": "string"
          },
          "sohBand": {
            "$ref": "#/components/schemas/BandOut"
          },
          "suggestedMaxLoanValueInr": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Suggestedmaxloanvalueinr"
          },
          "suggestedMaxLtvPct": {
            "title": "Suggestedmaxltvpct",
            "type": "number"
          },
          "valuedAt": {
            "title": "Valuedat",
            "type": "string"
          }
        },
        "required": [
          "packId",
          "valuedAt",
          "modelVersion",
          "sohBand",
          "grade",
          "riskTier",
          "collateralFactor",
          "suggestedMaxLtvPct",
          "collateralValueInr",
          "pessimisticCollateralInr",
          "suggestedMaxLoanValueInr",
          "reasonCodes",
          "notes",
          "basis"
        ],
        "title": "ValuationResponse",
        "type": "object"
      },
      "ValueBand": {
        "additionalProperties": false,
        "description": "Residual-value band in INR. Non-negative, p10 <= p50 <= p90.",
        "properties": {
          "p10": {
            "minimum": 0.0,
            "title": "P10",
            "type": "number"
          },
          "p50": {
            "minimum": 0.0,
            "title": "P50",
            "type": "number"
          },
          "p90": {
            "minimum": 0.0,
            "title": "P90",
            "type": "number"
          }
        },
        "required": [
          "p10",
          "p50",
          "p90"
        ],
        "title": "ValueBand",
        "type": "object"
      },
      "WarrantyLossCost": {
        "additionalProperties": false,
        "description": "A TECHNICAL warranty loss-cost input for a battery-performance warranty.\n\nEstimates, from the same forward degradation projection, the probability the pack BREACHES its\nguaranteed State-of-Health floor by the warranty term end (``breach_probability``) and the\nloss-cost that breach implies: the labeled ``remedy_cost_inr`` weighted by the breach\nprobability (``expected_loss_cost_inr``), a ``reserve_inr`` loaded with a prudence margin, and a\n``reserve_curve`` accruing the cumulative-breach loss cost to each projected horizon (see\nwarranty.py). ``warranty_term_months`` and ``warranty_soh_threshold_pct`` are the (overridable,\nlabeled-default) term and floor the read is computed at; ``horizon_limited`` is true when the\nterm ran past the furthest projected horizon.\n\nThis is a TECHNICAL loss-cost input for warranty pricing, NOT an actuarial premium and NOT a\nclaim probability with a certified basis: it is calibrated on the degradation model, not on\nrealized warranty-claim history. ``basis`` states this verbatim and travels with the loss-cost\nso the disclaimer cannot be dropped downstream. It is computed after and independently of the\nresidual value and the second-life valuation and feeds no other product. Like the other lenses\nit is optional so an older artifact or a hand-built stub can omit it.",
        "properties": {
          "assumptions": {
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "title": "Assumptions",
            "type": "array"
          },
          "basis": {
            "minLength": 1,
            "title": "Basis",
            "type": "string"
          },
          "breachProbability": {
            "maximum": 1.0,
            "minimum": 0.0,
            "title": "Breachprobability",
            "type": "number"
          },
          "expectedLossCostInr": {
            "minimum": 0.0,
            "title": "Expectedlosscostinr",
            "type": "number"
          },
          "horizonLimited": {
            "title": "Horizonlimited",
            "type": "boolean"
          },
          "remedyCostInr": {
            "minimum": 0.0,
            "title": "Remedycostinr",
            "type": "number"
          },
          "reserveCurve": {
            "items": {
              "$ref": "#/components/schemas/WarrantyReservePoint"
            },
            "minItems": 1,
            "title": "Reservecurve",
            "type": "array"
          },
          "reserveInr": {
            "minimum": 0.0,
            "title": "Reserveinr",
            "type": "number"
          },
          "warrantySohThresholdPct": {
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Warrantysohthresholdpct",
            "type": "number"
          },
          "warrantyTermMonths": {
            "minimum": 0.0,
            "title": "Warrantytermmonths",
            "type": "integer"
          }
        },
        "required": [
          "warrantyTermMonths",
          "warrantySohThresholdPct",
          "breachProbability",
          "remedyCostInr",
          "expectedLossCostInr",
          "reserveInr",
          "horizonLimited",
          "reserveCurve",
          "assumptions",
          "basis"
        ],
        "title": "WarrantyLossCost",
        "type": "object"
      },
      "WarrantyReservePoint": {
        "additionalProperties": false,
        "description": "One horizon on the warranty reserve-accrual curve.\n\n``cumulative_breach_probability`` is the probability the pack has breached the warranty floor\nat or before this horizon (monotone non-decreasing across the curve); ``reserve_inr`` is the\nreserve that cumulative probability implies. It mirrors the second_life.py plain-triple idiom:\nthe orchestrator maps warranty.ReserveCurvePoint into this contract model.",
        "properties": {
          "cumulativeBreachProbability": {
            "maximum": 1.0,
            "minimum": 0.0,
            "title": "Cumulativebreachprobability",
            "type": "number"
          },
          "monthsFromNow": {
            "minimum": 0.0,
            "title": "Monthsfromnow",
            "type": "integer"
          },
          "reserveInr": {
            "minimum": 0.0,
            "title": "Reserveinr",
            "type": "number"
          }
        },
        "required": [
          "monthsFromNow",
          "cumulativeBreachProbability",
          "reserveInr"
        ],
        "title": "WarrantyReservePoint",
        "type": "object"
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "bearerFormat": "Ionscore API key",
        "description": "An Ionscore API key presented as a bearer token: 'Authorization: Bearer <key>' (bk_ / bk_sbx_ prefixes).",
        "scheme": "bearer",
        "type": "http"
      }
    }
  },
  "info": {
    "summary": "Calibrated battery health scores over HTTP: SoH bands, degradation, residual, risk flags, drift monitoring.",
    "title": "Ionscore API",
    "version": "0.1.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/v1/certificates": {
      "get": {
        "description": "List the calling tenant's certificates (auth required; non-secret fields only).\n\nStrictly scoped to the calling key's tenant, so it can never surface another tenant's\ncertificates. Each entry carries the same public projection as issuance plus the live\nstatus (active or revoked).",
        "operationId": "listCertificates",
        "parameters": [
          {
            "in": "header",
            "name": "authorization",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CertificateList"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "missing credentials: supply 'Authorization: Bearer <key>'",
                  "status": 401,
                  "title": "Unauthorized",
                  "type": "urn:ionscore:unauthorized"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Unauthorized"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "burst rate limit exceeded; retry after the window resets",
                  "status": 429,
                  "title": "Too Many Requests",
                  "type": "urn:ionscore:rate-limited"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "certificate backend not configured",
                  "status": 503,
                  "title": "Service Unavailable",
                  "type": "urn:ionscore:auth-backend-unavailable"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "List Certificates",
        "tags": [
          "certificates"
        ]
      },
      "post": {
        "description": "Score a pack and issue a verifiable certificate for it (auth required).\n\nSame request contract as ``/v1/score`` (a sandbox-only ``packId``, OR inline identity +\nobservations) and it reuses that endpoint's exact scoring path, so the certified score is\nbyte-identical to what ``/v1/score`` returns. The sandbox-vs-production ``packId`` rule\napplies (a non-sandbox key scoring by ``packId`` is refused 403), the payload cap applies\n(413), and the per-key burst limiter runs in ``get_api_key``.\n\nMetering mirrors ``/v1/score`` EXACTLY: a certificate is a billable score, so the monthly\nscores quota is gated BEFORE scoring (429 with ``urn:ionscore:quota-exceeded`` once the\ntier cap is reached) and, on a successful issue, the tenant's \"scores\" counter is\nincremented by one. This closes the free-score gap: a tenant at its monthly cap cannot\nmint scores via issuance. Issuance ALSO increments a distinct informational\n\"certificates\" counter for issuance-volume observability (the way ``/v1/drift`` meters\n\"drift_packs\"). On success a certificate is minted for the CALLING tenant and its public\nfields plus its ``verifyUrl`` are returned.",
        "operationId": "issueCertificate",
        "parameters": [
          {
            "in": "header",
            "name": "authorization",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScoreRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IssuedCertificate"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "missing credentials: supply 'Authorization: Bearer <key>'",
                  "status": 401,
                  "title": "Unauthorized",
                  "type": "urn:ionscore:unauthorized"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "packId scoring runs against the built-in demo fleet and is a sandbox-only affordance; a non-sandbox key must post inline telemetry",
                  "status": 403,
                  "title": "Forbidden",
                  "type": "urn:ionscore:sandbox-only"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Forbidden"
          },
          "413": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "observations list exceeds the configured maximum",
                  "status": 413,
                  "title": "Payload Too Large",
                  "type": "urn:ionscore:payload-too-large"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Payload Too Large"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "monthly score quota reached for this tier (a certificate draws the scores quota)",
                  "status": 429,
                  "title": "Too Many Requests",
                  "type": "urn:ionscore:quota-exceeded"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "certificate backend not configured",
                  "status": 503,
                  "title": "Service Unavailable",
                  "type": "urn:ionscore:auth-backend-unavailable"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Issue Certificate",
        "tags": [
          "certificates"
        ]
      }
    },
    "/v1/certificates/{cert_id}/revoke": {
      "post": {
        "description": "Revoke one of the calling tenant's certificates by id; 404 if it is not this tenant's.\n\nTenant ownership is enforced in the store query: a ``cert_id`` belonging to another\ntenant (or no tenant) answers 404, never revealing that the certificate exists elsewhere.\nAfter a revoke the public ``GET /verify/{cert_id}`` reports status \"revoked\".",
        "operationId": "revokeCertificate",
        "parameters": [
          {
            "in": "path",
            "name": "cert_id",
            "required": true,
            "schema": {
              "title": "Cert Id",
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "authorization",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RevokeResult"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "missing credentials: supply 'Authorization: Bearer <key>'",
                  "status": 401,
                  "title": "Unauthorized",
                  "type": "urn:ionscore:unauthorized"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Unauthorized"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "no certificate with that id",
                  "status": 404,
                  "title": "Not Found",
                  "type": "urn:ionscore:not-found"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "burst rate limit exceeded; retry after the window resets",
                  "status": 429,
                  "title": "Too Many Requests",
                  "type": "urn:ionscore:rate-limited"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "certificate backend not configured",
                  "status": 503,
                  "title": "Service Unavailable",
                  "type": "urn:ionscore:auth-backend-unavailable"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Revoke Certificate",
        "tags": [
          "certificates"
        ]
      }
    },
    "/v1/drift": {
      "post": {
        "description": "Feature-drift report for a batch of live packs (auth required).\n\nSame ``DriftRequest`` contract as the unversioned ``/drift`` and it reuses that\nendpoint's exact logic (including the 503 when the model carries no drift\nreference). Drift is monitoring, not a billable score: sandbox and non-sandbox\nkeys are both allowed (the batch is always inline packs), and it is metered under\nthe informational \"drift_packs\" metric, which does NOT draw down the scores quota.\nThe only added guardrail is the batch-size cap (413): both the pack count and each\npack's observation count are bounded.",
        "operationId": "drift",
        "parameters": [
          {
            "in": "header",
            "name": "authorization",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DriftRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Drift",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "missing credentials: supply 'Authorization: Bearer <key>'",
                  "status": 401,
                  "title": "Unauthorized",
                  "type": "urn:ionscore:unauthorized"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Unauthorized"
          },
          "413": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "observations list exceeds the configured maximum",
                  "status": 413,
                  "title": "Payload Too Large",
                  "type": "urn:ionscore:payload-too-large"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Payload Too Large"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "burst rate limit exceeded; retry after the window resets",
                  "status": 429,
                  "title": "Too Many Requests",
                  "type": "urn:ionscore:rate-limited"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "auth backend not configured",
                  "status": 503,
                  "title": "Service Unavailable",
                  "type": "urn:ionscore:auth-backend-unavailable"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "V1 Drift",
        "tags": [
          "v1"
        ]
      }
    },
    "/v1/healthz": {
      "get": {
        "description": "Public liveness/readiness for the ``/v1`` surface.\n\nNo auth: a health probe must not need a key, and this must answer even when the\nauth backend is absent. ``status`` is unconditionally \"ok\" (the process is alive\nif this runs); ``ready`` mirrors whether the scoring model loaded, reusing\nscoring.py's cheap predicate.",
        "operationId": "healthz",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Healthz",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "V1 Healthz",
        "tags": [
          "v1"
        ]
      }
    },
    "/v1/model-card": {
      "get": {
        "description": "Serve the committed model card. PUBLIC: it is a published honesty artifact.\n\nThe card is served with no auth on purpose: it documents the model's training,\nevaluation, coverage, and calibration so a prospective caller can judge the model\nBEFORE holding a key. The response mirrors the model version as camelCase\n``modelVersion`` (consistent with the rest of the API) and carries the full,\nverbatim committed card under ``card``. If no card is found, 503.",
        "operationId": "getModelCard",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Getmodelcard",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "model card is not available in this deployment",
                  "status": 503,
                  "title": "Service Unavailable",
                  "type": "urn:ionscore:auth-backend-unavailable"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "summary": "V1 Model Card",
        "tags": [
          "v1"
        ]
      }
    },
    "/v1/portfolios": {
      "get": {
        "description": "List the calling tenant's portfolios (auth required; tenant-scoped, unmetered).",
        "operationId": "listPortfolios",
        "parameters": [
          {
            "in": "header",
            "name": "authorization",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortfolioList"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "missing credentials: supply 'Authorization: Bearer <key>'",
                  "status": 401,
                  "title": "Unauthorized",
                  "type": "urn:ionscore:unauthorized"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Unauthorized"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "burst rate limit exceeded; retry after the window resets",
                  "status": 429,
                  "title": "Too Many Requests",
                  "type": "urn:ionscore:rate-limited"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "lender backend not configured",
                  "status": 503,
                  "title": "Service Unavailable",
                  "type": "urn:ionscore:auth-backend-unavailable"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "List Portfolios",
        "tags": [
          "lender"
        ]
      },
      "post": {
        "description": "Create a portfolio for the calling tenant (auth required; MANAGEMENT, unmetered).\n\nPortfolio CRUD is administration, not scoring, so it does not draw the scores quota (like\nkey management). The portfolio scopes to the calling key's tenant.",
        "operationId": "createPortfolio",
        "parameters": [
          {
            "in": "header",
            "name": "authorization",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePortfolioRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortfolioOut"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "missing credentials: supply 'Authorization: Bearer <key>'",
                  "status": 401,
                  "title": "Unauthorized",
                  "type": "urn:ionscore:unauthorized"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Unauthorized"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "burst rate limit exceeded; retry after the window resets",
                  "status": 429,
                  "title": "Too Many Requests",
                  "type": "urn:ionscore:rate-limited"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "lender backend not configured",
                  "status": 503,
                  "title": "Service Unavailable",
                  "type": "urn:ionscore:auth-backend-unavailable"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Create Portfolio",
        "tags": [
          "lender"
        ]
      }
    },
    "/v1/portfolios/{portfolio_id}": {
      "get": {
        "description": "Portfolio detail plus a monitoring summary (auth required; tenant-scoped, unmetered).\n\nThe summary is read from each position's LAST evaluation snapshot (``lastSoh``), so it does\nno scoring and draws no quota: ``tierCounts`` is the stored risk-tier distribution,\n``breachCount`` is positions whose stored band breaches their SoH floor, and ``alertCount``\nis the portfolio's total covenant-alert rows. A portfolio that is not this tenant's is 404.",
        "operationId": "getPortfolio",
        "parameters": [
          {
            "in": "path",
            "name": "portfolio_id",
            "required": true,
            "schema": {
              "title": "Portfolio Id",
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "authorization",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortfolioDetail"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "missing credentials: supply 'Authorization: Bearer <key>'",
                  "status": 401,
                  "title": "Unauthorized",
                  "type": "urn:ionscore:unauthorized"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Unauthorized"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "no portfolio with that id for this account",
                  "status": 404,
                  "title": "Not Found",
                  "type": "urn:ionscore:not-found"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "burst rate limit exceeded; retry after the window resets",
                  "status": 429,
                  "title": "Too Many Requests",
                  "type": "urn:ionscore:rate-limited"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "lender backend not configured",
                  "status": 503,
                  "title": "Service Unavailable",
                  "type": "urn:ionscore:auth-backend-unavailable"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Get Portfolio",
        "tags": [
          "lender"
        ]
      }
    },
    "/v1/portfolios/{portfolio_id}/alerts": {
      "get": {
        "description": "List a portfolio's covenant alerts, newest first (auth required; tenant-scoped, unmetered).\n\nA portfolio that is not this tenant's is 404. Each alert's ``asOf`` is the evaluation's\ncaller-supplied instant (a reproducible artifact); ``createdAt`` is storage metadata.",
        "operationId": "listAlerts",
        "parameters": [
          {
            "in": "path",
            "name": "portfolio_id",
            "required": true,
            "schema": {
              "title": "Portfolio Id",
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "authorization",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertList"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "missing credentials: supply 'Authorization: Bearer <key>'",
                  "status": 401,
                  "title": "Unauthorized",
                  "type": "urn:ionscore:unauthorized"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Unauthorized"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "no portfolio with that id for this account",
                  "status": 404,
                  "title": "Not Found",
                  "type": "urn:ionscore:not-found"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "burst rate limit exceeded; retry after the window resets",
                  "status": 429,
                  "title": "Too Many Requests",
                  "type": "urn:ionscore:rate-limited"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "lender backend not configured",
                  "status": 503,
                  "title": "Service Unavailable",
                  "type": "urn:ionscore:auth-backend-unavailable"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "List Alerts",
        "tags": [
          "lender"
        ]
      }
    },
    "/v1/portfolios/{portfolio_id}/evaluate": {
      "post": {
        "description": "Score every position and emit covenant alerts (auth required; metered \"valuations\").\n\nFor each position the shared scorer runs (byte-identical to ``/v1/score``) and three covenant\nchecks run against the caller-supplied ``asOf``: ``soh_floor_breach`` (P10 or P50 SoH below\nthe position's SoH floor), ``abuse_flag`` (a scored risk flag at/above ``abuseMinSeverity``,\ndefault HIGH), and ``telematics_silence`` (last telemetry older than ``asOf`` minus\n``silenceThresholdDays``). Determinism: every alert's ``asOf`` and the silence age derive from\nthe caller ``asOf`` (REQUIRED), never the wall-clock.\n\nMetering: each position scored is a billable score, so the monthly scores quota is gated for\nthe whole batch BEFORE any scoring (429 at the cap) and, on success, the tenant's \"scores\" and\n\"valuations\" counters are each incremented by the position count. The sandbox-vs-production\nrule is enforced per position (a packId position under a non-sandbox key is 403). A portfolio\nthat is not this tenant's is 404. An empty portfolio evaluates to an empty summary with no\nmetering.",
        "operationId": "evaluatePortfolio",
        "parameters": [
          {
            "in": "path",
            "name": "portfolio_id",
            "required": true,
            "schema": {
              "title": "Portfolio Id",
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "authorization",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EvaluateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EvaluateSummary"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "missing credentials: supply 'Authorization: Bearer <key>'",
                  "status": 401,
                  "title": "Unauthorized",
                  "type": "urn:ionscore:unauthorized"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "packId scoring runs against the built-in demo fleet and is a sandbox-only affordance; a non-sandbox key must post inline telemetry",
                  "status": 403,
                  "title": "Forbidden",
                  "type": "urn:ionscore:sandbox-only"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "no portfolio with that id for this account",
                  "status": 404,
                  "title": "Not Found",
                  "type": "urn:ionscore:not-found"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "monthly score quota reached for this tier (a valuation draws the scores quota)",
                  "status": 429,
                  "title": "Too Many Requests",
                  "type": "urn:ionscore:quota-exceeded"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "lender backend not configured",
                  "status": 503,
                  "title": "Service Unavailable",
                  "type": "urn:ionscore:auth-backend-unavailable"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Evaluate Portfolio",
        "tags": [
          "lender"
        ]
      }
    },
    "/v1/portfolios/{portfolio_id}/positions": {
      "get": {
        "description": "List a portfolio's positions (auth required; tenant-scoped, unmetered). 404 if not owned.",
        "operationId": "listPositions",
        "parameters": [
          {
            "in": "path",
            "name": "portfolio_id",
            "required": true,
            "schema": {
              "title": "Portfolio Id",
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "authorization",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PositionList"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "missing credentials: supply 'Authorization: Bearer <key>'",
                  "status": 401,
                  "title": "Unauthorized",
                  "type": "urn:ionscore:unauthorized"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Unauthorized"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "no portfolio with that id for this account",
                  "status": 404,
                  "title": "Not Found",
                  "type": "urn:ionscore:not-found"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "burst rate limit exceeded; retry after the window resets",
                  "status": 429,
                  "title": "Too Many Requests",
                  "type": "urn:ionscore:rate-limited"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "lender backend not configured",
                  "status": 503,
                  "title": "Service Unavailable",
                  "type": "urn:ionscore:auth-backend-unavailable"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "List Positions",
        "tags": [
          "lender"
        ]
      },
      "post": {
        "description": "Add one or more positions to a portfolio (auth required; MANAGEMENT, unmetered).\n\nAdding a position does NOT score it (that is ``/evaluate``), so it draws no quota. Each\nposition must carry exactly one pack form: a sandbox ``packId`` OR inline ``identity`` +\n``observations`` (422 otherwise), and the sandbox-vs-production ``packId`` rule applies (403).\nThe inline observations cap applies (413). A portfolio that is not this tenant's is 404.",
        "operationId": "addPositions",
        "parameters": [
          {
            "in": "path",
            "name": "portfolio_id",
            "required": true,
            "schema": {
              "title": "Portfolio Id",
              "type": "string"
            }
          },
          {
            "in": "header",
            "name": "authorization",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddPositionsRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PositionList"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "missing credentials: supply 'Authorization: Bearer <key>'",
                  "status": 401,
                  "title": "Unauthorized",
                  "type": "urn:ionscore:unauthorized"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "packId scoring runs against the built-in demo fleet and is a sandbox-only affordance; a non-sandbox key must post inline telemetry",
                  "status": 403,
                  "title": "Forbidden",
                  "type": "urn:ionscore:sandbox-only"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Forbidden"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "no portfolio with that id for this account",
                  "status": 404,
                  "title": "Not Found",
                  "type": "urn:ionscore:not-found"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Not Found"
          },
          "413": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "observations list exceeds the configured maximum",
                  "status": 413,
                  "title": "Payload Too Large",
                  "type": "urn:ionscore:payload-too-large"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Payload Too Large"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "burst rate limit exceeded; retry after the window resets",
                  "status": 429,
                  "title": "Too Many Requests",
                  "type": "urn:ionscore:rate-limited"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "lender backend not configured",
                  "status": 503,
                  "title": "Service Unavailable",
                  "type": "urn:ionscore:auth-backend-unavailable"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Add Positions",
        "tags": [
          "lender"
        ]
      }
    },
    "/v1/score": {
      "post": {
        "description": "Score one pack (auth required); meter and quota-gate the tenant's usage.\n\nSame request contract as the unversioned ``/score`` (packId OR identity +\nobservations), and it reuses that endpoint's exact logic, so the returned\n``PackScore`` is byte-identical. The wrapper adds: the payload cap (413), the\nsandbox-vs-production packId rule (403), the monthly quota gate (429), and, on\nsuccess, a \"scores\" increment.",
        "operationId": "score",
        "parameters": [
          {
            "in": "header",
            "name": "authorization",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScoreRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PackScore"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "missing credentials: supply 'Authorization: Bearer <key>'",
                  "status": 401,
                  "title": "Unauthorized",
                  "type": "urn:ionscore:unauthorized"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "packId scoring runs against the built-in demo fleet and is a sandbox-only affordance; a non-sandbox key must post inline telemetry",
                  "status": 403,
                  "title": "Forbidden",
                  "type": "urn:ionscore:sandbox-only"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Forbidden"
          },
          "413": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "observations list exceeds the configured maximum",
                  "status": 413,
                  "title": "Payload Too Large",
                  "type": "urn:ionscore:payload-too-large"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Payload Too Large"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "monthly score quota reached for this tier",
                  "status": 429,
                  "title": "Too Many Requests",
                  "type": "urn:ionscore:quota-exceeded"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "auth backend not configured",
                  "status": 503,
                  "title": "Service Unavailable",
                  "type": "urn:ionscore:auth-backend-unavailable"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "V1 Score",
        "tags": [
          "v1"
        ]
      }
    },
    "/v1/valuation": {
      "post": {
        "description": "Score a pack and return an honest collateral / LTV valuation (auth required; metered).\n\nSame pack input as ``/v1/score`` (sandbox ``packId`` OR inline identity + observations) and\nit reuses that endpoint's EXACT scoring path, so the SoH band and grade are byte-identical to\nwhat ``/v1/score`` returns. The sandbox-vs-production ``packId`` rule (403) and the payload\ncap (413) apply.\n\nHONESTY: Ionscore has NO Indian resale-price data, so this NEVER invents a rupee resale\nprice. It returns our calibrated ``sohBand`` and ``grade``, a ``riskTier`` from SoH\nthresholds, and a transparent published ``collateralFactor`` (a health-to-value multiplier).\nINR figures (``collateralValueInr``, ``pessimisticCollateralInr``,\n``suggestedMaxLoanValueInr``) are returned ONLY when the lender supplies its own price basis\n(``lenderConfig.baseValueInr``); otherwise ``notes`` explains that INR requires it.\n``suggestedMaxLtvPct`` is the LENDER's own policy. This is NOT market pricing and NOT lending\nadvice (see ``basis``).\n\nMetering mirrors ``/v1/score`` and the certificate feature EXACTLY: a valuation is a billable\nscore, so the monthly scores quota is gated BEFORE scoring (429 ``urn:ionscore:quota-exceeded``\nat the cap) and, on success, the tenant's \"scores\" counter is incremented by one; a distinct\ninformational \"valuations\" counter is also incremented. Determinism: ``valuedAt`` derives from\nthe caller-supplied ``asOf`` (REQUIRED), never the wall-clock, so identical inputs yield\nbyte-identical responses.",
        "operationId": "valuation",
        "parameters": [
          {
            "in": "header",
            "name": "authorization",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ValuationRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValuationResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "missing credentials: supply 'Authorization: Bearer <key>'",
                  "status": 401,
                  "title": "Unauthorized",
                  "type": "urn:ionscore:unauthorized"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Unauthorized"
          },
          "403": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "packId scoring runs against the built-in demo fleet and is a sandbox-only affordance; a non-sandbox key must post inline telemetry",
                  "status": 403,
                  "title": "Forbidden",
                  "type": "urn:ionscore:sandbox-only"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Forbidden"
          },
          "413": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "observations list exceeds the configured maximum",
                  "status": 413,
                  "title": "Payload Too Large",
                  "type": "urn:ionscore:payload-too-large"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Payload Too Large"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "monthly score quota reached for this tier (a valuation draws the scores quota)",
                  "status": 429,
                  "title": "Too Many Requests",
                  "type": "urn:ionscore:quota-exceeded"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "lender backend not configured",
                  "status": 503,
                  "title": "Service Unavailable",
                  "type": "urn:ionscore:auth-backend-unavailable"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Valuation",
        "tags": [
          "lender"
        ]
      }
    },
    "/verify/{cert_id}": {
      "get": {
        "description": "PUBLIC: resolve a certificate by its id and return its verifiable public fields.\n\nNo authentication (no key, no cookie): the unguessable ``cert_id`` is the capability, so\nthe surface cannot be enumerated, and it is additionally rate-limited per client IP\n(429 when a source exceeds the generous window). Returns ONLY the public certificate\nfields plus the ``contentHash`` content-integrity checksum; an unknown id is a 404.\n\nIntegrity model: authenticity rests on the unguessable ``cert_id`` resolving to the\nauthoritative record at this trusted origin. The ``contentHash`` is a sha256\ncontent-integrity CHECKSUM (not a cryptographic signature; no non-repudiation): a\nconsumer recomputes ``cert_secrets.certificate_content_hash`` over the returned\n``certId``, ``packId``, ``sohPercent``, ``sohBand`` p10/p50/p90, ``grade``,\n``modelVersion``, and ``issuedAt`` and checks it equals the returned ``contentHash`` to\nconfirm the displayed values match what was issued WHEN the hash is obtained from this\norigin. It does not defend against a party controlling the whole response.",
        "operationId": "verifyCertificate",
        "parameters": [
          {
            "in": "path",
            "name": "cert_id",
            "required": true,
            "schema": {
              "title": "Cert Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicCertificate"
                }
              }
            },
            "description": "Successful Response"
          },
          "404": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "no certificate with that id",
                  "status": 404,
                  "title": "Not Found",
                  "type": "urn:ionscore:not-found"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Not Found"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "burst rate limit exceeded; retry after the window resets",
                  "status": 429,
                  "title": "Too Many Requests",
                  "type": "urn:ionscore:rate-limited"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Too Many Requests"
          },
          "503": {
            "content": {
              "application/problem+json": {
                "example": {
                  "detail": "certificate backend not configured",
                  "status": 503,
                  "title": "Service Unavailable",
                  "type": "urn:ionscore:auth-backend-unavailable"
                },
                "schema": {
                  "description": "An RFC7807 problem-details body: a stable machine-readable failure token plus a human-readable explanation.",
                  "properties": {
                    "detail": {
                      "description": "A human-readable explanation specific to this occurrence.",
                      "type": "string"
                    },
                    "status": {
                      "description": "The HTTP status code.",
                      "type": "integer"
                    },
                    "title": {
                      "description": "A short, human-readable summary of the problem type.",
                      "type": "string"
                    },
                    "type": {
                      "description": "A stable urn:ionscore:* token identifying the failure class.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "type",
                    "title",
                    "status",
                    "detail"
                  ],
                  "title": "Problem",
                  "type": "object"
                }
              }
            },
            "description": "Service Unavailable"
          }
        },
        "summary": "Verify Certificate",
        "tags": [
          "verify"
        ]
      }
    }
  }
}
