diff --git a/content/en/api-reference/common-4xx-errors.mdx b/content/en/api-reference/common-4xx-errors.mdx
index d037afd..df92528 100644
--- a/content/en/api-reference/common-4xx-errors.mdx
+++ b/content/en/api-reference/common-4xx-errors.mdx
@@ -1,12 +1,12 @@
---
-description: "The four most common 4xx/410 mistakes against the SharpAPI REST API — offset over the pagination cap, pre-namespace opportunity paths, streaming on the API root, and unknown filter slugs — with the exact fix for each."
+description: "The most common 4xx/410 mistakes against the SharpAPI REST API — offset over the pagination cap, market= vs market_type= confusion, market-segment slug passed as league, pre-namespace opportunity paths, streaming on the API root, and unknown filter slugs — with the exact fix for each."
---
import { Callout } from 'nextra/components'
# Common 4xx Mistakes
-Four client-side usage mistakes account for most of the recurring 4xx/410 responses SharpAPI returns. Each error body already names the fix — this page collects them in one place so you can map a status code to the correction without opening a support ticket.
+Six client-side usage mistakes account for most of the recurring 4xx/410 responses SharpAPI returns. Each error body already names the fix — this page collects them in one place so you can map a status code to the correction without opening a support ticket.
These are **client-side** errors, not outages. The general error envelope (fields, status-code meanings, the full code list) lives in [Response Conventions](/en/api-reference/conventions/). Always branch on `error.code`, not the prose `message`.
@@ -33,6 +33,38 @@ Deep pagination with `offset` is capped at **500** on [`/api/v1/odds`](/en/api-r
On `/odds/delta`, advance `since=` to the previous response's `updated_at` instead of increasing `offset`.
+## `market=` vs `market_type=` confusion → `400 invalid_filter`
+
+The response field that names the market is called `market_type` (e.g. `"market_type": "moneyline"`). The **query parameter** is `market=` — the two names differ by design, because the filter also accepts category aliases that expand to multiple types. Sending `?market_type=moneyline` works (it is accepted as an alias for `market=`), but the common mistake is passing the full exact-type name when a category alias was intended, or vice versa.
+
+| What you want | Correct param |
+|---|---|
+| All moneylines | `?market=moneyline` |
+| All spreads (point spread, puck line, run line, set handicap) | `?market=spread` |
+| All totals | `?market=total` |
+| All player props | `?market=props` |
+| Exact type from response | `?market=` (e.g. `market=point_spread`) |
+
+`market=` and `market_type=` are interchangeable on the query string — both reach the same filter. Category aliases (`main`, `spread`, `total`, `props`) expand to a group of types; everything else is treated as an exact type match and validated against the market registry. A value that matches neither an alias nor a registry slug returns `400 invalid_filter` with a `did_you_mean` hint.
+
+## League slug passed as `league=` when it is a market segment → `400 invalid_filter`
+
+League slugs (e.g. `nfl`, `nba`, `mlb`) and market-segment slugs (e.g. `nfl_1st_quarter_spreads`, `nba_player_points`) look similar but belong to different filter parameters. Passing a market-segment slug as a league value returns `400 invalid_filter` because it is not a valid league:
+
+```json
+{
+ "error": {
+ "code": "invalid_filter",
+ "message": "invalid filter values: league=[nfl_1st_quarter_spreads]; see GET /api/v1/leagues for valid values",
+ "details": {
+ "fields": { "league": ["nfl_1st_quarter_spreads"] }
+ }
+ }
+}
+```
+
+**Fix:** use `market_segment=nfl_1st_quarter_spreads` (or `market=`) for market filtering, and `league=nfl` for league filtering. Fetch valid league slugs from [`GET /api/v1/leagues`](/en/api-reference/leagues/) and valid market-segment slugs from [`GET /api/v1/markets`](/en/api-reference/markets/).
+
## Pre-namespace opportunity paths → `410 Gone`
Every opportunity type lives under `/api/v1/opportunities/`. The bare shorthand paths (`/api/v1/ev`, `/api/v1/arbitrage`, `/api/v1/middles`, `/api/v1/low_hold`) return **410 Gone** and name their replacement:
diff --git a/content/en/api-reference/odds.mdx b/content/en/api-reference/odds.mdx
index 0941dad..057dec7 100644
--- a/content/en/api-reference/odds.mdx
+++ b/content/en/api-reference/odds.mdx
@@ -31,7 +31,7 @@ The sportsbooks returned in your results depend on your subscription tier. Free
| `sportsbook` | string | tier-allowed | Comma-separated sportsbook IDs (e.g., `draftkings,fanduel`). Tier limits enforced. |
| `sport` | string | all | Filter by sport(s), comma-separated (e.g., `basketball`, `football`). Supports category aliases. |
| `league` | string | all | Filter by league(s), comma-separated (e.g., `nba`, `nfl`, `nhl`) |
-| `market` | string | all | Filter by market type(s), comma-separated. Supports [category aliases](#market-category-aliases) (`main`, `spread`, `total`, `props`) or exact types (`point_spread`, `player_points`). Also accepted as `market_type=` (mirrors the response field name). |
+| `market` | string | all | Filter by market type(s), comma-separated. Accepts [category aliases](#market-category-aliases) (`main`, `spread`, `total`, `props`) **or** exact type names as they appear in the `market_type` response field (e.g., `moneyline`, `point_spread`, `player_points`). Also accepted as `market_type=`. |
| `event_id` | string | — | Filter by event ID(s), comma-separated |
| `is_live` | boolean | — | `true` = live only, `false` = prematch only, omit = both |
| `group_by` | string | — | Group results by field (e.g., `event`) |
@@ -44,6 +44,14 @@ The sportsbooks returned in your results depend on your subscription tier. Free
Use comma-separated values to filter by multiple sportsbooks: `sportsbook=draftkings,fanduel,betmgm`
+
+**`market=` vs `market_type` — don't confuse the filter name with the response field name.** The response object contains a field called `market_type` (e.g. `"market_type": "moneyline"`). The query parameter is `market=` — which also accepts `market_type=` as an alias. Both `?market=moneyline` and `?market_type=moneyline` work and are equivalent. Passing an unrecognized value returns `400 invalid_filter`. See [Common 4xx Mistakes](/en/api-reference/common-4xx-errors/) for the full error shape.
+
+
+
+**`league=` takes league slugs, not market-segment slugs.** League slugs look like `nfl`, `nba`, `mlb`. Market-segment slugs like `nfl_1st_quarter_spreads` belong on the `market_segment=` filter, not `league=`. Mixing them returns `400 invalid_filter`. Fetch valid league slugs from [`GET /api/v1/leagues`](/en/api-reference/leagues/).
+
+
### Market Category Aliases
Instead of listing individual market types, you can use a category alias to match a group of related markets. Aliases and exact types can be mixed freely in a comma-separated list.