Found by the docs-reality audit 2026-07-14 (report: DOCS_REALITY_AUDIT_2026-07-14.md at the docs.sharpapi.io repo root on dev; unit: top-concepts-sdks-examples; wire shapes independently re-verified against deployed sharp-api-go 84c92a4).
Two model↔wire mismatches in src/sharpapi/models.py:
1. MiddleSide (models.py:385) — raises ValidationError on every live middles response.
class MiddleSide(BaseModel):
book: str
selection: str
line: float
odds: OddsValue # required nested object
…
The live API sends middle sides flat — sportsbook (not book) and odds_american / odds_decimal / odds_probability / fair_probability (no nested odds object). Required fields book and odds are absent from real payloads, so client.middles() cannot parse a successful response at all → pydantic ValidationError.
2. EVOpportunity.confidence_score (models.py:277) — silently always None.
Wire field is confidence (int 0–100); there is no alias, so confidence_score: float | None = None never populates. Consumers filtering on opp.confidence_score get None for every row (silent, unlike #1).
Wire sample (live /api/v1/opportunities/ev?limit=1, trimmed):
{"confidence": 60, "sportsbook": "draftkings", "odds_american": -185, "odds_decimal": 1.541, "odds_probability": 0.6491, "fair_probability": 0.7407, "quality_tier": "B", …}
Suggested fix: rename to confidence (or add a populate-by-alias), flatten MiddleSide to the wire contract, and add a recorded-fixture round-trip test against captured live payloads so model drift fails CI. Note the wire also now carries quality_tier ("A"/"B"/"C") on EV rows (shipped 2026-07-14) — worth adding to EVOpportunity in the same pass. The docs SDK pages mirror these model shapes and are being corrected in the docs audit's Wave 1; the SDK is the source the docs should follow, so this fix should land first. PyPI is immutable — needs a version bump + release.
Found by the docs-reality audit 2026-07-14 (report:
DOCS_REALITY_AUDIT_2026-07-14.mdat the docs.sharpapi.io repo root on dev; unit: top-concepts-sdks-examples; wire shapes independently re-verified against deployed sharp-api-go84c92a4).Two model↔wire mismatches in
src/sharpapi/models.py:1.
MiddleSide(models.py:385) — raises ValidationError on every live middles response.The live API sends middle sides flat —
sportsbook(notbook) andodds_american/odds_decimal/odds_probability/fair_probability(no nestedoddsobject). Required fieldsbookandoddsare absent from real payloads, soclient.middles()cannot parse a successful response at all → pydantic ValidationError.2.
EVOpportunity.confidence_score(models.py:277) — silently always None.Wire field is
confidence(int 0–100); there is no alias, soconfidence_score: float | None = Nonenever populates. Consumers filtering onopp.confidence_scoreget None for every row (silent, unlike #1).Wire sample (live
/api/v1/opportunities/ev?limit=1, trimmed):{"confidence": 60, "sportsbook": "draftkings", "odds_american": -185, "odds_decimal": 1.541, "odds_probability": 0.6491, "fair_probability": 0.7407, "quality_tier": "B", …}Suggested fix: rename to
confidence(or add a populate-by-alias), flattenMiddleSideto the wire contract, and add a recorded-fixture round-trip test against captured live payloads so model drift fails CI. Note the wire also now carriesquality_tier("A"/"B"/"C") on EV rows (shipped 2026-07-14) — worth adding toEVOpportunityin the same pass. The docs SDK pages mirror these model shapes and are being corrected in the docs audit's Wave 1; the SDK is the source the docs should follow, so this fix should land first. PyPI is immutable — needs a version bump + release.