From-id Pagination
From-id pagination uses record IDs to navigate backwards through datasets in chronological order. This pagination method only allows you to move backwards in time, making it ideal for collecting historical data.
How pagination works
- Initial request: Make a request without the
from_idparameter to get the most recent records. - Backward navigation: Use the
transaction_idof the last record asfrom_idin your next request. The response will always include thatfrom_idrecord. - Stop condition: If the response contains more than just the
from_idrecord, continue. If it only contains that one record, stop.
Request parameters
from_id: The ID of a record. The response will contain this record and records that are older.
When you omit the from_id parameter, you get the most recent records.
Data ordering
Records returned by these listing routes are ordered by time, with the most recent records first.
Using from_id returns that record and records that are older.
Initial Data Collection
Start by making your first request without the from_id parameter:
You'll receive a response like this:
[
{"id": 100, "name": "A", "created": "2024-01-15T09:15:00Z"},
{"id": 99, "name": "B", "created": "2024-01-15T08:30:00Z"},
{"id": 98, "name": "C", "created": "2024-01-15T07:45:00Z"}
]
What to do:
- Store all the records you retrieved.
- If you find a record you already know, stop.
- If you are at the end of the record set, use the last
transaction_idasfrom_idin your next request. - The response will always contain that
from_idrecord (98). If it only contains that one record, stop. Otherwise continue at step 1.
Example
import requests
import time
def fetch_records(url, headers, from_id=None):
params = {}
if from_id is not None:
params['from_id'] = from_id
response = requests.get(url, params=params, headers=headers)
response.raise_for_status()
return response.json()
def collect_current_data(url, headers):
all_records = []
from_id = None
while True:
print(f"Fetching records from_id={from_id}...")
records = fetch_records(url, headers, from_id=from_id)
# If the response is empty, there are no records in the dataset.
if not records:
print(" Empty dataset")
break
# The response always contains the from_id record.
# If it only contains that one record, we've reached the end.
if from_id is not None and len(records) == 1:
print(" No more records")
break
# Store all records.
all_records.extend(records)
print(f" Found {len(records)} records; total {len(all_records)} records")
# Use last record's ID for next request (go backwards in time).
from_id = records[-1]['transaction_id']
time.sleep(0.1) # Throttle requests to avoid rate limiting.
print(f"Total: {len(all_records)} records")
return all_records
if __name__ == "__main__":
url = "https://esi.evetech.net/..." # ... (replace with actual route)
headers = {
"User-Agent": "ESI-Example/1.0",
"X-Compatibility-Date": "2025-09-30",
"Authorization": "Bearer <your-token>",
}
all_data = collect_current_data(url, headers)
# ... (do something with all_data)