TyreReviews API
Access comprehensive tyre data, test results, and reviews programmatically
Rich Data
Access to 50,000+ tyres with scores, reviews, and test results
Fast & Reliable
Average response time under 100ms with 99.9% uptime
Secure
SSL encrypted, API key authentication, and rate limiting
Getting Started
Follow these simple steps to start using the TyreReviews API:
1. Get Your API Key
Contact our sales team to obtain your API credentials. You'll receive an API key, rate limit based on your plan, and access to documentation.
2. Make Your First Request
curl -X GET "https://api.tyrereviews.com/v1/tyres/search?pattern=michelin" \
-H "X-API-Key: your_api_key_here"
Base URL
All API requests should be made to: https://api.tyrereviews.com/v1/
Authentication
The TyreReviews API uses API key authentication. Include your API key in the request header:
X-API-Key: your_api_key_here
Security Best Practices
Do
- Keep your API key secure and private
- Use environment variables to store keys
- Rotate keys regularly
- Use HTTPS for all requests
Don't
- Share your API key publicly
- Commit keys to version control
- Include keys in client-side code
- Use keys in URLs
Available Endpoints
Tyre Endpoints
/tyres/search
Search by pattern, brand, season, score
/tyres/{id}
Full details with score breakdown & mileage
/tyres/{id}/score
Overall score, confidence tier, source
/tyres/{id}/score-explanation
Category breakdowns, methodology, narrative
/tyres/{id}/tests
Professional test results with per-metric data
/tyres/{id}/reviews
User reviews with ratings and statistics
/tyres/{id}/images
Product images and YouTube videos
/tyres/{id}/alternatives
Alternative search patterns
Test Endpoints
/tests
List published magazine tests
/tests/{id}
Test details with tyre list
/tests/{id}/results
Full results with per-tyre metrics
Brand Endpoints
/brands
All brands with tyre counts
/brands/{id}
Brand details with stats
/brands/{id}/tyres
Paginated brand tyre catalogue
Search Tyres
The search endpoint is the most powerful way to find tyres in our database.
Parameters
| Parameter | Type | Description |
|---|---|---|
pattern | string | Search pattern (e.g., "michelin-pilot-sport") |
brand | string | Filter by brand name |
season | integer | Season ID (1=summer, 2=winter, 3=all-season) |
vehicle | integer | Vehicle type ID (1=Car, 2=SUV, 3=Van) |
type | integer | Tyre type ID |
min_score | float | Minimum score (0–10) |
sort | string | score:desc (default), score:asc, name:asc, name:desc, views:desc, reviews:desc, date:desc |
fields | string | Comma-separated field names (e.g., id,brand,model,score) |
limit | integer | Results per page (max 100) |
offset | integer | Pagination offset |
Example Request
GET /v1/tyres/search?pattern=michelin&season=1&min_score=7&limit=10
X-API-Key: your_api_key_here
Example Response
{
"success": true,
"data": [
{
"id": 6,
"tyre_id": "PS2",
"brand_id": 3,
"brand": "Michelin",
"model": "Pilot Sport PS2",
"full_name": "Michelin Pilot Sport PS2",
"score": 7.8,
"score_source": "combined",
"review_count": 250,
"avg_rating": 82.5,
"season": "Summer",
"vehicle_type": "Car",
"tyre_type": "Performance",
"image_url": "https://www.tyrereviews.com/images/tyres/Michelin-Pilot-Sport-PS2.jpg",
"url": "https://www.tyrereviews.com/Tyre/Michelin/Pilot-Sport-PS2.htm"
}
],
"meta": { "total": 15, "count": 1, "limit": 10, "offset": 0 }
}
Pro Tip
Use either the numeric ID or a pattern string to get full tyre details:
GET /v1/tyres/6 (numeric ID) or GET /v1/tyres/pilot-sport-4 (pattern string)
Tyre Details
Get comprehensive information about a specific tyre, including score breakdowns, confidence, and expected mileage.
Request
GET /v1/tyres/3672
X-API-Key: your_api_key_here
Flexible Identifiers
The {id} parameter accepts both numeric IDs and pattern strings.
Numeric: /tyres/6 · Pattern: /tyres/pilot-sport-4 · URL encoded: /tyres/pilot%20sport%204
Patterns are matched against the tyre_alternative table and are case-insensitive.
Response Fields
| Field | Type | Description |
|---|---|---|
id | integer | Unique tyre identifier |
brand_name | string | Manufacturer name |
title | string | Tyre model name |
tyre_reviews_score | float|null | Overall score (0–10). Null if not calculated. |
score_source | string|null | combined, tests_only, or reviews_only |
score_confidence | integer|null | Confidence percentage (0–100) |
score_confidence_tier | string|null | High (≥80%), Medium (≥50%), or Limited |
season_name | string | Season type (Summer, Winter, All Season, All Weather) |
vehicle_name | string | Target vehicle type |
totalreviews | integer | Number of user reviews |
totalrating | float | Average user rating (0–100) |
image_url | string | Full URL to tyre product image |
brand_image_url | string|null | Full URL to brand logo |
url | string | Link to the tyre page on tyrereviews.com |
score_details | object|null | Pre-computed category breakdown scores. See Tyre Scores. |
expected_mileage | object|null | Combined mileage estimate from test data and user reviews. |
Expected Mileage
When available, the expected_mileage object combines professional test mileage data with user-reported End-of-Life mileage (test data weighted 70%, user reviews 30%).
{
"expected_mileage": {
"has_data": true,
"combined_mileage_miles": 32500,
"combined_mileage_km": 52300,
"confidence": "high",
"has_discrepancy": false,
"discrepancy_percent": 12,
"test_data": {
"confidence": "high",
"avg_mileage_miles": 35000,
"avg_mileage_km": 56327,
"source_count": 2,
"source_type": "test"
},
"user_data": {
"confidence": "medium",
"avg_mileage_miles": 28000,
"avg_mileage_km": 45062,
"source_count": 12,
"source_type": "user_reviews"
}
}
}
| Field | Type | Description |
|---|---|---|
combined_mileage_miles | int|null | Best estimate in miles (test 70% + reviews 30%) |
combined_mileage_km | int|null | Best estimate in kilometres |
confidence | string | high (both sources), medium (≥8 reviews), low (limited data) |
has_discrepancy | bool | True when test and review mileage differ by more than 25% |
test_data | object|null | Mileage from professional tests (breakdown_id 7) |
user_data | object|null | Mileage from End-of-Life user reviews (min 3 reviews, 5k–100k miles) |
Returns null if no mileage data is available from either source.
Tyre Scores
The Tyre Reviews Score is a composite 0–10 rating combining professional test data, user reviews, and consistency analysis using Bayesian statistical smoothing.
Score Summary: GET /tyres/{id}/score
GET /v1/tyres/3672/score
X-API-Key: your_api_key_here
{
"success": true,
"data": {
"tyre_id": 3672,
"overall_score": 7.2,
"score_source": "combined",
"confidence": 100,
"confidence_tier": "High",
"explanation_url": "/v1/tyres/3672/score-explanation"
}
}
Category Breakdowns: score_details
When you fetch a tyre via GET /tyres/{id}, the response includes a score_details object:
{
"score_details": {
"categories": [
{ "name": "Snow", "display_score": 91.2, "raw_score": 98.0, "weight": 1.38, "test_count": 11 },
{ "name": "Wet", "display_score": 59.5, "raw_score": 91.9, "weight": 2.00, "test_count": 11 },
{ "name": "Dry", "display_score": 41.7, "raw_score": 89.4, "weight": 1.50, "test_count": 7 }
],
"derived_categories": [
{ "name": "Traction", "display_score": 82.8, "raw_score": 96.2, "weight": 0, "test_count": 4 },
{ "name": "Braking", "display_score": 66.6, "raw_score": 90.0, "weight": 0, "test_count": 11 }
]
}
}
| Field | Type | Description |
|---|---|---|
display_score | float | Min-max scaled score (0–100). Use for progress bars. |
raw_score | float | Original weighted average before scaling (0–100). |
weight | float | Category weight in overall score. Always 0 for derived. |
test_count | int | Number of test metrics contributing to this category. |
Full Score Explanation: GET /tyres/{id}/score-explanation
Returns a comprehensive explanation including category breakdowns, methodology, source tests, and a narrative summary. Cached for 1 hour.
Availability
Returns 404 if the tyre has no score. Not all tyres have scores — approximately 1,946 tyres currently have computed scores.
Pattern Matching
All tyre endpoints accept flexible identifiers — you can use either numeric IDs or string patterns.
Pattern Matching Rules
The API tries to match your pattern in this order:
- Exact match on
tyre_alternative.title - Exact match on
tyre_alternative.tyre_id - Match with spaces converted to hyphens (case-insensitive)
- Match with all spaces removed (case-insensitive)
Examples
| You Send | Matches | Result |
|---|---|---|
6 | Numeric ID | Tyre ID: 6 |
pilot sport 4 | PILOT SPORT 4 | Tyre ID: 1927 |
pilot-sport-4 | PILOT SPORT 4 | Tyre ID: 1927 |
Important
- Patterns are case-insensitive
- Spaces can be hyphens, plus signs, or URL encoded
- Numeric IDs are faster (no database lookup required)
Test Endpoints
Access magazine tyre test data including test metadata, tyre positions, and detailed performance metrics.
Test Details: GET /tests/{id}
Returns full details for a specific published tyre test, including all tyres tested with their positions.
GET /v1/tests/450
X-API-Key: your_api_key_here
Response Fields
| Field | Type | Description |
|---|---|---|
id | integer | Test ID |
title | string | Full test title |
test_year | integer | Year the test was conducted |
tyre_size | string | Tyre size tested (e.g., "205/55 R16") |
season | string | Season type |
vehicle_type | string | Vehicle type |
publication_id | string|null | Publishing source |
tyres_tested | integer | Total tyres in the test |
article_url | string | Link to article on tyrereviews.com |
tyres[] | array | List of tyres with position, score, award, image_url |
Example Response
{
"success": true,
"data": {
"id": 450,
"title": "Summer Tyre Test 2024",
"test_year": 2024,
"tyre_size": "205/55 R16",
"season": "Summer",
"vehicle_type": "Car",
"tyres_tested": 10,
"article_url": "https://www.tyrereviews.com/Article/summer-tyre-test-2024",
"tyres": [
{
"tyre_id": 1927,
"position": 1,
"position_percentile": 100.0,
"normalized_score": 95.2,
"award": "Test Winner",
"brand": "Michelin",
"model": "Pilot Sport 5",
"score": 8.1,
"image_url": "https://www.tyrereviews.com/images/tyres/Michelin-Pilot-Sport-5.jpg"
}
]
}
}
Test Results: GET /tests/{id}/results
Returns the full results table with per-tyre performance metrics grouped by category.
| Parameter | Type | Description |
|---|---|---|
limit | integer | Results per page (default 50, max 100) |
offset | integer | Pagination offset |
Metrics Structure
The metrics object groups measurements by category. direction indicates whether lower or higher values are better.
{
"metrics": {
"Wet": [
{ "metric": "Wet Braking", "value": "34.2", "unit": "m", "direction": "lower" },
{ "metric": "Wet Handling", "value": "62.3", "unit": "s", "direction": "lower" }
],
"Dry": [
{ "metric": "Dry Braking", "value": "33.8", "unit": "m", "direction": "lower" }
]
}
}
Brand Endpoints
Access tyre brand information and browse brand catalogues.
Brand Details: GET /brands/{id}
| Field | Type | Description |
|---|---|---|
id | integer | Brand ID |
name | string | Brand name |
brand_tier | string|null | Premium, Mid-Range, Economy, or Budget |
tyre_count | integer | Total active tyres |
average_score | float|null | Average score across scored tyres |
scored_tyres | integer | Number of tyres with a computed score |
image_url | string|null | Brand logo URL |
Brand Tyres: GET /brands/{id}/tyres
Paginated list of all tyres from a brand with scores, confidence, and classification.
| Parameter | Type | Description |
|---|---|---|
limit | integer | Results per page (default 20, max 100) |
offset | integer | Pagination offset |
sort | string | score:desc (default), score:asc, name:asc, name:desc, reviews:desc |
Example Response
{
"success": true,
"data": [
{
"id": 1927,
"tyre_id": "PS5",
"model": "Pilot Sport 5",
"score": 8.1,
"score_source": "combined",
"score_confidence": 95,
"score_confidence_tier": "High",
"review_count": 120,
"avg_rating": 88.5,
"season": "Summer",
"vehicle_type": "Car",
"tyre_type": "Performance",
"image_url": "https://www.tyrereviews.com/images/tyres/Michelin-Pilot-Sport-5.jpg",
"url": "https://www.tyrereviews.com/Tyre/Michelin/Pilot-Sport-5.htm"
}
],
"meta": { "total": 85, "count": 10, "limit": 10, "offset": 0 }
}
Code Examples
# Search for tyres
curl -X GET "https://api.tyrereviews.com/v1/tyres/search?pattern=continental&season=2" \
-H "X-API-Key: your_api_key_here"
# Get tyre details (includes score_details & expected_mileage)
curl -X GET "https://api.tyrereviews.com/v1/tyres/3672" \
-H "X-API-Key: your_api_key_here"
# Get tyre by pattern string
curl -X GET "https://api.tyrereviews.com/v1/tyres/pilot-sport-4" \
-H "X-API-Key: your_api_key_here"
# Get score summary
curl -X GET "https://api.tyrereviews.com/v1/tyres/3672/score" \
-H "X-API-Key: your_api_key_here"
# Get full score explanation
curl -X GET "https://api.tyrereviews.com/v1/tyres/3672/score-explanation" \
-H "X-API-Key: your_api_key_here"
# Get test details
curl -X GET "https://api.tyrereviews.com/v1/tests/450" \
-H "X-API-Key: your_api_key_here"
# Get test results with metrics
curl -X GET "https://api.tyrereviews.com/v1/tests/450/results" \
-H "X-API-Key: your_api_key_here"
# Get brand details
curl -X GET "https://api.tyrereviews.com/v1/brands/3" \
-H "X-API-Key: your_api_key_here"
# Get brand tyres sorted by score
curl -X GET "https://api.tyrereviews.com/v1/brands/3/tyres?sort=score:desc&limit=10" \
-H "X-API-Key: your_api_key_here"
const API_KEY = 'your_api_key_here';
const BASE_URL = 'https://api.tyrereviews.com/v1';
const headers = { 'X-API-Key': API_KEY };
async function searchTyres(pattern, season) {
const res = await fetch(
`${BASE_URL}/tyres/search?pattern=${pattern}&season=${season}`,
{ headers }
);
return res.json();
}
async function getTyreDetails(tyreId) {
const res = await fetch(`${BASE_URL}/tyres/${tyreId}`, { headers });
return res.json();
}
async function getScoreExplanation(tyreId) {
const res = await fetch(`${BASE_URL}/tyres/${tyreId}/score-explanation`, { headers });
return res.json();
}
// Display category scores
getTyreDetails(3672).then(({ data }) => {
if (data.score_details) {
data.score_details.categories.forEach(cat => {
console.log(`${cat.name}: ${cat.display_score}% (${cat.test_count} tests)`);
});
}
});
import requests
API_KEY = 'your_api_key_here'
BASE_URL = 'https://api.tyrereviews.com/v1'
headers = {'X-API-Key': API_KEY}
def search_tyres(pattern, season=None, min_score=None):
params = {'pattern': pattern}
if season: params['season'] = season
if min_score: params['min_score'] = min_score
return requests.get(f'{BASE_URL}/tyres/search', headers=headers, params=params).json()
def get_tyre_details(tyre_id):
return requests.get(f'{BASE_URL}/tyres/{tyre_id}', headers=headers).json()
# Display category breakdowns
tyre = get_tyre_details(3672)
details = tyre['data'].get('score_details')
if details:
for cat in details['categories']:
print(f" {cat['name']}: {cat['display_score']}% ({cat['test_count']} tests)")
<?php
$apiKey = 'your_api_key_here';
$baseUrl = 'https://api.tyrereviews.com/v1';
function apiRequest($endpoint, $params = []) {
global $apiKey, $baseUrl;
$url = $baseUrl . $endpoint;
if ($params) $url .= '?' . http_build_query($params);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-API-Key: ' . $apiKey]);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
$results = apiRequest('/tyres/search', ['pattern' => 'michelin', 'season' => 1]);
foreach ($results['data'] as $tyre) {
echo $tyre['full_name'] . " - Score: " . $tyre['score'] . "\n";
}
Error Handling
The API uses standard HTTP status codes:
| Code | Meaning | Description |
|---|---|---|
| 200 | OK | Request successful |
| 400 | Bad Request | Invalid parameters or malformed request |
| 401 | Unauthorized | Invalid or missing API key |
| 404 | Not Found | Resource not found |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Server Error | Internal server error |
Error Response Format
{
"success": false,
"message": "Invalid API key",
"errors": ["The provided API key is not valid or has been suspended"],
"meta": {
"timestamp": "2026-01-19T10:30:00Z",
"request_id": "550e8400-e29b-41d4-a716-446655440000"
}
}
Common Issues
- Empty results? Check spelling (e.g., "Pirelli" not "Prelli")
- 404 on /tyres/{pattern}? Pattern not found — try searching first or use numeric ID
- 401 Unauthorized? Check your API key in the X-API-Key header
Rate Limits
Rate limits are enforced based on your subscription plan:
Basic
- 100 requests/hour
- 10,000 requests/month
- 1 year historical data
Professional
- 1,000 requests/hour
- 100,000 requests/month
- All historical data
Enterprise
- 10,000+ requests/hour
- Unlimited requests
- Custom endpoints + SLA
Rate Limit Headers
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 950
X-RateLimit-Reset: 1705665600
Best Practices
Caching
- Cache responses locally when possible
- Respect cache headers in responses
- Tyre details change infrequently
- Test results are static once published
Retries
- Implement exponential backoff
- Retry on 5xx errors only
- Don't retry on 4xx errors
- Maximum 3 retry attempts
Pro Tip
Use the fields parameter to request only specific fields and reduce response size:
GET /tyres/search?pattern=michelin&fields=id,brand,model,score
Support
We're here to help you integrate with the TyreReviews API.
Documentation
Comprehensive guides and API reference
Enterprise SLA
24-hour response, dedicated account manager