Pagination and limits

Paginated endpoints take limit and offset.

The envelope

A paginated response wraps its results in data and adds two objects.

dataobject[]requiredThe results themselves. The shape depends on the endpoint and the sport.
paginationPaginationResponserequiredHow many results exist and where this page sits.3 fields
totalCountnumberrequiredResults matching your query, not the number returned on this page.
offsetnumberrequiredThe offset this page was fetched at.
limitnumberrequiredThe page size used.
planPlanResponserequiredYour current API subscription tier, and a message explaining it.2 fields
tierstringrequiredYour current API subscription tier.
messagestringrequiredExplanation message regarding your current tier.

Example response

200 application/json
{
  "data": [
    "..."
  ],
  "pagination": {
    "totalCount": 490,
    "offset": 20,
    "limit": 100
  },
  "plan": {
    "tier": "BASIC",
    "message": "Some results might be hidden with FREE tier. Check your API coverage for more information: https://rapidapi.com/highlightly-api-highlightly-api-default/api/sport-highlights-api/details"
  }
}

The envelope is the same for every sport. Only what sits inside data changes.

Paging through results

limit sets the page size and offset skips that many results. Page by holding limit steady and advancing offset until you have covered totalCount.

const key = process.env.HIGHLIGHTLY_API_KEY
const limit = 40
const all = []

let offset = 0
let total = Infinity

while (offset < total) {
  const url = `https://sports.highlightly.net/football/highlights?leagueId=173537&limit=${limit}&offset=${offset}`
  const response = await fetch(url, {
    headers: { 'x-rapidapi-key': key }
  })

  if (!response.ok) {
    throw new Error(`Highlightly responded ${response.status}`)
  }

  const { data, pagination } = await response.json()

  all.push(...data)

  total = pagination.totalCount
  offset += limit
}

totalCount is the number of results matching your query, not the number on the current page, so it is the value to page against.

Default page sizes are set per endpoint, and an endpoint has the same default on every prefix that carries it.

Which endpoints paginate

/matches, /highlights, /odds and /bookmakers return the envelope on every prefix, and so do /leagues and /players wherever they exist.

/teams returns a plain array on /american-football, /nba, /nhl and /baseball, and takes no limit or offset. /standings returns a paginated envelope on all four single league prefixes.

Knowing when results were hidden

The plan object describes your tier. On a restricted tier some results might be hidden, so a short page is not necessarily the end of the data.

plan.tier names your subscription, and plan.message explains it. An example message follows.

Some results might be hidden with FREE tier. Check your API coverage for more information.

It carries a link to your coverage details.

On the Basic and Free plans, /highlights may be restricted, while /odds and /highlights/geo-restrictions/{id} are not available. That holds for every prefix.

Plans and their limits are listed on the All Sports API page.

Rate limits

Two response headers track your quota.

Header Meaning
x-ratelimit-requests-limit Requests your plan allows. Static.
x-ratelimit-requests-remaining Requests left. At zero, requests fail until the daily quota resets.

One quota covers every sport prefix. A product polling live scores across several of them spends it faster than a single sport integration would, since every prefix draws on the same allowance.

Paging a large result set is the other heavy cost, since each page is one request. Cache results whose refresh interval is measured in hours rather than minutes.