Overview
The ByteFLASH Tuning Data API gives authorised partners programmatic access to our vehicle tuning database. You can retrieve manufacturer lists, models, generation ranges, and detailed Stage 1 tuning figures (stock and tuned horsepower & torque, plus ECU types) to display on your own website.
https://www.byteflash.co.uk/api/v1/
JSON (UTF-8)
API key (header or query param)
All responses share this envelope structure:
{
"success": true,
"count": 42, // number of items returned (where applicable)
"data_key": [ ... ] // payload: key name varies per endpoint
}
// On error:
{
"success": false,
"error": "Human-readable error message"
}
Authentication
Every request must include your API key. There are two ways to send it; the header method is strongly preferred for server-side code, as the key will not appear in server logs or browser history.
Method 1: HTTP Header (recommended)
// Add this header to every request: X-API-Key: bf_your_key_here
Method 2: Query Parameter
https://www.byteflash.co.uk/api/v1/?action=manufacturers&api_key=bf_your_key_here
Your API key was provided to you by ByteFLASH. Treat it like a password; it is only sent to you once. If you ever lose it or suspect it has been compromised, contact us and we will issue a replacement immediately.
Errors & Status Codes
| HTTP Code | Meaning | Common cause |
|---|---|---|
| 200 OK | Success | Normal response |
| 400 Bad Request | Missing or invalid parameter | Forgot manufacturer_id, unknown action |
| 401 Unauthorized | No key or wrong key | Missing or incorrect X-API-Key |
| 403 Forbidden | Key valid but access denied | Key suspended, or request from a domain not on your whitelist |
| 429 Too Many Requests | Rate limit exceeded | Over your hourly allowance; check the Retry-After response header |
Always check success === true before using the payload:
$data = json_decode($response, true); if (!$data['success']) { // log or display $data['error'] throw new RuntimeException('API error: ' . $data['error']); }
Rate Limiting
Your API key has a request limit per rolling hour. When that limit is exceeded the API returns
HTTP 429 Too Many Requests along with a Retry-After: 3600 header.
If you need a higher limit, please get in touch with us.
Endpoints
All endpoints are GET requests to the same base URL; the
action parameter selects the operation.
GET ?action=manufacturers
Returns all vehicle manufacturers in the database, with a logo URL and model count for each.
Parameters: none beyond action.
Example response:
{
"success": true,
"count": 79,
"manufacturers": [
{
"id": 5,
"name": "Audi",
"logo_url": "https://www.byteflash.co.uk/images/brands/Audi.png",
"model_count": 18
},
{
"id": 7,
"name": "BMW",
"logo_url": "https://www.byteflash.co.uk/images/brands/BMW.png",
"model_count": 22
}
// ... more manufacturers
]
}
logo_url will be null for any manufacturer
where we do not hold a logo image. Always check for null before rendering an
<img> tag, or fall back to displaying the name as text.
GET ?action=models&manufacturer_id={id}
Returns all models for a given manufacturer.
| Parameter | Type | Required? | Description |
|---|---|---|---|
manufacturer_id | integer | Required | ID from the manufacturers endpoint |
Example response:
{
"success": true,
"count": 22,
"manufacturer": {
"id": 7,
"name": "BMW",
"logo_url": "https://www.byteflash.co.uk/images/brands/BMW.png"
},
"models": [
{ "id": 75, "name": "1 Series", "generation_count": 4 },
{ "id": 76, "name": "2 Series", "generation_count": 3 }
// ...
]
}
GET ?action=generations&model_id={id}
Returns all generation/year ranges for a given model.
| Parameter | Type | Required? | Description |
|---|---|---|---|
model_id | integer | Required | ID from the models endpoint |
Example response:
{
"success": true,
"count": 4,
"manufacturer": { "id": 7, "name": "BMW", "logo_url": "https://..." },
"model": { "id": 75, "name": "1 Series" },
"generations": [
{ "id": 160, "label": "E87 - 2004 - 2007", "variant_count": 12 },
{ "id": 161, "label": "E82 - 2007 - 2013", "variant_count": 9 }
// ...
]
}
GET ?action=variants&generation_id={id}
Returns all tuning variants (engine configurations) for a generation, with full performance figures.
| Parameter | Type | Required? | Description |
|---|---|---|---|
generation_id | integer | Required | ID from the generations endpoint |
Example response:
{
"success": true,
"count": 12,
"manufacturer": { "id": 7, "name": "BMW", "logo_url": "https://..." },
"model": { "id": 75, "name": "1 Series" },
"generation": { "id": 160, "label": "E87 - 2004 - 2007" },
"variants": [
{
"id": 825,
"engine_label": "116i 115hp",
"fuel": "Petrol",
"engine_size_cc": 1596,
"power": {
"stock_hp": 115, "tuned_hp": 128, "gain_hp": 13,
"stock_nm": 150, "tuned_nm": 165, "gain_nm": 15
},
"ecus": [ "Bosch ME9.2" ]
},
{
"id": 826,
"engine_label": "118D 122hp",
"fuel": "Diesel",
"engine_size_cc": 1995,
"power": {
"stock_hp": 122, "tuned_hp": 155, "gain_hp": 33,
"stock_nm": 280, "tuned_nm": 340, "gain_nm": 60
},
"ecus": [ "Bosch EDC16C35" ]
},
{
"id": 827,
"engine_label": "118i 129hp",
"fuel": "Petrol",
"engine_size_cc": 1995,
"power": {
"stock_hp": 129, "tuned_hp": 145, "gain_hp": 16,
"stock_nm": 180, "tuned_nm": 200, "gain_nm": 20
},
"ecus": [ "Bosch MEV946", "Bosch MEV1746" ]
}
// ... more variants
]
}
power (stock_hp, tuned_hp, etc.) may be null where
figures are not available for that engine. Always null-check before doing arithmetic or display.
GET ?action=search&make={name}
Returns the complete hierarchy (manufacturers → models → generations → variants) in a single call. Useful for building a vehicle lookup widget without multiple round-trips.
| Parameter | Type | Required? | Description |
|---|---|---|---|
make | string | Required | Manufacturer name; partial match, case-insensitive. e.g. BMW or vw |
model | string | Optional | Model name filter. e.g. 3 Series |
generation | string | Optional | Generation label filter. e.g. F30 |
Example URL:
https://www.byteflash.co.uk/api/v1/?action=search&make=BMW&model=1+Series&api_key=bf_your_key
PHP Code Examples
All examples use PHP's built-in file_get_contents() with a stream context; no
additional libraries required.
Basic request: fetch all manufacturers
<?php $api_key = 'bf_your_key_here'; $base_url = 'https://www.byteflash.co.uk/api/v1/'; // Build the request with the API key in a header $context = stream_context_create([ 'http' => [ 'header' => 'X-API-Key: ' . $api_key, 'timeout' => 10, ] ]); $url = $base_url . '?action=manufacturers'; $json = file_get_contents($url, false, $context); if ($json === false) { die('Could not reach the API.'); } $data = json_decode($json, true); if (!$data['success']) { die('API error: ' . $data['error']); } foreach ($data['manufacturers'] as $mfr) { echo $mfr['name'] . ' (' . $mfr['model_count'] . ' models)' . PHP_EOL; }
Reusable API client class
For real projects, wrap the API calls in a simple class to avoid repetition:
<?php class ByteFlashApi { private $api_key; private $base_url = 'https://www.byteflash.co.uk/api/v1/'; public function __construct(string $api_key) { $this->api_key = $api_key; } /** * Low-level request. Returns decoded array or throws on error. */ private function request(string $action, array $params = []): array { $params['action'] = $action; $url = $this->base_url . '?' . http_build_query($params); $context = stream_context_create([ 'http' => [ 'header' => 'X-API-Key: ' . $this->api_key, 'timeout' => 10, ] ]); $json = file_get_contents($url, false, $context); if ($json === false) { throw new RuntimeException('ByteFlash API: network error.'); } $data = json_decode($json, true); if (!isset($data['success'])) { throw new RuntimeException('ByteFlash API: invalid JSON response.'); } if (!$data['success']) { throw new RuntimeException('ByteFlash API error: ' . $data['error']); } return $data; } public function getManufacturers(): array { return $this->request('manufacturers')['manufacturers']; } public function getModels(int $manufacturer_id): array { return $this->request('models', ['manufacturer_id' => $manufacturer_id])['models']; } public function getGenerations(int $model_id): array { return $this->request('generations', ['model_id' => $model_id])['generations']; } public function getVariants(int $generation_id): array { return $this->request('variants', ['generation_id' => $generation_id])['variants']; } public function search(string $make, string $model = '', string $generation = ''): array { $params = ['make' => $make]; if ($model) $params['model'] = $model; if ($generation) $params['generation'] = $generation; return $this->request('search', $params)['results']; } } // Usage: $api = new ByteFlashApi('bf_your_key_here'); $manufacturers = $api->getManufacturers(); $models = $api->getModels(7); // BMW $generations = $api->getGenerations(75); // BMW 1 Series $variants = $api->getVariants(160); // BMW 1 Series E87
Display a tuning results table
A complete, page-ready example. Drop it into any PHP page on your site after swapping in your key
and populating $generation_id from user input.
<?php $api_key = 'bf_your_key_here'; $base_url = 'https://www.byteflash.co.uk/api/v1/'; $generation_id = (int) ($_GET['gen'] ?? 0); if (!$generation_id) { die('No generation selected.'); } $context = stream_context_create(['http' => [ 'header' => 'X-API-Key: ' . $api_key, 'timeout' => 10, ]]); $data = json_decode( file_get_contents($base_url . '?action=variants&generation_id=' . $generation_id, false, $context), true ); if (!$data['success']) { die(htmlspecialchars($data['error'])); } $mfr = $data['manufacturer']; $gen = $data['generation']; $vars = $data['variants']; ?> <h2> <?php if ($mfr['logo_url']): ?> <img src="<?= htmlspecialchars($mfr['logo_url']) ?>" alt="<?= htmlspecialchars($mfr['name']) ?>" style="height:40px;vertical-align:middle;margin-right:10px"> <?php endif; ?> <?= htmlspecialchars($data['model']['name'] . ' ' . $gen['label']) ?> </h2> <table> <thead> <tr> <th>Engine</th><th>Fuel</th> <th>Stock HP</th><th>Tuned HP</th><th>Gain HP</th> <th>Stock Nm</th><th>Tuned Nm</th><th>Gain Nm</th> <th>ECU(s)</th> </tr> </thead> <tbody> <?php foreach ($vars as $v): ?> <?php $p = $v['power']; ?> <tr> <td><?= htmlspecialchars($v['engine_label']) ?></td> <td><?= htmlspecialchars($v['fuel']) ?></td> <td><?= $p['stock_hp'] ?? '—' ?></td> <td><?= $p['tuned_hp'] ?? '—' ?></td> <td><?= $p['gain_hp'] !== null ? '+' . $p['gain_hp'] : '—' ?></td> <td><?= $p['stock_nm'] ?? '—' ?></td> <td><?= $p['tuned_nm'] ?? '—' ?></td> <td><?= $p['gain_nm'] !== null ? '+' . $p['gain_nm'] : '—' ?></td> <td><?= htmlspecialchars(implode(', ', $v['ecus'])) ?></td> </tr> <?php endforeach; ?> </tbody> </table>
Rendering manufacturer logos safely
Because logo_url can be null, always provide a text fallback:
<?php foreach ($manufacturers as $mfr): ?> <div class="brand-card"> <?php if ($mfr['logo_url']): ?> <img src="<?= htmlspecialchars($mfr['logo_url']) ?>" alt="<?= htmlspecialchars($mfr['name']) ?> logo" class="brand-logo"> <?php else: ?> <span class="brand-name"><?= htmlspecialchars($mfr['name']) ?></span> <?php endif; ?> </div> <?php endforeach; ?>
Caching responses (recommended)
The vehicle database changes infrequently. Caching API responses on your server speeds up your pages and means your site keeps working if the API is temporarily unreachable.
<?php function cachedApiCall(string $url, string $api_key, int $ttl_seconds = 3600): array { // Cache file lives in your temp dir; adjust path as needed $cache_file = sys_get_temp_dir() . '/' . 'bf_api_' . md5($url) . '.json'; // Return cached version if it exists and is still fresh if (file_exists($cache_file) && (time() - filemtime($cache_file)) < $ttl_seconds) { return json_decode(file_get_contents($cache_file), true); } // Fetch from API $context = stream_context_create(['http' => [ 'header' => 'X-API-Key: ' . $api_key, 'timeout' => 10, ]]); $json = @file_get_contents($url, false, $context); if ($json === false) { // Network error: serve stale cache if available, otherwise fail if (file_exists($cache_file)) { return json_decode(file_get_contents($cache_file), true); } throw new RuntimeException('API unreachable and no cached data available.'); } $data = json_decode($json, true); if (!empty($data['success'])) { // Only cache successful responses file_put_contents($cache_file, $json, LOCK_EX); } return $data; } // Usage: cache the manufacturer list for 6 hours: $api_key = 'bf_your_key_here'; $base_url = 'https://www.byteflash.co.uk/api/v1/'; $data = cachedApiCall( $base_url . '?action=manufacturers', $api_key, 21600 // 6 hours in seconds ); $manufacturers = $data['manufacturers'] ?? [];
Key Security & Sharing Prevention
Your API key grants access to ByteFLASH data on your behalf. If a key is leaked, someone else could consume your request allowance. Here is what we do to protect you, and what you should do on your side.
What we enforce on our side
| Mechanism | How it works |
|---|---|
| Domain whitelisting | Your key can be locked to one or more specific domains. Requests arriving with a different
Origin or Referer header are rejected with HTTP 403.
Contact us when setting up your account to enable this. |
| Rate limiting | Your key has a per-hour request allowance. Even if a key is accidentally shared, any misuse is automatically bounded. |
| Request logging | Every request is recorded with its IP address and origin domain. Unusual activity is monitored and may result in a key being suspended. |
| Instant revocation | If your key is ever compromised, contact us and we can suspend or replace it immediately; the old key stops working straight away. |
| One-way key storage | Keys are stored as a cryptographic hash. Even in the event of a database breach, the raw key values cannot be recovered. |
What you should do
- Never put your API key in client-side JavaScript. Anyone viewing your page source can steal it. Always make API calls from server-side PHP, then pass the resulting data to the browser as HTML or your own JSON.
- Ask us to lock your key to your domain. This alone prevents almost all casual key theft.
- Store the key in a config file or environment variable outside your web root, not hardcoded in PHP files that might end up in a repository.
- Contact us immediately if you believe your key has been seen by someone who should not have it; we will issue a replacement straight away.
<script> fetch('https://www.byteflash.co.uk/api/v1/?action=manufacturers&api_key=bf_your_key') .then(r => r.json()).then(data => console.log(data)); </script>