Skip to Content
API ReferenceMiddles Summary

Middles Summary

Get aggregate statistics for current middle opportunities without the full list. Uses the same underlying data as the Middles endpoint.

GET /api/v1/opportunities/middles/summary

AuthenticationPermalink for this section

Requires API key. Pro tier or higher required.

Query ParametersPermalink for this section

ParameterTypeDefaultDescription
sportstringallFilter by sport (e.g., basketball, football)
leaguestringallFilter by league (e.g., nba, nfl, nhl)

Example RequestsPermalink for this section

curl -X GET "https://api.sharpapi.io/api/v1/opportunities/middles/summary?league=nfl" \ -H "X-API-Key: YOUR_API_KEY"

ResponsePermalink for this section

Success (200)Permalink for this section

Real response for GET /api/v1/opportunities/middles/summary?sport=baseball (captured 2026-07-02):

{ "data": { "by_league": { "mexico_-_lmb": { "avg_expected_value": 3.33, "avg_quality_score": 1, "count": 22 }, "mlb": { "avg_expected_value": 10.47, "avg_quality_score": 3.2, "count": 72 } }, "by_sport": { "baseball": { "avg_expected_value": 8.8, "avg_quality_score": 2.69, "count": 94 } }, "total": 94 }, "updated_at": "2026-07-02T18:22:29.38658773Z" }

Response HeadersPermalink for this section

X-RateLimit-Limit: 300 X-RateLimit-Remaining: 296 X-RateLimit-Reset: 1707401000 X-Data-Delay: 0 X-Request-Id: 1782526326424224-82519

Error ResponsesPermalink for this section

401 Unauthorized

No key supplied returns missing_api_key; a bad key returns invalid_api_key.

{ "error": { "code": "missing_api_key", "message": "API key required. Pass via X-API-Key header, api_key query parameter, or Bearer token.", "docs": "https://sharpapi.io/docs/authentication" } }

403 Tier Restricted

{ "error": { "code": "tier_restricted", "message": "This endpoint requires Pro tier or higher", "docs": "https://sharpapi.io/pricing", "tier": "hobby", "required_tier": "pro" } }

Response FieldsPermalink for this section

FieldTypeDescription
totalintegerTotal current middles matching the filters
by_sportobjectPer-sport buckets, keyed by sport slug
by_sport.<sport>.countintegerNumber of middles in this sport
by_sport.<sport>.avg_quality_scorenumberAverage middle quality score for this sport
by_sport.<sport>.avg_expected_valuenumberAverage expected value for this sport
by_leagueobjectPer-league buckets, keyed by league slug — same {count, avg_quality_score, avg_expected_value} shape

Use CasesPermalink for this section

Dashboard OverviewPermalink for this section

Use the summary endpoint to power dashboard widgets showing middle opportunity counts, breakdowns, and averages without fetching the full list.

Polling vs Full FetchPermalink for this section

Poll the summary endpoint at shorter intervals to detect when new opportunities appear, then fetch the full Middles endpoint only when the count changes.

// Poll summary every 10 seconds let lastCount = 0; setInterval(async () => { const summary = await fetchMiddlesSummary(); if (summary.data.total !== lastCount) { lastCount = summary.data.total; const middles = await fetchMiddles(); // Full fetch updateUI(middles); } }, 10000);

The summary is computed from the same in-process result set as the full Middles endpoint (refreshed each engine cycle) and counts toward your rate limit the same as the full middles endpoint.

Last updated on