Rate Limits
Each plan comes with a monthly request quota and a per-minute rate limit. Stay inside both and your requests are never rejected.
How limits work
Two limits apply to every account:
- Monthly quota — the number of requests included in your plan each month.
- Rate limit — the number of requests you can make per minute. It smooths out bursts so one busy client can’t starve the others.
Go over either one and the API responds with 429 Too Many Requests until that limit resets.
Limits by plan
| Plan | Monthly requests | Rate limit |
|---|---|---|
| Free | [X,XXX] requests | [X / min] |
| Starter | [XX,XXX] requests | [X / min] |
| Professional | [XXX,XXX] requests | [X / min] |
| Enterprise | Custom | Custom |
See Pricing for everything included in each plan, or contact sales for custom limits.
Request cost
Each call to an endpoint counts as one request, unless the endpoint’s documentation lists a different cost. Every reference page shows it under Request cost in the API information card.
Paginated lists cost one request per page: reading five pages of fixtures uses five requests. See Pagination.
Rate-limit headers
Every response includes headers that tell you where you stand:
| Information | Header |
|---|---|
| Your limit | [Header names to confirm] |
| Requests remaining | [Header names to confirm] |
| When the limit resets | [Header names to confirm] |
Read them on every response and slow down before you reach the limit, not after.
Handling 429 responses
A request over the limit is rejected and returns no data:
{ "error": { "status": 429, "message": "Rate limit reached" }}Wait until the limit resets, then retry. If you don’t track the reset time, back off exponentially — wait 1 second, then 2, then 4 — and give up after a few attempts:
async function getWithRetry(url, { retries = 3 } = {}) { for (let attempt = 0; ; attempt++) { const res = await fetch(url, { headers: { "x-api-key": process.env.GOSPORTS_API_KEY }, }); if (res.status !== 429 || attempt >= retries) return res; // Back off: 1s, 2s, 4s await new Promise((r) => setTimeout(r, 1000 * 2 ** attempt)); }}const res = await getWithRetry("https://api.gosportsapi.com/v1/football/fixtures/live");Staying under the limit
- Poll live endpoints every 60 seconds. Data freshness is about 30 seconds, so polling faster spends requests without getting fresher data.
- Cache responses and serve all of your users from one upstream request. See Caching.
- Filter with
league_id,dateorteam_idso you fetch only what you need. - Spread scheduled jobs out instead of starting them all at the same moment.
- Store data you’ve already fetched rather than requesting it again. See Syncing data.