# API FAQ

### Sportmonks Football API v3

### Most popular questions

#### Why is my data missing?

**Short answer:** Data might be missing due to subscription plan limitations, missing includes, incorrect filters, or the data genuinely not existing for that fixture/league.

**Common causes & solutions:**

**1. Missing includes**

Your subscription includes the data, but you didn't request it with `include`.

```javascript
// ❌ Wrong - No includes, missing participant data
const fixture = await fetch('/fixtures/123?api_token=TOKEN');
// Returns: { id: 123, name: "Match", participants: undefined }

// ✅ Correct - With includes
const fixture = await fetch('/fixtures/123?api_token=TOKEN&include=participants;events;statistics');
// Returns: Full data with participants, events, and statistics
```

**Solution:** Always use `include` parameter to get related data.\
[Learn more about includes](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/includes)

**2. Plan limitations**

Your plan may not include certain data types (odds, predictions, player statistics, etc.)

**Check your plan:** Visit [MySportmonks](https://my.sportmonks.com/) → Subscriptions → My subscription

**Base plans all include**

* ✅ Basic match data
* ✅ Live scores
* ✅ Player statistics
* ✅ Team data
* ✅ Fixtures & results
* ✅ Lineups
* ✅ Events
* ✅ Statistics

{% hint style="info" %}
**Note**: Your plan may not include certain data types (odds, predictions etc.). Odds, Predictions, Pressure Index & Expected Goals are available as add-ons. You can add these add-ons on top of your plan.
{% endhint %}

| Plan           | Leagues     | API Calls/Hour | Price      |
| -------------- | ----------- | -------------- | ---------- |
| **Starter**    | 5 leagues   | 2,000          | €29/month  |
| **Growth**     | 30 leagues  | 2,500          | €99/month  |
| **Pro**        | 120 leagues | 3,000          | €249/month |
| **Enterprise** | All leagues | 5,000          | Custom     |

**Solution:** Upgrade your plan or verify which data your plan includes.\
[Compare plans](https://www.sportmonks.com/pricing)

**3. Data not available yet**

For upcoming fixtures, some data (lineups) isn't available until closer to kickoff.

**Typical data availability timeline:**

```
```

**Solution:** Check `fixture.starting_at` to see when the match begins. Request data at appropriate times.

**4. League/Competition not covered**

Some lower-tier leagues or cup competitions may have limited data coverage.

**Check coverage:**

```javascript
// Get all leagues in your subscription
const leagues = await fetch('/core/leagues?api_token=TOKEN');

// Check if specific league is covered
const isLeagueIncluded = leagues.data.some(l => l.id === YOUR_LEAGUE_ID);
```

**Solution:** Verify league coverage in [MySportmonks](https://my.sportmonks.com/) → Data Coverage

**5. Fixture state**

Data availability depends on fixture state (NS = Not Started, LIVE = In Progress, FT = Finished, etc.)

```javascript
const fixture = await fetch('/fixtures/123?api_token=TOKEN&include=state');

console.log(fixture.state.name); // "NS", "LIVE", "FT", "POSTP", "CANCL"

// Check what data is available
if (fixture.state.name === 'NS') {
  // Only pre-match data available
} else if (fixture.state.name === 'LIVE') {
  // Live scores, events available
} else if (fixture.state.name === 'FT') {
  // All data available
}
```

**Solution:** Check fixture state before expecting certain data types.\
[Learn about fixture states](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/states)

#### How do I reduce API calls?

**Short answer:** Use includes to combine requests, cache reference data, use batch endpoints, and implement smart polling strategies.

**5 Proven strategies:**

**1. Use Includes (50-80% Reduction)**

Combine multiple requests into one:

```javascript
// ❌ Bad - 3 separate requests
const fixture = await fetch('/fixtures/123?api_token=TOKEN');
const teams = await fetch('/teams/53?api_token=TOKEN');
const stats = await fetch('/statistics/fixtures/123?api_token=TOKEN');
// Total: 3 API calls

// ✅ Good - 1 request with includes
const fixture = await fetch('/fixtures/123?api_token=TOKEN&include=participants;statistics;events');
// Total: 1 API call (67% savings!)
```

**Impact:** Reduces 3 calls to 1 = **67% savings**

[Complete includes guide](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/includes)

**2. Cache reference data (30-50% Reduction)**

Data that rarely changes should be cached:

**What to cache & for how long:**

| Data Type                  | Cache Duration | Why                |
| -------------------------- | -------------- | ------------------ |
| Types (statistics, events) | **1 week**     | Never changes      |
| States                     | **1 week**     | Static data        |
| Leagues                    | **1 day**      | Rarely updates     |
| Teams                      | **1 hour**     | Occasional updates |
| Venues                     | **1 week**     | Stable data        |
| Markets/Bookmakers         | **1 day**      | Infrequent changes |

**Example implementation:**

```javascript
class CachedAPI {
  constructor(token) {
    this.token = token;
    this.cache = new Map();
  }
  
  async getCached(endpoint, cacheDuration) {
    const now = Date.now();
    
    if (this.cache.has(endpoint)) {
      const { data, timestamp } = this.cache.get(endpoint);
      if (now - timestamp < cacheDuration) {
        console.log('✅ Using cache - 0 API calls');
        return data;
      }
    }
    
    console.log('📡 Fetching from API');
    const response = await fetch(`${endpoint}?api_token=${this.token}`);
    const data = await response.json();
    
    this.cache.set(endpoint, { data, timestamp: now });
    return data;
  }
}

// Usage
const api = new CachedAPI('YOUR_TOKEN');

// First call - fetches from API (1 call)
const types = await api.getCached('/core/types', 7 * 24 * 60 * 60 * 1000);

// Next 1000 lookups - from cache (0 calls!)
const type1 = types.data.find(t => t.id === 86);
const type2 = types.data.find(t => t.id === 52);
// ... 998 more lookups = 0 API calls
```

**Impact:** 1000 requests reduced to 1 = **99.9% savings**

**3. Use batch endpoints (40-60% Reduction)**

Fetch multiple resources in one request:

```javascript
// ❌ Bad - 10 separate requests
for (const id of [123, 456, 789, 101, 102, 103, 104, 105, 106, 107]) {
  await fetch(`/fixtures/${id}?api_token=TOKEN`);
}
// Total: 10 API calls

// ✅ Good - 1 batched request
const ids = [123, 456, 789, 101, 102, 103, 104, 105, 106, 107];
await fetch(`/fixtures/multi/${ids.join(',')}?api_token=TOKEN`);
// Total: 1 API call (90% savings!)
```

**Available batch endpoints:**

* `/fixtures/multi/{ids}`
* `/teams/multi/{ids}`
* `/players/multi/{ids}`

**4. Smart polling for livescores (40-60% reduction)**

Only poll when necessary:

```javascript
// ❌ Bad - Poll every 5 seconds, always
setInterval(() => {
  fetch('/livescores?api_token=TOKEN');
}, 5000);
// = 720 calls/hour

// ✅ Good - Adaptive polling
function adaptivePolling() {
  const hasLiveMatches = checkIfAnyLive();
  
  if (hasLiveMatches) {
    return setInterval(pollLivescores, 10000); // 10s when live
  } else {
    return setInterval(pollLivescores, 300000); // 5min when no live matches
  }
}
// = 360 calls/hour during matches, 12 calls/hour otherwise (95% savings!)
```

**Better yet - Use `/livescores/latest`:**

```javascript
// Only fetches matches that updated in last 10 seconds
const updates = await fetch('/livescores/latest?api_token=TOKEN');
// Only updates changed matches in UI
```

**5. Use `filters=populate` for bulk operations**

When populating databases, use populate filter:

```javascript
// ❌ Slow - Default pagination (25 per page)
// For 1000 fixtures = 40 requests
for (let page = 1; page <= 40; page++) {
  await fetch(`/fixtures?page=${page}&api_token=TOKEN`);
}

// ✅ Fast - With populate filter (1000 per page)
await fetch(`/fixtures?filters=populate&per_page=1000&api_token=TOKEN`);
// For 1000 fixtures = 1 request (97.5% savings!)
```

**Note:** `populate` disables includes, use only for bulk data collection.

**Combined impact:**

Before optimisation:

* Daily API calls: 20,000

After all strategies:

* Daily API calls: 2,500

**Total savings: 87.5%** 🎉

[Complete optimisation guide](https://docs.sportmonks.com/v3/api/rate-limit)

#### What's the difference between endpoints and entities?

**Short answer:** Endpoints are URLs you call. Entities are the data types that count toward rate limits. Multiple endpoints can use the same entity.

**Detailed explanation:**

**Endpoints** = The API URLs you make requests to

**Entities** = The underlying resource type (what counts for rate limits)

**Key concept:** Rate limits are **per entity**, not per endpoint.

**Example:**

```javascript
// These are different ENDPOINTS:
await fetch('/fixtures/123');           // Endpoint 1
await fetch('/fixtures/date/2026-03-17'); // Endpoint 2
await fetch('/livescores/inplay');      // Endpoint 3

// But they ALL use the same ENTITY: "Fixture"
// So they all count toward the SAME rate limit bucket
```

**Rate limit structure:**

Each entity has its own rate limit depending on your plan:

| Entity      | Your Endpoints                                                        |
| ----------- | --------------------------------------------------------------------- |
| **Fixture** | `/fixtures`, `/fixtures/{id}`, `/fixtures/date/{date}`, `/livescores` |
| **Team**    | `/teams`, `/teams/{id}`, `/teams/search/{name}`                       |
| **Player**  | `/players`, `/players/{id}`, `/players/search/{name}`                 |
| **League**  | `/leagues`, `/leagues/{id}`                                           |

**Practical example:**

```javascript
// Scenario: You make these requests in 1 hour

// Fixture entity requests (all count together)
await fetch('/fixtures/123');          // Fixture count: 1
await fetch('/fixtures/456');          // Fixture count: 2
await fetch('/livescores');            // Fixture count: 3
await fetch('/fixtures/date/today');   // Fixture count: 4
// Current Fixture usage: 4/2000

// Team entity requests (separate counter)
await fetch('/teams/53');              // Team count: 1
await fetch('/teams/62');              // Team count: 2
// Current Team usage: 2/2000

// Current total usage:
// - Fixture entity: 4/2000
// - Team entity: 2/2000
```

**Why this matters:**

You could theoretically make:

* 3,000 Fixture requests
* 3,000 Team requests
* 3,000 Player requests
* 3,000 League requests

\= **12,000+ total API requests per hour** across different entities!

**How to check which entity:**

Every API response includes:

```json
{
  "data": { ... },
  "rate_limit": {
    "resets_in_seconds": 1847,
    "remaining": 2996,
    "requested_entity": "Fixture"
  }
}
```

[Complete rate limiting guide](https://docs.sportmonks.com/v3/api/rate-limit)

#### How often is data updated?

**Short answer:** Live match data updates every 10-30 seconds. Reference data (teams, leagues) updates less frequently. Update frequency varies by data type.

**Update frequency by data type:**

| Data Type        | Update Frequency | When It Updates                          |
| ---------------- | ---------------- | ---------------------------------------- |
| **Live Scores**  | 10-30 seconds    | During live matches                      |
| **Match Events** | 10-30 seconds    | Goals, cards, substitutions in real-time |
| **Statistics**   | 30-60 seconds    | During and after matches                 |
| **Lineups**      | Once             | Published 1 hour before kickoff          |
| **Standings**    | After each match | When match finishes                      |
| **Fixtures**     | Daily            | New fixtures added, dates updated        |
| **Teams**        | Weekly           | Squad changes, manager updates           |
| **Players**      | Weekly           | Transfers, injuries                      |
| **Leagues**      | Monthly          | Seasonal updates                         |
| **Venues**       | Rarely           | Only when stadium info changes           |
| **Types/States** | Never            | Static reference data                    |

**Live match data timeline:**

```
Pre-Match
├─ Lineups → Updated 4–6 times per day for higher-coverage leagues; checked every 5 minutes during the final hour before kickoff
├─ Weather conditions → Updated 4 times per day; every 30 minutes for upcoming fixtures
└─ Pre-match odds → Updated every 1–15 minutes depending on the bookmaker

During Match (90+ minutes)
├─ Scores → Updated within 10 seconds of a goal
├─ Events → Updated within 10–30 seconds
├─ Statistics → Updated every 30–60 seconds
├─ In-play odds → Updated every 2–10 seconds
└─ Live commentary → Updated at the same frequency as events

Post-Match (after final whistle)
├─ Final statistics → Available within 10 minutes, then regularly updated for several days if changes occur
├─ Player ratings → Already live during the match, updated every minute; updated alongside statistics post-match where applicable
├─ Match highlights → Not currently available
└─ Standings → Available shortly after match completion

```

**Recommended polling intervals:**

```javascript
// Live matches - Poll every 10 seconds
if (fixture.state.name === 'LIVE') {
  setInterval(fetchLiveData, 10000);
}

// Pre-match - Poll every 30 minutes (for lineup updates)
if (fixture.state.name === 'NS' && hoursUntilKickoff < 2) {
  setInterval(fetchPreMatchData, 1800000);
}

// Standings - Poll once after each match completes
if (fixture.state.name === 'FT') {
  fetchStandings(); // One-time fetch
}

// Reference data - Cache for 1 week
const types = await getCached('/core/types', 604800000);
```

**Special cases:**

**Expected goals (xG)**

* Available during live matches, updated every 60 seconds
* Final xG available shortly after the match

**Player statistics**

* All stats (standard, advanced, and xG) are updated live during the match and continue to be updated post-match

**Odds:**

* Pre-match: Updated every 1–15 minutes depending on the bookmaker
* In-play: Updated every 2–10 seconds during live matches

Don't poll more frequently than the data updates. Use appropriate intervals based on data type.

[Learn about fixture states](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/states)

#### Why am I getting rate limited?

**Short answer:** You've exceeded your plans requests per hour for a specific entity. Common causes: polling too frequently, not using includes, not caching reference data.

**Understanding rate limits:**

Every plan has its own requests figure per hour per entity.

**Error message:**

```json
{
  "error": "Too Many Requests",
  "message": "Rate limit of 2000 requests per hour exceeded (This is the base rate for the starter plan)",
  "retry_after": 1847,
  "rate_limit": {
    "remaining": 0,
    "total": 2000,
    "resets_in_seconds": 1847,
    "requested_entity": "Fixture"
  }
}
```

**Common causes:**

**1. Polling too frequently**

```javascript
// ❌ This hits rate limit in 4 hours
setInterval(() => {
  fetch('/livescores?api_token=TOKEN');
}, 5000); // Every 5 seconds = 720 calls/hour
// 4 hours × 720 = 2,880 calls (almost at limit!)

// ✅ Poll smarter
setInterval(() => {
  fetch('/livescores/latest?api_token=TOKEN'); // Only updated matches
}, 10000); // Every 10 seconds = 360 calls/hour
```

**2. Not using includes**

```javascript
// ❌ Making separate requests
for (let i = 0; i < 100; i++) {
  await fetch(`/fixtures/${ids[i]}?api_token=TOKEN`); // 100 calls
  await fetch(`/teams/${teamIds[i]}?api_token=TOKEN`); // 100 calls
}
// Total: 200 calls for 100 fixtures

// ✅ Using includes
const response = await fetch(
  `/fixtures/multi/${ids.join(',')}?api_token=TOKEN&include=participants`
);
// Total: 1 call (99.5% reduction!)
```

**3. Not caching reference data**

```javascript
// ❌ Fetching types for every fixture
for (let fixture of fixtures) {
  const types = await fetch('/core/types?api_token=TOKEN'); // 100 calls
  const statType = types.data.find(t => t.id === fixture.type_id);
}

// ✅ Cache types once
const types = await fetch('/core/types?api_token=TOKEN'); // 1 call
const typeMap = new Map(types.data.map(t => [t.id, t]));

for (let fixture of fixtures) {
  const statType = typeMap.get(fixture.type_id); // 0 API calls
}
// Savings: 99 calls (99% reduction!)
```

**How to fix:**

**Immediate solutions:**

1. **Wait for reset:**

   ```javascript
   // Response tells you when limit resets
   const retryAfter = response.retry_after; // seconds
   console.log(`Wait ${retryAfter}s before retrying`);
   ```
2. **Implement retry logic:**

   ```javascript
   async function fetchWithRetry(url) {
     try {
       const response = await fetch(url);
       if (response.status === 429) {
         const data = await response.json();
         await sleep(data.retry_after * 1000);
         return fetchWithRetry(url); // Retry after waiting
       }
       return response.json();
     } catch (error) {
       console.error('Error:', error);
     }
   }
   ```

**Long-term solutions:**

1. Use includes to reduce requests by 50-80%
2. Cache reference data (types, states, leagues)
3. Use `/livescores/latest` instead of `/livescores`
4. Implement smart polling (only when needed)
5. Use batch endpoints (`/fixtures/multi/{ids}`)
6. Upgrade your rate limit if consistently hitting it

[Complete rate limiting guide](https://docs.sportmonks.com/v3/api/rate-limit)

#### How do I debug API responses?

**Short answer:** Use browser DevTools Network tab, console.log responses, check response status codes, verify includes are working, and use the API Explorer.

**6-Step debugging process:**

**Step 1: Check response status**

```javascript
const response = await fetch('/fixtures/123?api_token=TOKEN');

console.log('Status:', response.status);
console.log('OK?:', response.ok);

// Common status codes:
// 200 = Success
// 401 = Invalid API token
// 404 = Resource not found
// 429 = Rate limited
// 500 = Server error
```

**Step 2: Log full response**

```javascript
const response = await fetch('/fixtures/123?api_token=TOKEN&include=participants');
const data = await response.json();

console.log('Full response:', data);
console.log('Data:', data.data);
console.log('Participants:', data.data.participants);
console.log('Rate limit:', data.rate_limit);
```

**Step 3: Verify includes are working**

```javascript
const response = await fetch('/fixtures/123?api_token=TOKEN&include=participants;events');
const data = await response.json();

// Check if includes loaded
console.log('Has participants?', Array.isArray(data.data.participants));
console.log('Has events?', Array.isArray(data.data.events));

if (!data.data.participants) {
  console.error('❌ Participants not included! Check:');
  console.error('1. Is include parameter spelled correctly?');
  console.error('2. Does your plan include this data?');
  console.error('3. Is data available for this fixture?');
}
```

**Step 4: Use browser DevTools**

Open browser Console (F12) and check:

**Network tab:**

1. Find your API request
2. Click on it
3. Check **Headers** tab → Request URL (is it correct?)
4. Check **Response** tab → See raw JSON
5. Check **Preview** tab → Formatted view

**Step 5: Test in API playground**

[**MySportmonks API Playground**](https://my.sportmonks.com/api/playground)

1. Select endpoint (e.g., `/fixtures/{id}`)
2. Enter ID: `123`
3. Add includes: `participants;events`
4. Click "Send Request"
5. View response

Benefits:

* No code needed
* Verifies endpoint works
* Shows exact response structure
* Copies working code examples

**Step 6: Check common issues**

**Issue 1: Data is `null` or `undefined`**

```javascript
// ❌ Data is null
const teams = data.data.participants; // null

// Debugging:
console.log('Fixture state:', data.data.state?.name);
// If state is "NS" (Not Started), some data isn't available yet

console.log('Subscription includes:', data.subscription);
// Check if your plan includes this data

console.log('Include param:', new URL(requestUrl).searchParams.get('include'));
// Verify you actually included it
```

**Quick debug helper:**

```javascript
function debugResponse(response, data) {
  console.group('🔍 API Debug Info');
  console.log('Status:', response.status, response.ok ? '✅' : '❌');
  console.log('URL:', response.url);
  console.log('Has data?', !!data?.data);
  console.log('Rate limit:', data?.rate_limit?.remaining, '/', data?.rate_limit?.total);
  console.log('Response:', data);
  console.groupEnd();
}

// Usage
const response = await fetch(url);
const data = await response.json();
debugResponse(response, data);
```

[Error codes reference](https://docs.sportmonks.com/v3/api/error-codes)

#### Can I use the API in production?

**Short answer:** Yes! The Sportmonks API is designed for production use. Make sure you handle errors, implement caching, respect rate limits, and secure your API token.

**Production readiness checklist:**

```
□ API token stored securely (env variables, secrets manager)
□ Error handling on all API calls
□ Rate limit handling with retry logic
□ Caching for reference data
□ Request timeouts configured
□ Monitoring/logging in place
□ Graceful degradation for failures
□ Backend proxy (not direct frontend calls)
□ HTTPS only
□ API usage metrics tracked
□ Backup/fallback strategies
□ Load testing completed
□ Error tracking service configured (Sentry, etc.)
```

[Best practices guide](https://docs.sportmonks.com/v3/welcome/best-practices)\
[Rate limiting guide](https://docs.sportmonks.com/v3/api/rate-limit)

#### What's the difference between plans?

**Short answer:** Plans differ in data access, number of leagues, rate limits, and support level.

**Plan comparison:**

<table><thead><tr><th width="147.800048828125">Feature</th><th width="145.4000244140625">Starter</th><th width="139.0001220703125">Growth</th><th width="152">Pro</th><th>Enterprise</th></tr></thead><tbody><tr><td><strong>Price</strong></td><td>€29/month</td><td>€99/month</td><td>€249/month</td><td>Custom</td></tr><tr><td><strong>Leagues</strong></td><td><p>5</p><p>leagues</p></td><td><p>30 </p><p>leagues</p></td><td><p>120 </p><p>leagues</p></td><td>All leagues</td></tr><tr><td><strong>Rate Limit</strong></td><td>2K/hour</td><td>2.5K/hour</td><td>3K/hour</td><td>5K/hour</td></tr><tr><td><strong>Support</strong></td><td>Email</td><td>Priority Email</td><td>Priority + Chat</td><td>Dedicated</td></tr></tbody></table>

**Free Trial:**

All paid plans include a **14-day free trial**. No credit card required.

**Compare plans:** [Sportmonks pricing](https://www.sportmonks.com/football-api/plans-pricing/)

### FAQs by category

#### Authentication & Access

**Q: How do I get an API token?**

Sign up at [sportmonks.com](https://www.sportmonks.com/), then find your API token at [MySportmonks](https://my.sportmonks.com/) → API → Token.

**Q: My API token isn't working. What should I check?**

Common issues:

1. Token not included: Use `?api_token=YOUR_TOKEN`
2. Typo in token: Copy-paste from MySportmonks
3. Wrong subscription: Verify correct token
4. Subscription expired: Check [MySportmonks](https://my.sportmonks.com/)

**Q: Should I use different tokens for development and production?**

Yes, recommended! Get separate subscriptions to prevent development work from affecting production rate limits.

#### Data & Content

**Q: Which leagues are included in my plan?**

Check [MySportmonks](https://my.sportmonks.com/) → Data Coverage, or:

```javascript
const leagues = await fetch('/core/leagues?api_token=YOUR_TOKEN');
console.log('Included leagues:', leagues.data.length);
```

**Q: How do I get historical data?**

Use date filters:

```javascript
// Fixtures from specific date
const fixtures = await fetch('/fixtures?api_token=TOKEN&filters=fixtureDate:2024-01-01');

// Date range
const fixtures = await fetch('/fixtures?api_token=TOKEN&filters=fixtureStartDate:2024-01-01;fixtureEndDate:2024-01-31');
```

**Q: What's the difference between includes and selects?**

**Includes** = Add related data\
**Selects** = Limit which fields return

```javascript
// Includes - get MORE data
fetch('/fixtures/123?include=participants;events');

// Selects - get LESS data (smaller, faster)
fetch('/fixtures/123?select=id,name,starting_at');
```

[Includes guide](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/includes)

#### Performance & Optimisation

**Q: What's the fastest way to get live scores?**

Use `/livescores/latest`:

```javascript
// Only returns matches updated in last 10 seconds
const updates = await fetch('/livescores/latest?api_token=TOKEN');
```

**Q: How can I reduce response size?**

Use `select` parameter:

```javascript
// Default: ~5KB
const fixture = await fetch('/fixtures/123?api_token=TOKEN');

// With select: ~1KB (80% smaller!)
const fixture = await fetch('/fixtures/123?api_token=TOKEN&select=id,name,starting_at,state');
```

**Q: Should I use pagination?**

Yes, for large datasets:

```javascript
// Standard pagination
const page1 = await fetch('/fixtures?api_token=TOKEN&page=1&per_page=100');

// Bulk operations - use populate
const bulk = await fetch('/fixtures?api_token=TOKEN&filters=populate&per_page=1000');
```

#### Billing & Plans

**Q: Can I try before I buy?**

Yes! All paid plans include a **14-day free trial**. No credit card required.

**Q: Can I cancel anytime?**

Yes, cancel anytime at [MySportmonks](https://my.sportmonks.com/) → Subscriptions → Cancel.

**Q: Do you offer annual billing discounts?**

Yes! Annual billing offers \~20% savings. Contact <sales@sportmonks.com>.

#### Technical & Debugging

**Q: Why am I getting CORS errors?**

CORS errors occur when calling API directly from browser.

**Solution:** Create a backend proxy:

```javascript
// Backend (Node.js/Express)
app.get('/api/fixtures/:id', async (req, res) => {
  const data = await fetch(
    `https://api.sportmonks.com/v3/football/fixtures/${req.params.id}?api_token=${process.env.TOKEN}`
  );
  res.json(await data.json());
});

// Frontend calls your backend
fetch('/api/fixtures/123'); // No CORS!
```

**Q: How do I handle null values?**

Use optional chaining:

```javascript
// ❌ Unsafe
const teamName = fixture.participants.home.name;

// ✅ Safe
const teamName = fixture?.participants?.find(p => p.meta.location === 'home')?.name ?? 'Unknown';
```

**Q: How do I search for teams/players?**

Use search endpoints:

```javascript
// Search teams
const teams = await fetch('/teams/search/Arsenal?api_token=TOKEN');

// Search players
const players = await fetch('/players/search/Messi?api_token=TOKEN');
```

#### Integration & Development

**Q: Can I use this with React/Vue/Angular?**

Absolutely! Example React hook:

```javascript
import { useState, useEffect } from 'react';

function useFixture(id) {
  const [fixture, setFixture] = useState(null);
  const [loading, setLoading] = useState(true);
  
  useEffect(() => {
    async function fetchFixture() {
      const response = await fetch(`/api/fixtures/${id}`);
      setFixture(await response.json());
      setLoading(false);
    }
    fetchFixture();
  }, [id]);
  
  return { fixture, loading };
}
```

### Still have questions?

#### Get help

**Email Support:** <support@sportmonks.com>

#### Useful links

* [Complete API Documentation](https://docs.sportmonks.com/v3)
* [Tutorials & Guides](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials)
* [API Playground](https://my.sportmonks.com/api/playground)
* [Status Page](https://status.sportmonks.com/)
* [My Account](https://my.sportmonks.com/)
