# States

### What does the include do?

The `state` include allows you to retrieve comprehensive information about the current state of a fixture. The state indicates the exact phase of the match - whether it's scheduled, live, finished, postponed, cancelled, or in any other specific state. This is essential for properly displaying match status and handling different scenarios in your application.

### Why use states?

The state include is crucial for:

* **Match status display**: Show accurate status (Live, Finished, Postponed, etc.)
* **Real-time filtering**: Filter fixtures by state (e.g., show only live matches)
* **Notification systems**: Trigger alerts when matches change state
* **Data synchronisation**: Know when to refresh match data
* **Error handling**: Handle postponed, cancelled, or interrupted matches
* **User experience**: Provide contextual information based on match state

### Requesting states

To retrieve state information for a fixture, use the following include:

```http
https://api.sportmonks.com/v3/football/fixtures
?api_token=YOUR_TOKEN&include=state
```

Or for a specific fixture:

```http
https://api.sportmonks.com/v3/football/fixtures/{fixture_id}
?api_token=YOUR_TOKEN&include=state
```

### Response structure

When you include `state` in your request, you'll receive a state object:

```json
{
   "data": {
    "id": 19568462,
    "sport_id": 1,
    "league_id": 2,
    "season_id": 25580,
    "stage_id": 77478049,
    "group_id": null,
    "aggregate_id": null,
    "round_id": 388953,
    "state_id": 5,
    "venue_id": 204,
    "name": "Arsenal vs FC Bayern M\u00fcnchen",
    "starting_at": "2025-11-26 20:00:00",
    "result_info": "Arsenal won after full-time.",
    "leg": "1\/1",
    "details": null,
    "length": 90,
    "placeholder": false,
    "has_odds": true,
    "has_premium_odds": true,
    "starting_at_timestamp": 1764187200,
    "state": {
      "id": 5,
      "state": "FT",
      "name": "Full Time",
      "short_name": "FT",
      "developer_name": "FT"
    }
  }
}
```

### Field descriptions

| Field            | Type    | Description                                         |
| ---------------- | ------- | --------------------------------------------------- |
| `id`             | integer | Unique identifier for this state                    |
| `state`          | string  | Short code for the state (e.g., "FT", "LIVE", "NS") |
| `name`           | string  | Full descriptive name of the state                  |
| `short_name`     | string  | Short display name for the state                    |
| `developer_name` | string  | Programming-friendly name (uppercase, underscores)  |

### Complete list of fixture states

| ID | State Code         | Name                      | Description                                                                                   |
| -- | ------------------ | ------------------------- | --------------------------------------------------------------------------------------------- |
| 1  | NS                 | Not Started               | The initial status of a fixture.                                                              |
| 2  | INPLAY\_1ST\_HALF  | 1st Half                  | The game is in play (first half).                                                             |
| 3  | HT                 | Half Time                 | Match is at half time break                                                                   |
| 4  | BREAK              | Regular Time Finished     | Waiting for extra time to start.                                                              |
| 5  | FT                 | Full Time                 | The game ended after 90 minutes. When going to extra time, this appears briefly before BREAK. |
| 6  | INPLAY\_ET         | Extra Time                | Extra time (first half) is in progress.                                                       |
| 7  | <p>AET</p><p></p>  | Finished After Extra Time | The match has ended after 120 minutes.                                                        |
| 8  | FT\_PEN            | Full-Time After Penalties | The match finished following a penalty shootout.                                              |
| 9  | INPLAY\_PENALTIES  | Penalty Shootout          | Penalties are being taken to decide the winner.                                               |
| 10 | POSTPONED          | Postponed                 | The match has been postponed to another date.                                                 |
| 11 | SUSPENDED          | Suspended                 | The match is suspended and will continue later.                                               |
| 12 | CANCELLED          | Cancelled                 | The match has been permanently cancelled.                                                     |
| 13 | TBA                | To Be Announced           | Fixture has no confirmed date/time yet.                                                       |
| 14 | WO                 | Walk Over                 | A victory was awarded because no opponent was available.                                      |
| 15 | ABANDONED          | Abandoned                 | The match was abandoned and will resume later.                                                |
| 16 | DELAYED            | Delayed                   | Kick-off has been delayed.                                                                    |
| 17 | AWARDED            | Awarded                   | Winner decided externally (administrative decision).                                          |
| 18 | INTERRUPTED        | Interrupted               | Temporarily stopped (e.g., bad weather).                                                      |
| 19 | AU                 | Awaiting Updates          | Temporary state due to data or connectivity delay.                                            |
| 20 | DELETED            | Deleted                   | The fixture is no longer active in standard calls but can still be fetched with `deleted=1`.  |
| 21 | EXTRA\_TIME\_BREAK | Extra Time Break          | Short break between extra time halves.                                                        |
| 22 | INPLAY\_2ND\_HALF  | 2nd Half                  | The game is in play (second half).                                                            |
| 25 | PEN\_BREAK         | Penalties Break           | Waiting for penalties to start.                                                               |
| 26 | PENDING            | Pending                   | The fixture awaits new data or verification.                                                  |

### State transitions and flow

Understanding how states transition is crucial for building robust applications:

#### Normal match flow

```
NS (Not Started)
  ↓ Match starts
LIVE (1st Half)
  ↓ Half-time whistle
HT (Half Time)
  ↓ 2nd half starts
LIVE (2nd Half)
  ↓ Full-time whistle
FT (Full Time)
```

| From | To   | Trigger           | Description                      |
| ---- | ---- | ----------------- | -------------------------------- |
| NS   | LIVE | Match starts      | Game begins (1st half)           |
| LIVE | HT   | Half-time whistle | Match reaches half-time break    |
| HT   | LIVE | 2nd half starts   | Second half commences            |
| LIVE | FT   | Full-time whistle | Match concludes after 90 minutes |

#### Match with extra time

```
FT (After 90 minutes)
  ↓ Extra time starts
ET (Extra Time 1st Half)
  ↓ Break
BREAK (Extra Time Half Time)
  ↓ Extra time 2nd half
ET (Extra Time 2nd Half)
  ↓ Finished
AET (After Extra Time)
```

| From  | To    | Trigger                     | Description                     |
| ----- | ----- | --------------------------- | ------------------------------- |
| FT    | ET    | Extra time starts           | Game continues after full-time  |
| ET    | BREAK | 1st half of extra time ends | Extra time break/half-time      |
| BREAK | ET    | Extra time 2nd half starts  | Second half of extra time       |
| ET    | AET   | Extra time concludes        | Match finished after extra time |

#### Match with penalties

```
AET (After Extra Time)
  ↓ Penalties start
PEN_LIVE (Penalty Shootout)
  ↓ Shootout complete
FT_PEN (Finished on Penalties)
```

| From      | To        | Trigger           | Description                |
| --------- | --------- | ----------------- | -------------------------- |
| AET       | PEN\_LIVE | Penalties start   | Penalty shootout begins    |
| PEN\_LIVE | FT\_PEN   | Shootout complete | Match decided by penalties |

#### Problem states

```
NS (Not Started)
  ↓ Issues arise
DELAYED → (eventually) → LIVE or POSTP
POSTP → (rescheduled) → NS
CANCL → (no transition, final state)

LIVE (During match)
  ↓ Issues arise
INT (Interrupted) → (may resume) → LIVE
SUSP (Suspended) → (may resume) → LIVE
ABAN (Abandoned) → (no transition, final state)
```

| From    | To      | Trigger             | Description                              |
| ------- | ------- | ------------------- | ---------------------------------------- |
| NS      | DELAYED | Issues arise        | Match start delayed                      |
| DELAYED | LIVE    | Delay resolved      | Match eventually starts                  |
| DELAYED | POSTP   | Cannot resume       | Match postponed to another date          |
| POSTP   | NS      | Rescheduled         | Match rescheduled for later date         |
| NS      | CANCL   | Match cancelled     | Final state - no further transitions     |
| LIVE    | INT     | Issues during match | Match interrupted (weather, crowd, etc.) |
| INT     | LIVE    | Issues resolved     | Match resumes                            |
| LIVE    | SUSP    | Match suspended     | Match temporarily suspended              |
| SUSP    | LIVE    | Suspension lifted   | Match resumes after suspension           |
| LIVE    | ABAN    | Match abandoned     | Final state - match abandoned            |

### Filtering by state

To filter fixtures based on specific states, use the `filters` parameter:

```
https://api.sportmonks.com/v3/football/fixtures
?api_token=YOUR_TOKEN&include=state&filters=fixtureStates:2
```

Filter for multiple states:

```
https://api.sportmonks.com/v3/football/fixtures
?api_token=YOUR_TOKEN&include=state&filters=fixtureStates:2,3,10
```

#### Common Filter Scenarios

**Get only live matches:**

```
&filters=fixtureStates:2,10,7
```

States: INPLAY\_1ST\_HALF (2), INPLAY\_2ND\_HALF (22), INPLAY\_ET (6), PEN\_LIVE (7)

**Get finished matches:**

```
&filters=fixtureStates:5,6,8
```

States: FT (5), AET (7), FT\_PEN (8)

**Get problem matches:**

```
&filters=fixtureStates:12,13,14,15,16,17
```

States: CANCELLED (12), ABANDONED (15), DELAYED (16), AWARDED (17), INTERRUPTED (18)

### Nested includes

#### state.type

Get detailed type information for the state:

```
https://api.sportmonks.com/v3/football/fixtures/{fixture_id}
?api_token=YOUR_TOKEN&include=state.type
```

This returns additional type metadata (though state itself is typically sufficient).

### Code examples

#### Python example

```python
import requests

# API configuration
API_TOKEN = "YOUR_TOKEN"

# Get all live fixtures
def get_live_fixtures():
    """Get all currently live matches"""
    url = "https://api.sportmonks.com/v3/football/fixtures"
    params = {
        "api_token": API_TOKEN,
        "include": "state,participants",
        "filters": "fixtureStates:2,6,7,22"  #  INPLAY_1ST_HALF, INPLAY_2ND_HALF, INPLAY_ET, PEN_LIVE
    }
    
    response = requests.get(url, params=params)
    data = response.json()
    
    fixtures = data.get('data', [])
    
    print(f"🔴 {len(fixtures)} live matches found:\n")
    
    for fixture in fixtures:
        state = fixture.get('state', {})
        print(f"{fixture['name']}")
        print(f"  Status: {state['name']} ({state['state']})")
        print()
    
    return fixtures

# Check specific fixture state
def check_fixture_state(fixture_id):
    """Check the state of a specific fixture"""
    url = f"https://api.sportmonks.com/v3/football/fixtures/{fixture_id}"
    params = {
        "api_token": API_TOKEN,
        "include": "state"
    }
    
    response = requests.get(url, params=params)
    data = response.json()
    
    fixture = data['data']
    state = fixture.get('state', {})
    
    return {
        'fixture_id': fixture_id,
        'fixture_name': fixture['name'],
        'state_id': state['id'],
        'state_code': state['state'],
        'state_name': state['name'],
        'is_live': state['id'] in [2, 6, 7, 22],
        'is_finished': state['id'] in [5, 7, 8],
        'has_problem': state['id'] in [12, 15, 16, 17, 18]
    }

# Monitor state changes
def monitor_fixtures(fixture_ids, callback):
    """Monitor fixtures for state changes"""
    previous_states = {}
    
    url = "https://api.sportmonks.com/v3/football/fixtures/multi/" + ",".join(map(str, fixture_ids))
    params = {
        "api_token": API_TOKEN,
        "include": "state"
    }
    
    response = requests.get(url, params=params)
    data = response.json()
    
    for fixture in data.get('data', []):
        fixture_id = fixture['id']
        current_state = fixture['state']['id']
        
        if fixture_id in previous_states:
            if previous_states[fixture_id] != current_state:
                # State changed!
                callback(fixture, previous_states[fixture_id], current_state)
        
        previous_states[fixture_id] = current_state

# Get fixtures with problems
def get_problem_fixtures():
    """Get all postponed, cancelled, or problematic fixtures"""
    url = "https://api.sportmonks.com/v3/football/fixtures"
    params = {
        "api_token": API_TOKEN,
        "include": "state,participants",
        "filters": "fixtureStates:12;15;16;17;18"  # Problem states
    }
    
    response = requests.get(url, params=params)
    data = response.json()
    
    fixtures = data.get('data', [])
    
    # Group by state type
    by_state = {}
    for fixture in fixtures:
        state_name = fixture['state']['name']
        if state_name not in by_state:
            by_state[state_name] = []
        by_state[state_name].append(fixture)
    
    print("⚠️  Problem Fixtures:\n")
    for state_name, matches in by_state.items():
        print(f"{state_name}: {len(matches)} matches")
        for match in matches:
            print(f"  - {match['name']}")
        print()
    
    return by_state

# Categorise fixtures by state
def categorise_fixtures_by_state(fixtures):
    """Categorise fixtures into groups based on state"""
    categories = {
        'upcoming': [],
        'live': [],
        'finished': [],
        'postponed': [],
        'cancelled': [],
        'other': []
    }
    
    for fixture in fixtures:
        state_id = fixture['state']['id']
        
        if state_id == 1:  # Not Started
            categories['upcoming'].append(fixture)
        elif state_id in [2, 6, 7, 22]:  #  INPLAY_1ST_HALF, INPLAY_2ND_HALF, INPLAY_ET, PEN_LIVE
            categories['live'].append(fixture)
        elif state_id in [5, 7, 8]:  # FT, AET, FT_PEN
            categories['finished'].append(fixture)
        elif state_id == 10:  # Postponed
            categories['postponed'].append(fixture)
        elif state_id == 12:  # Cancelled
            categories['cancelled'].append(fixture)
        else:
            categories['other'].append(fixture)
    
    return categories

# Example usage
live_matches = get_live_fixtures()
fixture_state = check_fixture_state(18535517)
print(f"Fixture state: {fixture_state}")
problem_fixtures = get_problem_fixtures()
```

#### JavaScript Example

```javascript
// API configuration
const API_TOKEN = "YOUR_TOKEN";

// Get all live fixtures
async function getLiveFixtures() {
    const url = "https://api.sportmonks.com/v3/football/fixtures";
    const params = new URLSearchParams({
        api_token: API_TOKEN,
        include: "state,participants",
        filters: "fixtureStates:2,10,7" // LIVE, ET, PEN_LIVE
    });

    try {
        const response = await fetch(`${url}?${params}`);
        const data = await response.json();
        const fixtures = data.data || [];
        
        console.log(`🔴 ${fixtures.length} live matches found:\n`);
        
        fixtures.forEach(fixture => {
            const state = fixture.state || {};
            console.log(`${fixture.name}`);
            console.log(`  Status: ${state.name} (${state.state})`);
            console.log();
        });
        
        return fixtures;
    } catch (error) {
        console.error("Error fetching live fixtures:", error);
        return [];
    }
}

// Check specific fixture state
async function checkFixtureState(fixtureId) {
    const url = `https://api.sportmonks.com/v3/football/fixtures/${fixtureId}`;
    const params = new URLSearchParams({
        api_token: API_TOKEN,
        include: "state"
    });

    try {
        const response = await fetch(`${url}?${params}`);
        const data = await response.json();
        const fixture = data.data;
        const state = fixture.state || {};
        
        return {
            fixture_id: fixtureId,
            fixture_name: fixture.name,
            state_id: state.id,
            state_code: state.state,
            state_name: state.name,
            is_live: [2, 6, 7, 22].includes(state.id),
            is_finished: [5, 7, 8].includes(state.id),
            has_problem: [12, 15, 16, 17, 18].includes(state.id)
        };
    } catch (error) {
        console.error("Error checking fixture state:", error);
        return null;
    }
}

// Display state badge
function createStateBadge(state) {
    const badge = document.createElement('span');
    badge.className = `state-badge state-${state.state.toLowerCase()}`;
    
    // Color coding
    const colors = {
        'LIVE': '#ff0000',
        'FT': '#28a745',
        'HT': '#ffc107',
        'POSTP': '#6c757d',
        'CANCL': '#dc3545'
    };
    
    badge.style.backgroundColor = colors[state.state] || '#6c757d';
    badge.style.color = 'white';
    badge.style.padding = '4px 8px';
    badge.style.borderRadius = '4px';
    badge.style.fontWeight = 'bold';
    badge.textContent = state.short_name;
    
    return badge;
}

// Get fixtures with problems
async function getProblemFixtures() {
    const url = "https://api.sportmonks.com/v3/football/fixtures";
    const params = new URLSearchParams({
        api_token: API_TOKEN,
        include: "state,participants",
        filters: "fixtureStates:12;13;14;15;16;17" // Problem states
    });

    try {
        const response = await fetch(`${url}?${params}`);
        const data = await response.json();
        const fixtures = data.data || [];
        
        // Group by state
        const byState = {};
        fixtures.forEach(fixture => {
            const stateName = fixture.state.name;
            if (!byState[stateName]) {
                byState[stateName] = [];
            }
            byState[stateName].push(fixture);
        });
        
        console.log("⚠️  Problem Fixtures:\n");
        Object.entries(byState).forEach(([stateName, matches]) => {
            console.log(`${stateName}: ${matches.length} matches`);
            matches.forEach(match => {
                console.log(`  - ${match.name}`);
            });
            console.log();
        });
        
        return byState;
    } catch (error) {
        console.error("Error fetching problem fixtures:", error);
        return {};
    }
}

// Categorise fixtures
function categoriseFixturesByState(fixtures) {
    const categories = {
        upcoming: [],
        live: [],
        finished: [],
        postponed: [],
        cancelled: [],
        other: []
    };
    
    fixtures.forEach(fixture => {
        const stateId = fixture.state.id;
        
        if (stateId === 1) {
            categories.upcoming.push(fixture);
        } else if ([2, 6, 7, 22].includes(stateId)) {
            categories.live.push(fixture);
        } else if ([5, 7, 8].includes(stateId)) {
            categories.finished.push(fixture);
        } else if (stateId === 10) {
            categories.postponed.push(fixture);
        } else if (stateId === 12) {
            categories.cancelled.push(fixture);
        } else {
            categories.other.push(fixture);
        }
    });
    
    return categories;
}

// Build fixtures list with state indicators
function buildFixturesList(fixtures) {
    const container = document.createElement('div');
    container.className = 'fixtures-list';
    
    const categories = categoriseFixturesByState(fixtures);
    
    // Display by category
    Object.entries(categories).forEach(([category, matches]) => {
        if (matches.length > 0) {
            const section = document.createElement('div');
            section.className = 'fixture-category';
            section.innerHTML = `<h3>${category.toUpperCase()} (${matches.length})</h3>`;
            
            matches.forEach(fixture => {
                const item = document.createElement('div');
                item.className = 'fixture-item';
                item.appendChild(createStateBadge(fixture.state));
                item.innerHTML += ` ${fixture.name}`;
                section.appendChild(item);
            });
            
            container.appendChild(section);
        }
    });
    
    document.body.appendChild(container);
}

// Run examples
getLiveFixtures();
checkFixtureState(18535517).then(state => console.log("Fixture state:", state));
getProblemFixtures();
```

### Common use cases

#### 1. Live match filtering

Show only matches that are currently live:

```python
def is_match_live(state_id):
    return state_id in [2, 6, 7, 22]  # INPLAY_1ST_HALF, INPLAY_2ND_HALF, INPLAY_ET, PEN_LIVE
```

#### 2. State-based notifications

Send notifications when states change:

```python
def should_notify(old_state, new_state):
    notifications = {
        (1, 2): "Match started!",
        (2, 3): "Half time",
        (3, 2): "Second half started",
        (2, 5): "Full time",
        (5, 10): "Extra time started!",
        (1, 13): "Match postponed",
        (1, 12): "Match cancelled"
    }
    return notifications.get((old_state, new_state))
```

#### 3. Data refresh strategy

Determine when to refresh data based on state:

```python
def get_refresh_interval(state_id):
    """Get appropriate refresh interval in seconds"""
    if state_id in [2, 6, 7, 22]:  # Live states
        return 30  # Refresh every 30 seconds
    elif state_id in [1]:  # Not started
        return 300  # Refresh every 5 minutes
    elif state_id in [5, 7, 8]:  # Finished
        return None  # No need to refresh
    else:
        return 600  # Check every 10 minutes
```

### Best practices

1. **Always include state for fixtures**: State is essential for proper match display and handling.
2. **Use state IDs, not names**: State IDs are more reliable than text names which may change.
3. **Handle problem states gracefully**: Show appropriate messages for postponed, cancelled, or interrupted matches.
4. **Filter efficiently**: Use state filters in API requests rather than filtering after fetching.
5. **Monitor state transitions**: For live applications, track when states change to trigger updates.
6. **Cache finished matches**: Once a match reaches FT/AET/FT\_PEN, its state won't change.
7. **Consider ALL live states**: Don't just check for state ID 2 (INPLAY\_1ST\_HALF). Include extra time (6) and penalties (9).

### Summary

The `state` include provides essential match status information with 21 different states covering all possible fixture scenarios from scheduled to finished, including problem states like postponed and cancelled. Understanding state transitions and using state-based filtering enables robust match tracking, proper data refresh strategies, and excellent user experiences. Always check state before displaying match data or determining refresh intervals.

### See also

#### Prerequisites

* [Fixtures Tutorial](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/livescores-and-fixtures/fixtures) - Understanding fixtures
* [Includes Tutorial](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/includes) - Using the state include

#### Using states

* [Livescores](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/livescores-and-fixtures/livescores) - Filter by live states
* [Filter and Select](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/filter-and-select-fields) - Filter by state IDs
* [Odds](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/odds-and-predictions) - State affects odds availability

#### Related concepts

* [Events](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/includes/events) - Events depend on match state
* [Periods](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/includes/periods) - Match period tracking
* [Scores](https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/includes/scores) - Scores update with state changes

#### Building applications

* [Best Practices](https://docs.sportmonks.com/v3/welcome/best-practices) - Handling different states
* [Rate Limiting](https://docs.sportmonks.com/v3/api/rate-limit) - Polling based on state

#### Reference

* [States Definition](https://docs.sportmonks.com/v3/definitions/states) - Complete list of state IDs
