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.

Base URL
https://www.byteflash.co.uk/api/v1/
Format
JSON (UTF-8)
Authentication
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
Avoid the query-parameter method in production. Your key will appear in browser network tools, server access logs, and any analytics package that records full URLs. Use it only for quick local testing.

Your API key is provided by ByteFLASH. Treat it like a password; it is only sent to you once. If you ever lose it or believe it has been compromised, contact us and we will issue a replacement immediately.

Errors & Status Codes

HTTP CodeMeaningCommon cause
200 OKSuccessNormal response
400 Bad RequestMissing or invalid parameterForgot manufacturer_id, unknown action
401 UnauthorizedNo key or wrong keyMissing or incorrect X-API-Key
403 ForbiddenKey valid but access deniedKey suspended, or request from a domain not on your whitelist
429 Too Many RequestsRate limit exceededOver 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.

Best practice: cache responses on your side. The vehicle database changes infrequently, so caching for 1–24 hours will keep you well within your limit even on busy sites, and makes your pages faster. See the caching example below.

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 URLs: 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.

ParameterTypeRequired?Description
manufacturer_idintegerRequiredID from the manufacturers endpoint
{
  "success":      true,
  "count":        22,
  "manufacturer": { "id": 7, "name": "BMW", "logo_url": "https://..." },
  "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.

ParameterTypeRequired?Description
model_idintegerRequiredID from the models endpoint
{
  "success":    true,
  "count":      4,
  "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.

ParameterTypeRequired?Description
generation_idintegerRequiredID from the generations endpoint
{
  "success":  true,
  "count":    12,
  "variants": [
    {
      "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" ]
    }
    // ... more variants
  ]
}
Any field within power may be null where figures are not available for that engine. Always null-check before doing arithmetic or display.

Returns the complete hierarchy (manufacturers → models → generations → variants) in a single call. Useful for building a vehicle lookup widget without multiple round-trips.

ParameterTypeRequired?Description
makestringRequiredManufacturer name; partial match, case-insensitive. e.g. BMW or vw
modelstringOptionalModel name filter. e.g. 3 Series
generationstringOptionalGeneration label filter. e.g. F30
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/';

$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

<?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; }

    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 (!$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 $id): array { return $this->request('models', ['manufacturer_id' => $id])['models']; }
    public function getGenerations(int $id): array { return $this->request('generations', ['model_id' => $id])['generations']; }
    public function getVariants(int $id): array { return $this->request('variants', ['generation_id' => $id])['variants']; }
}

$api = new ByteFlashApi('bf_your_key_here');
$manufacturers = $api->getManufacturers();
$models        = $api->getModels(7);       // BMW
$variants      = $api->getVariants(160);    // BMW 1 Series E87

Display a tuning results table

<?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'])); }
// ... render table using $data['variants']

Rendering manufacturer logos safely

<?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)

<?php

function cachedApiCall(string $url, string $api_key, int $ttl_seconds = 3600): array
{
    $cache_file = sys_get_temp_dir() . '/' . 'bf_api_' . md5($url) . '.json';
    if (file_exists($cache_file) && (time() - filemtime($cache_file)) < $ttl_seconds) {
        return json_decode(file_get_contents($cache_file), true);
    }
    $context = stream_context_create(['http' => ['header' => 'X-API-Key: ' . $api_key, 'timeout' => 10]]);
    $json = @file_get_contents($url, false, $context);
    if ($json === false) {
        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'])) { file_put_contents($cache_file, $json, LOCK_EX); }
    return $data;
}

// Cache the manufacturer list for 6 hours:
$data = cachedApiCall($base_url . '?action=manufacturers', $api_key, 21600);
$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.

What we enforce on our side

MechanismHow it works
Domain whitelistingYour key can be locked to specific domains. Requests from other origins are rejected with HTTP 403. Contact us when setting up your account to enable this.
Rate limitingYour key has a per-hour request allowance. Even if a key is accidentally shared, any misuse is automatically bounded.
Request loggingEvery request is recorded with its IP address and origin domain. Unusual activity is monitored and may result in a key being suspended.
Instant revocationIf your key is ever compromised, contact us and we can suspend or replace it immediately.
One-way key storageKeys 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. 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.
Never do this: key visible in browser source and network tools:
<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>
Do this instead: Call the API from your server-side PHP and output the data directly into your page HTML, or serve it through your own endpoint. Your API key never leaves your server.