Skip to Content
Core ConceptsEntity Reference IDs

Entity reference IDs

SharpAPI emits stable, integer-keyed identifiers (numerical_id) on every reference entity, plus self-describing nested reference objects on every odds row and opportunity leg. This page documents what those IDs guarantee, how to use them, and how they relate to the existing string IDs.

New (May 2026). Both numerical_id and the nested reference objects are additive. Existing string IDs (sport: "baseball", league: "mlb", sportsbook: "pinnacle", home_team: "New York Yankees") remain in every response and are not deprecated. There is no removal timeline — both shapes are supported indefinitely.

What’s new

Each reference endpoint (/sports, /leagues, /sportsbooks, /markets, /teams) now returns a numerical_id integer alongside the existing slug id. /teams additionally returns an abbreviation field where one is known.

Each odds row (and each leg of an EV / arbitrage / middle opportunity) now carries six optional nested reference objects that bundle the entity’s id, display label, and numerical_id directly with the row — no second lookup against /sports or /teams needed:

{ "home": { "id": "new_york_yankees", "numerical_id": 20, "name": "New York Yankees", "abbreviation": "NYY", "logo": "https://cdn.opticodds.com/team-logos/baseball/36.png", "city": "New York", "mascot": "Yankees", "conference": "AL", "division": "East Division" }, "away": { "id": "boston_red_sox", "numerical_id": 5, "name": "Boston Red Sox", "abbreviation": "BOS", "logo": "https://cdn.opticodds.com/team-logos/baseball/14.png", "city": "Boston", "mascot": "Red Sox", "conference": "AL", "division": "East Division" }, "sport_ref": { "id": "baseball", "numerical_id": 3, "name": "Baseball" }, "league_ref": { "id": "mlb", "numerical_id": 354, "label": "MLB" }, "market_ref": { "id": "moneyline", "numerical_id": 878, "label": "Moneyline" }, "sportsbook_ref": { "id": "pinnacle", "numerical_id": 28, "label": "Pinnacle" } }

numerical_id semantics

Each numerical_id is allocated from a frozen, per-domain registry under api-adapters/sharp_atlas/. The contract is:

PropertyGuarantee
FrozenOnce assigned, a numerical_id is never reused, reissued, or remapped to a different entity. The Yankees’ numerical_id: 20 will be 20 until the API is retired.
Dense from 1IDs start at 1 and are issued sequentially per domain. There are no negative or zero IDs and no large skips. Sports, leagues, sportsbooks, markets, and teams each have an independent dense range.
Domain-scopedA numerical_id is only unique within its domain (sport, league, sportsbook, market, team). numerical_id: 3 on a sport is unrelated to numerical_id: 3 on a team. Pair the integer with the domain to disambiguate.
Assigned, not derivedIDs are explicitly tracked in the atlas JSONs — they are not hashes of the slug or computed from sort order. Adding a new entity allocates the next free integer; renaming a slug does not change its numerical_id.
Not a sportsbook IDThis is SharpAPI’s identifier, not the sportsbook’s internal one. A book’s native event/market/selection IDs are still emitted on a per-row basis — see external_event_id, selection_id, market_id, and external_ids on the Events endpoint.

When fields are absent

The nested reference objects are emitted only when the underlying entity has been mapped in the atlas. For unmapped entities — typically long-tail leagues, exotic markets, or freshly added sportsbooks before catalog assignment — the corresponding *_ref block is omitted (or has numerical_id: null) and the existing string field on the row is the only ID you’ll see.

In practice:

  • Major sports, leagues, and books are fully mapped — expect every *_ref block to be present.
  • Player-prop markets and corners/cards/period markets in soccer have the broadest catalog; some niche prop types are still being assigned.
  • Team abbreviation is populated where one is broadly known (US major leagues, EPL, ATP/WTA short codes). For minor / international teams it may be absent.

Consumers should treat every nested block as optional. Generic clients should fall back to the flat string field (sport, league, sportsbook, home_team, away_team, market_type) when the corresponding *_ref is not present.

Indexing & joins

Use numerical_id as the primary key when storing odds/opportunities in your own database. Integer keys are smaller, cheaper to index, and stable across slug renames or display-label tweaks.

Cross-feed mapping

If you ingest from multiple data providers, numerical_id gives you a fast equality check inside SharpAPI rows. For mapping across vendors, the slug id (mlb, pinnacle, new_york_yankees) is still the more portable join key — slugs are human-readable and tend to overlap across vendors more than integer IDs do.

UI display

Use name (sports, teams) or label (leagues, markets, sportsbooks) for display; the abbreviation on home/away is appropriate for compact cells.

Streaming

The same nested objects appear on /api/v1/stream/odds SSE frames and on WebSocket v1 / v1.5 odds payloads — no separate stream is required.

Field reference

Reference endpoints

Every reference endpoint adds numerical_id to its existing object schema. /teams additionally adds abbreviation.

EndpointAdded fieldTypeNotes
/sportsnumerical_idinteger | nullSport-scoped domain
/leaguesnumerical_idinteger | nullLeague-scoped domain
/sportsbooksnumerical_idinteger | nullSportsbook-scoped domain
/marketsnumerical_idinteger | nullMarket-type-scoped domain
/teamsnumerical_id, abbreviation, logo, city, mascot, conference, divisioninteger | null, string | nullTeam-scoped domain. Latter five are atlas metadata sourced from OpticOdds.

Nested reference blocks on odds & opportunity legs

BlockWhereFieldsPurpose
home, awayEvery odds row, every opportunity legid, numerical_id, name, abbreviation, logo, city, mascot, conference, divisionResolve the two competitors without a separate /teams call.
sport_refSameid, numerical_id, nameDisplay-ready sport reference.
league_refSameid, numerical_id, labelDisplay-ready league reference.
market_refSameid, numerical_id, labelDisplay-ready market reference (canonical market type).
sportsbook_refSameid, numerical_id, labelDisplay-ready sportsbook reference.

All inner fields are optional within a block. A block may be present with a null numerical_id if the slug has been mapped but the integer assignment is pending; both numerical_id and the entire block may also be absent for unmapped entities.

Team metadata fields

The home / away blocks expose five additional optional metadata fields beyond id / numerical_id / name / abbreviation. They are sourced from the SharpAPI atlas and populated for the broad majority of teams (≈93% on logo, with comparable coverage on the rest):

FieldExampleNotes
logo"https://cdn.opticodds.com/team-logos/baseball/36.png"Full CDN URL for a team crest. Treat the host as opaque; SharpAPI may re-host the same asset under its own domain in the future.
city"New York"The team’s geographic anchor. For multi-city teams (e.g. the New York Football Giants playing in NJ) we follow the league’s conventional city.
mascot"Yankees"The team mascot / nickname portion of the full name.
conference"AL", "AFC", "Western"League-defined conference / grouping. Format varies per league.
division"East Division", "NL East", "Pacific Division"Sub-grouping within the conference, league-defined.

Individual-sport competitors (tennis players, MMA fighters, golfers, drivers) generally have none of these fields populated — they are not “teams” in the conventional sense and inherit only id / numerical_id / name.

Migration

There is nothing to migrate. Continue using the flat string fields if they cover your needs. Adopt the *_ref blocks and numerical_id selectively when:

  • you need a stable integer key for storage,
  • you want display-ready labels without a second API call,
  • or you’re building a cross-feed normalization layer.

The flat fields and the nested blocks describe the same row — they will not contradict each other.

Last updated on