# Periods

### What does the include do?

The `periods` include allows you to retrieve detailed information about different periods within a football match, including regular time, extra time, and penalties. This include provides comprehensive timing data including the current minute, seconds elapsed, period start/end times, and whether the period is currently active (ticking).

### Why use periods?

The periods include is essential for:

* **Live match tracking**: Display accurate match time with minute and second precision
* **Match state management**: Know which period is currently being played
* **Time-based analysis**: Analyse events by period (first half, second half, extra time)
* **Broadcast applications**: Show precise match timing for live streams
* **Statistical analysis**: Break down team performance by match period
* **Injury time tracking**: Monitor added time in each period

### Requesting periods

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

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

**Example:** Get periods for Real Madrid vs FC Barcelona (fixture ID: 19439347)

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

### Response structure

When you include `periods` in your request, you'll receive an array of period objects for each match period:

```json
{
  "data": {
    "id": 19439347,
    "sport_id": 1,
    "league_id": 564,
    "season_id": 25659,
    "stage_id": 77476930,
    "group_id": null,
    "aggregate_id": null,
    "round_id": 373219,
    "state_id": 5,
    "venue_id": 2020,
    "name": "Real Madrid vs FC Barcelona",
    "starting_at": "2025-10-26 15:15:00",
    "result_info": "Real Madrid won after full-time.",
    "leg": "1\/1",
    "details": null,
    "length": 90,
    "placeholder": false,
    "has_odds": true,
    "has_premium_odds": true,
    "starting_at_timestamp": 1761491700,
    "periods": [
      {
        "id": 6330171,
        "fixture_id": 19439347,
        "type_id": 1,
        "started": 1761491882,
        "ended": 1761494952,
        "counts_from": 0,
        "ticking": false,
        "sort_order": 1,
        "description": "1st-half",
        "time_added": 6,
        "period_length": 45,
        "minutes": 51,
        "seconds": 10,
        "has_timer": false
      },
      {
        "id": 6330453,
        "fixture_id": 19439347,
        "type_id": 2,
        "started": 1761495960,
        "ended": 1761499312,
        "counts_from": 45,
        "ticking": false,
        "sort_order": 2,
        "description": "2nd-half",
        "time_added": 10,
        "period_length": 45,
        "minutes": 100,
        "seconds": 52,
        "has_timer": false
      }
    ]
  }
}
```

### Field descriptions

| Field           | Type         | Description                                                                           |
| --------------- | ------------ | ------------------------------------------------------------------------------------- |
| `id`            | integer      | Unique identifier for this period                                                     |
| `fixture_id`    | integer      | ID of the fixture this period belongs to                                              |
| `type_id`       | integer      | Type identifier for the period (see Period Types below)                               |
| `started`       | integer      | UNIX timestamp of when the period started                                             |
| `ended`         | integer/null | UNIX timestamp of when the period ended (null if ongoing)                             |
| `counts_from`   | integer      | Minute from which this period starts counting (e.g., 0 for 1st half, 45 for 2nd half) |
| `ticking`       | boolean      | Whether the period is currently active/being played                                   |
| `sort_order`    | integer      | Sorting order of the period (1 = first, 2 = second, etc.)                             |
| `description`   | string       | Human-readable description of the period                                              |
| `time_added`    | integer/null | Additional injury/stoppage time added to the period (in minutes)                      |
| `period_length` | integer      | Standard length of the period in minutes (usually 45 for regular time)                |
| `minutes`       | integer      | Current minute within the match (cumulative)                                          |
| `seconds`       | integer      | Seconds after the current minute (0-59)                                               |
| `has_timer`     | boolean      | Whether detailed timer information (minutes/seconds) is available                     |

### Period types

The `type_id` field indicates what type of period this represents:

| Type ID | Description              | counts\_from | period\_length |
| ------- | ------------------------ | ------------ | -------------- |
| 1       | First Half (1ST\_HALF)   | 0            | 45             |
| 2       | Second Half (2ND\_HALF)  | 45           | 45             |
| 3       | Extra Time - First Half  | 90           | 15             |
| 4       | Extra Time - Second Half | 105          | 15             |
| 5       | Penalty Shootout         | 120          | Variable       |
| 14      | Awaiting Extra Time      | 90           | 0              |
| 16      | Extra Time Halftime      | 105          | 0              |
| 18      | Awaiting Penalties       | 120          | 0              |

### Understanding period timing

#### counts\_from

This field indicates the starting minute for the period:

* 1st half: `counts_from = 0` (minutes 0-45)
* 2nd half: `counts_from = 45` (minutes 45-90)
* Extra time 1st: `counts_from = 90` (minutes 90-105)
* Extra time 2nd: `counts_from = 105` (minutes 105-120)

#### minutes and seconds

These fields provide the current match time:

* `minutes`: Cumulative minute count from match start (e.g., 47 means 47th minute)
* `seconds`: Seconds within current minute (0-59)

**Example:** `minutes = 47, seconds = 23` means the match is at 47:23

#### ticking

* `true`: This period is currently active (match is live in this period)
* `false`: This period has ended

#### time\_added (Injury time)

The additional minutes added to the period for stoppages:

* Usually 1-5 minutes in regular time
* Shows as "45+2" in match displays when 2 minutes added to 1st half

### Current period include

In addition to the `periods` include, you can use the `currentPeriod` include for a more convenient way to get only the active period:

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

This returns only the period that is currently ticking (or null if match hasn't started or has ended).

### Nested includes

The periods include supports the following nested includes:

#### periods.type

Get detailed information about the period type:

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

#### periods.events

Get all events that occurred during this specific period:

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

#### periods.statistics

Get statistics specific to this period:

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

### Code examples

#### Python example

```python
import requests
from datetime import datetime

# API configuration
API_TOKEN = "YOUR_TOKEN"
FIXTURE_ID = 19439347

# Request periods
url = f"https://api.sportmonks.com/v3/football/fixtures/{FIXTURE_ID}"
params = {
    "api_token": API_TOKEN,
    "include": "periods"
}

response = requests.get(url, params=params)
data = response.json()

# Extract periods
periods = data['data'].get('periods', [])

# Display all periods
for period in periods:
    print(f"\n{period['description']}:")
    print(f"  Started: {datetime.fromtimestamp(period['started'])}")
    if period['ended']:
        print(f"  Ended: {datetime.fromtimestamp(period['ended'])}")
        duration = period['ended'] - period['started']
        print(f"  Duration: {duration // 60} minutes")
    print(f"  Ticking: {period['ticking']}")
    if period['time_added']:
        print(f"  Injury time: +{period['time_added']} minutes")

# Find current/active period
def get_current_period(periods):
    """Get the currently active period"""
    return next((p for p in periods if p['ticking']), None)

current = get_current_period(periods)
if current:
    print(f"\n🔴 LIVE: Currently in {current['description']}")
    print(f"⏱️  Match time: {current['minutes']}:{current['seconds']:02d}")
else:
    print("\n✅ Match ended or not started")

# Calculate total match time
def calculate_total_time(periods):
    """Calculate total playing time including injury time"""
    total_minutes = 0
    for period in periods:
        if period['ended']:
            duration_seconds = period['ended'] - period['started']
            total_minutes += duration_seconds // 60
    return total_minutes

total_time = calculate_total_time(periods)
print(f"\n⏱️  Total playing time: {total_time} minutes")

# Track injury time patterns
def analyze_injury_time(periods):
    """Analyse injury time added in each period"""
    injury_time = {}
    for period in periods:
        if period['time_added']:
            injury_time[period['description']] = period['time_added']
    return injury_time

injury_analysis = analyze_injury_time(periods)
print(f"\n🚑 Injury time analysis:")
for period_name, minutes in injury_analysis.items():
    print(f"  {period_name}: +{minutes} minutes")

# Check if match went to extra time
def has_extra_time(periods):
    """Check if match included extra time"""
    return any(p['type_id'] in [3, 4] for p in periods)

def has_penalties(periods):
    """Check if match went to penalties"""
    return any(p['type_id'] == 5 for p in periods)

if has_extra_time(periods):
    print("\n⏱️  Match included extra time")
if has_penalties(periods):
    print("🎯 Match decided by penalties")
```

#### JavaScript example

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

// Request periods
async function getFixturePeriods() {
    const url = `https://api.sportmonks.com/v3/football/fixtures/${FIXTURE_ID}`;
    const params = new URLSearchParams({
        api_token: API_TOKEN,
        include: "periods"
    });

    try {
        const response = await fetch(`${url}?${params}`);
        const data = await response.json();
        
        const periods = data.data.periods || [];
        
        // Display all periods
        periods.forEach(period => {
            console.log(`\n${period.description}:`);
            console.log(`  Started: ${new Date(period.started * 1000).toLocaleString()}`);
            if (period.ended) {
                console.log(`  Ended: ${new Date(period.ended * 1000).toLocaleString()}`);
                const duration = Math.floor((period.ended - period.started) / 60);
                console.log(`  Duration: ${duration} minutes`);
            }
            console.log(`  Ticking: ${period.ticking}`);
            if (period.time_added) {
                console.log(`  Injury time: +${period.time_added} minutes`);
            }
        });
        
        // Find current period
        const currentPeriod = getCurrentPeriod(periods);
        if (currentPeriod) {
            console.log(`\n🔴 LIVE: Currently in ${currentPeriod.description}`);
            console.log(`⏱️  Match time: ${currentPeriod.minutes}:${String(currentPeriod.seconds).padStart(2, '0')}`);
            
            // Display live timer
            displayLiveTimer(currentPeriod);
        } else {
            console.log("\n✅ Match ended or not started");
        }
        
        // Calculate total time
        const totalTime = calculateTotalTime(periods);
        console.log(`\n⏱️  Total playing time: ${totalTime} minutes`);
        
        // Check match extras
        if (hasExtraTime(periods)) {
            console.log("⏱️  Match included extra time");
        }
        if (hasPenalties(periods)) {
            console.log("🎯 Match decided by penalties");
        }
        
    } catch (error) {
        console.error("Error fetching periods:", error);
    }
}

function getCurrentPeriod(periods) {
    return periods.find(p => p.ticking === true);
}

function calculateTotalTime(periods) {
    return periods.reduce((total, period) => {
        if (period.ended) {
            const durationMinutes = Math.floor((period.ended - period.started) / 60);
            return total + durationMinutes;
        }
        return total;
    }, 0);
}

function hasExtraTime(periods) {
    return periods.some(p => [3, 4].includes(p.type_id));
}

function hasPenalties(periods) {
    return periods.some(p => p.type_id === 5);
}

// Display live match timer
function displayLiveTimer(period) {
    const timerDiv = document.createElement('div');
    timerDiv.className = 'live-timer';
    timerDiv.innerHTML = `
        <div class="timer-container">
            <div class="period-name">${period.description}</div>
            <div class="match-time">${period.minutes}:${String(period.seconds).padStart(2, '0')}</div>
            ${period.time_added ? `<div class="injury-time">+${period.time_added} min</div>` : ''}
            <div class="live-indicator">🔴 LIVE</div>
        </div>
    `;
    document.body.appendChild(timerDiv);
}

// Build period timeline visualization
function buildPeriodTimeline(periods) {
    const timeline = document.createElement('div');
    timeline.className = 'period-timeline';
    
    periods.forEach((period, index) => {
        const periodBlock = document.createElement('div');
        periodBlock.className = `period-block ${period.ticking ? 'active' : 'completed'}`;
        periodBlock.innerHTML = `
            <div class="period-label">${period.description}</div>
            <div class="period-time">${period.counts_from}-${period.counts_from + period.period_length}'</div>
            ${period.time_added ? `<div class="added-time">+${period.time_added}'</div>` : ''}
        `;
        timeline.appendChild(periodBlock);
    });
    
    document.body.appendChild(timeline);
}

// Format match time display
function formatMatchTime(period) {
    const baseMinute = period.minutes;
    const seconds = period.seconds;
    
    // Check if in injury time
    const regularTime = period.counts_from + period.period_length;
    if (baseMinute >= regularTime && period.time_added) {
        const injuryMinute = baseMinute - regularTime;
        return `${regularTime}+${injuryMinute}:${String(seconds).padStart(2, '0')}`;
    }
    
    return `${baseMinute}:${String(seconds).padStart(2, '0')}`;
}

// Run the example
getFixturePeriods();
```

### Common use cases

#### 1. Live match timer display

Display accurate live match time with injury time:

```python
def format_match_time(period):
    """Format match time for display"""
    minutes = period['minutes']
    seconds = period['seconds']
    regular_time = period['counts_from'] + period['period_length']
    
    # Check if in injury time
    if minutes >= regular_time and period['time_added']:
        injury_minute = minutes - regular_time
        return f"{regular_time}+{injury_minute}:{seconds:02d}"
    
    return f"{minutes}:{seconds:02d}"
```

#### 2. Period-based statistics

Analyze team performance by period:

```python
def analyze_by_period(fixtures_with_periods_and_events):
    """Analyse goals scored by period"""
    period_stats = {
        '1ST_HALF': {'goals': 0},
        '2ND_HALF': {'goals': 0},
        'EXTRA_TIME': {'goals': 0}
    }
    
    for fixture in fixtures_with_periods_and_events:
        events = fixture.get('events', [])
        for event in events:
            if event['type_id'] == 14:  # Goal
                period_id = event['period_id']
                period = next((p for p in fixture['periods'] if p['id'] == period_id), None)
                if period:
                    period_stats[period['description']]['goals'] += 1
    
    return period_stats
```

#### 3. Match state detection

Determine current match state:

```python
def get_match_state(periods):
    """Determine current match state"""
    current = next((p for p in periods if p['ticking']), None)
    
    if not current:
        if any(p['ended'] for p in periods):
            return "FINISHED"
        return "NOT_STARTED"
    
    if current['type_id'] == 1:
        return "FIRST_HALF"
    elif current['type_id'] == 2:
        return "SECOND_HALF"
    elif current['type_id'] in [3, 4]:
        return "EXTRA_TIME"
    elif current['type_id'] == 5:
        return "PENALTIES"
    
    return "UNKNOWN"
```

### Best practices

1. **Use has\_timer to check data availability**: Not all matches have detailed timer information. Check `has_timer` before displaying seconds.
2. **Handle null ended timestamps**: For live matches, `ended` will be null for the current period.
3. **Use currentPeriod for live updates**: If you only need the active period, use `include=currentPeriod` instead of fetching all periods.
4. **Calculate injury time correctly**: Display as "45+2" not "47" when showing injury time to users.
5. **Check ticking for live status**: The `ticking` field is the most reliable way to determine if a period is currently active.
6. **Sort by sort\_order**: Always use `sort_order` to display periods in chronological order.
7. **Cache completed periods**: Period data doesn't change after a period ends. Cache historical periods to reduce API calls.

### Related includes

* [**Events**](https://docs.sportmonks.com/football/tutorials-and-guides/tutorials/includes/events) - Cross-reference events with periods to show when they occurred
* [**Statistics**](https://docs.sportmonks.com/football/definitions/types/statistics) - Get period-specific statistics
* [**States**](https://docs.sportmonks.com/football/tutorials-and-guides/tutorials/includes/states) - Understand match state transitions
* [**Scores**](https://docs.sportmonks.com/football/tutorials-and-guides/tutorials/includes/scores) - See scores by period

### Summary

The `periods` include provides comprehensive timing information for all match periods including first half, second half, extra time, and penalties. With fields for current minutes/seconds, injury time, and active status, it enables accurate live match timers, period-based analysis, and match state management. Use `currentPeriod` for live matches when you only need the active period data.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.sportmonks.com/v3/tutorials-and-guides/tutorials/includes/periods.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
