Home > Uncategorized > Spanish Vehicle Registration API: Complete Guide to Vehicle and Motorcycle Data Lookup in Spain

Spanish Vehicle Registration API: Complete Guide to Vehicle and Motorcycle Data Lookup in Spain

https://www.matriculaapi.com/
Spain maintains a comprehensive vehicle registration system managed by the Dirección General de Tráfico (DGT), covering over 25 million registered vehicles across the Iberian Peninsula, Balearic Islands, Canary Islands, and Spanish territories. The Spanish Vehicle Registration API provides developers and businesses with access to detailed vehicle specifications, technical data, and theft status information for both cars and motorcycles registered throughout Spain.

Overview of Spanish Vehicle Registration System

Spain’s vehicle registration is centralized under the DGT (Dirección General de Tráfico), which maintains detailed records for all vehicles operating on Spanish roads. The system provides comprehensive data including technical specifications, variant information, and critical safety indicators such as stolen vehicle status.

Spanish license plates have evolved through several formats:

  • Current format (2000-present): Four numbers + three letters (1234 ABC)
  • Previous format: Letters indicating province + numbers + letters
  • Special plates: Diplomatic, military, historical, and temporary registrations

Spanish Vehicle API Features

Available Data for Cars

When querying Spanish car registrations through the /CheckSpain endpoint, you can retrieve:

  • Make and Model – Complete manufacturer and vehicle model identification
  • Registration Year – Year when the vehicle was first registered in Spain
  • Registration Date – Exact date of vehicle registration
  • Engine Specifications – Engine displacement in cubic centimeters
  • Fuel Type – Detailed fuel classification (Diesel, Gasolina, etc.)
  • Vehicle Variant – Specific model variant and trim level
  • Technical Details – Number of seats, doors, and variant type
  • Power Rating – Dynamic power in horsepower
  • VIN Number – Vehicle Identification Number when available
  • Stolen Status – Critical indicator if vehicle has been reported stolen
  • Indicative Price – Reference pricing information

Sample Car Response Format

{
  "Description": "RENAULT MEGANE",
  "CarMake": {
    "CurrentTextValue": "RENAULT"
  },
  "CarModel": {
    "CurrentTextValue": "MEGANE"
  },
  "MakeDescription": {
    "CurrentTextValue": "RENAULT"
  },
  "ModelDescription": {
    "CurrentTextValue": "MEGANE"
  },
  "EngineSize": "1461",
  "VehicleIdentificationNumber": null,
  "RegistrationYear": "2010",
  "RegistrationDate": "06/07/2010",
  "Variation": "EXPRESSION 1.5DCI 85",
  "Seats": null,
  "VariantType": "Diesel 1461 cc 5 puertas",
  "VehicleType": "Car",
  "Fuel": "Diesel",
  "IndicativePrice": null,
  "Doors": "5",
  "AllTerain": null,
  "DynamicPower": "85.0",
  "Stolen": null
}

Spanish Motorcycle API

Dedicated Motorcycle Endpoint

For motorcycles and scooters registered in Spain, use the specialized motorcycle endpoint: https://www.matriculaapi.com/api/bespokeapi.asmx?op=CheckMotorBikeSpain

This endpoint returns motorcycle-specific data optimized for two-wheeled vehicles.

Available Data for Motorcycles

When querying Spanish motorcycle registrations, you can retrieve:

  • Make and Model – Motorcycle manufacturer and model identification
  • Registration Year – Year of first registration in Spain
  • Registration Date – Exact registration date
  • Engine Size – Engine displacement in cubic centimeters
  • Fuel Type – Fuel classification (typically Gasolina for motorcycles)
  • Variant – Specific motorcycle variant and version
  • Number of Seats – Rider and passenger capacity
  • Indicative Price – Reference pricing information
  • Transmission Type – Manual or automatic transmission
  • Dynamic Power – Power output in horsepower
  • Stolen Status – Critical theft indicator
  • VIN Number – Vehicle Identification Number when available

Sample Motorcycle Response Format

{
  "Description": "SUZUKI DL 650 V-STROM",
  "CarMake": {
    "CurrentTextValue": "SUZUKI"
  },
  "CarModel": {
    "CurrentTextValue": "DL 650"
  },
  "MakeDescription": {
    "CurrentTextValue": "SUZUKI"
  },
  "ModelDescription": {
    "CurrentTextValue": "DL 650"
  },
  "EngineSize": "645",
  "VehicleIdentificationNumber": "",
  "RegistrationYear": "2003",
  "RegistrationDate": "01/11/2003",
  "Variation": "V-STROM",
  "Seats": 1,
  "VariantType": "",
  "VehicleType": "MOTOCICLETA",
  "Fuel": "GASOLINA",
  "IndicativePrice": "7909.79",
  "Doors": 0,
  "AllTerain": 0,
  "KType": 0,
  "Transmission": "MANUAL",
  "DynamicPower": "68",
  "Stolen": null
}

API Implementation

Endpoint Usage

The Spanish Vehicle API uses two primary endpoints:

  1. Cars: /CheckSpain – For passenger vehicles, vans, and trucks
  2. Motorcycles: /CheckMotorBikeSpain – For motorcycles, scooters, and mopeds

Both endpoints require:

  • Registration Number – The complete Spanish license plate number
  • Username – Your API authentication credentials

Basic Implementation Example

// JavaScript example for Spanish vehicle lookup
class SpanishVehicleAPI {
  constructor(username) {
    this.username = username;
    this.carUrl = "https://www.matriculaapi.com/api/reg.asmx/CheckSpain";
    this.motorcycleUrl = "https://www.matriculaapi.com/api/bespokeapi.asmx/CheckMotorBikeSpain";
  }
  
  async lookupCar(registrationNumber) {
    const apiUrl = `${this.carUrl}?RegistrationNumber=${registrationNumber}&username=${this.username}`;
    
    try {
      const response = await fetch(apiUrl);
      const xmlText = await response.text();
      
      // Parse XML response
      const parser = new DOMParser();
      const xmlDoc = parser.parseFromString(xmlText, "text/xml");
      const jsonData = xmlDoc.getElementsByTagName("vehicleJson")[0].textContent;
      const vehicleInfo = JSON.parse(jsonData);
      
      return {
        type: 'car',
        make: vehicleInfo.MakeDescription.CurrentTextValue,
        model: vehicleInfo.ModelDescription.CurrentTextValue,
        year: vehicleInfo.RegistrationYear,
        registrationDate: vehicleInfo.RegistrationDate,
        engineSize: vehicleInfo.EngineSize,
        fuel: vehicleInfo.Fuel,
        power: vehicleInfo.DynamicPower,
        variant: vehicleInfo.Variation,
        variantType: vehicleInfo.VariantType,
        doors: vehicleInfo.Doors,
        seats: vehicleInfo.Seats,
        vin: vehicleInfo.VehicleIdentificationNumber,
        kType: vehicleInfo.KType,
        stolen: vehicleInfo.Stolen,
        indicativePrice: vehicleInfo.IndicativePrice
      };
    } catch (error) {
      console.error('Spanish car lookup failed:', error);
      return null;
    }
  }
  
  async lookupMotorcycle(registrationNumber) {
    const apiUrl = `${this.motorcycleUrl}?RegistrationNumber=${registrationNumber}&username=${this.username}`;
    
    try {
      const response = await fetch(apiUrl);
      const xmlText = await response.text();
      
      // Parse XML response
      const parser = new DOMParser();
      const xmlDoc = parser.parseFromString(xmlText, "text/xml");
      const jsonData = xmlDoc.getElementsByTagName("vehicleJson")[0].textContent;
      const motorcycleInfo = JSON.parse(jsonData);
      
      return {
        type: 'motorcycle',
        make: motorcycleInfo.MakeDescription.CurrentTextValue,
        model: motorcycleInfo.ModelDescription.CurrentTextValue,
        year: motorcycleInfo.RegistrationYear,
        registrationDate: motorcycleInfo.RegistrationDate,
        engineSize: motorcycleInfo.EngineSize,
        fuel: motorcycleInfo.Fuel,
        power: motorcycleInfo.DynamicPower,
        variant: motorcycleInfo.Variation,
        seats: motorcycleInfo.Seats,
        transmission: motorcycleInfo.Transmission,
        vin: motorcycleInfo.VehicleIdentificationNumber,
        stolen: motorcycleInfo.Stolen,
        indicativePrice: motorcycleInfo.IndicativePrice
      };
    } catch (error) {
      console.error('Spanish motorcycle lookup failed:', error);
      return null;
    }
  }
  
  async lookupWithAutoDetect(registrationNumber) {
    // Try car lookup first
    let result = await this.lookupCar(registrationNumber);
    if (result && result.make) {
      return result;
    }
    
    // If car lookup fails, try motorcycle
    result = await this.lookupMotorcycle(registrationNumber);
    return result;
  }
}

// Usage examples
const api = new SpanishVehicleAPI("your_username");

// Car lookup
api.lookupCar("5428GXS").then(data => {
  if (data) {
    console.log(`Car: ${data.make} ${data.model} (${data.year})`);
    console.log(`Engine: ${data.engineSize}cc ${data.fuel}`);
    console.log(`Power: ${data.power}HP`);
    console.log(`Variant: ${data.variant}`);
    if (data.stolen) {
      console.warn('⚠️ VEHICLE REPORTED STOLEN');
    }
  }
});

// Motorcycle lookup
api.lookupMotorcycle("1234ABC").then(data => {
  if (data) {
    console.log(`Motorcycle: ${data.make} ${data.model} (${data.year})`);
    console.log(`Engine: ${data.engineSize}cc`);
    console.log(`Power: ${data.power}HP`);
    console.log(`Transmission: ${data.transmission}`);
  }
});

// Auto-detect vehicle type
api.lookupWithAutoDetect("5428GXS").then(data => {
  if (data) {
    console.log(`${data.type}: ${data.make} ${data.model}`);
  }
});

Python Implementation

import requests
import xml.etree.ElementTree as ET
import json

class SpanishVehicleAPI:
    def __init__(self, username):
        self.username = username
        self.car_url = "https://www.matriculaapi.com/api/reg.asmx/CheckSpain"
        self.motorcycle_url = "https://www.matriculaapi.com/api/bespokeapi.asmx/CheckMotorBikeSpain"
    
    def validate_spanish_registration(self, registration):
        """Validate Spanish registration number format"""
        if not registration:
            return False, "Registration number is required"
        
        # Remove spaces and convert to uppercase
        reg = registration.replace(" ", "").upper()
        
        # Spanish format: 4 numbers + 3 letters (modern format)
        if len(reg) < 6 or len(reg) > 8:
            return False, "Invalid registration length"
        
        return True, reg
    
    def lookup_car(self, registration_number):
        """Lookup Spanish car with comprehensive error handling"""
        is_valid, processed_reg = self.validate_spanish_registration(registration_number)
        if not is_valid:
            return {"error": processed_reg}
        
        try:
            params = {
                'RegistrationNumber': processed_reg,
                'username': self.username
            }
            
            response = requests.get(self.car_url, params=params, timeout=15)
            response.raise_for_status()
            
            # Parse XML response
            root = ET.fromstring(response.content)
            json_element = root.find('.//vehicleJson')
            
            if json_element is None or not json_element.text:
                return {"error": "No car data found for this registration number"}
            
            vehicle_data = json.loads(json_element.text)
            
            return {
                'success': True,
                'type': 'car',
                'description': vehicle_data.get('Description'),
                'make': vehicle_data.get('MakeDescription', {}).get('CurrentTextValue'),
                'model': vehicle_data.get('ModelDescription', {}).get('CurrentTextValue'),
                'registration_year': vehicle_data.get('RegistrationYear'),
                'registration_date': vehicle_data.get('RegistrationDate'),
                'engine_size': vehicle_data.get('EngineSize'),
                'fuel_type': vehicle_data.get('Fuel'),
                'power_hp': vehicle_data.get('DynamicPower'),
                'variant': vehicle_data.get('Variation'),
                'variant_type': vehicle_data.get('VariantType'),
                'doors': vehicle_data.get('Doors'),
                'seats': vehicle_data.get('Seats'),
                'vin': vehicle_data.get('VehicleIdentificationNumber'),
                'k_type': vehicle_data.get('KType'),
                'stolen': vehicle_data.get('Stolen'),
                'indicative_price': vehicle_data.get('IndicativePrice'),
                'all_terrain': vehicle_data.get('AllTerain'),
                'raw_data': vehicle_data
            }
            
        except Exception as e:
            return {"error": f"Car lookup failed: {str(e)}"}
    
    def lookup_motorcycle(self, registration_number):
        """Lookup Spanish motorcycle"""
        is_valid, processed_reg = self.validate_spanish_registration(registration_number)
        if not is_valid:
            return {"error": processed_reg}
        
        try:
            params = {
                'RegistrationNumber': processed_reg,
                'username': self.username
            }
            
            response = requests.get(self.motorcycle_url, params=params, timeout=15)
            response.raise_for_status()
            
            # Parse XML response
            root = ET.fromstring(response.content)
            json_element = root.find('.//vehicleJson')
            
            if json_element is None or not json_element.text:
                return {"error": "No motorcycle data found for this registration number"}
            
            motorcycle_data = json.loads(json_element.text)
            
            return {
                'success': True,
                'type': 'motorcycle',
                'description': motorcycle_data.get('Description'),
                'make': motorcycle_data.get('MakeDescription', {}).get('CurrentTextValue'),
                'model': motorcycle_data.get('ModelDescription', {}).get('CurrentTextValue'),
                'registration_year': motorcycle_data.get('RegistrationYear'),
                'registration_date': motorcycle_data.get('RegistrationDate'),
                'engine_size': motorcycle_data.get('EngineSize'),
                'fuel_type': motorcycle_data.get('Fuel'),
                'power_hp': motorcycle_data.get('DynamicPower'),
                'variant': motorcycle_data.get('Variation'),
                'seats': motorcycle_data.get('Seats'),
                'transmission': motorcycle_data.get('Transmission'),
                'vin': motorcycle_data.get('VehicleIdentificationNumber'),
                'stolen': motorcycle_data.get('Stolen'),
                'indicative_price': motorcycle_data.get('IndicativePrice'),
                'raw_data': motorcycle_data
            }
            
        except Exception as e:
            return {"error": f"Motorcycle lookup failed: {str(e)}"}
    
    def lookup_with_auto_detect(self, registration_number):
        """Try both car and motorcycle endpoints automatically"""
        # Try car first
        result = self.lookup_car(registration_number)
        if result.get('success'):
            return result
        
        # Try motorcycle if car lookup fails
        result = self.lookup_motorcycle(registration_number)
        if result.get('success'):
            return result
        
        return {"error": "Vehicle not found in car or motorcycle databases"}

# Usage examples
api = SpanishVehicleAPI("your_username")

# Car lookup
car_result = api.lookup_car("5428GXS")
if car_result.get('success'):
    print(f"Car: {car_result['make']} {car_result['model']}")
    print(f"Year: {car_result['registration_year']}")
    print(f"Engine: {car_result['engine_size']}cc {car_result['fuel_type']}")
    print(f"Power: {car_result['power_hp']}HP")
    print(f"Variant: {car_result['variant']}")
    
    if car_result['stolen']:
        print("⚠️ WARNING: VEHICLE REPORTED STOLEN")

# Motorcycle lookup
bike_result = api.lookup_motorcycle("1234ABC")
if bike_result.get('success'):
    print(f"Motorcycle: {bike_result['make']} {bike_result['model']}")
    print(f"Engine: {bike_result['engine_size']}cc")
    print(f"Power: {bike_result['power_hp']}HP")
    print(f"Transmission: {bike_result['transmission']}")

# Auto-detect vehicle type
auto_result = api.lookup_with_auto_detect("5428GXS")
if auto_result.get('success'):
    print(f"Vehicle Type: {auto_result['type']}")
    print(f"Vehicle: {auto_result['make']} {auto_result['model']}")

Spanish Vehicle Registration Format

Current Format (2000-Present)

Spanish license plates use the format: 1234 ABC

  • Four numbers: Sequential numbering (0000-9999)
  • Three letters: Alphabetical sequence (avoiding vowels and confusing letters)
  • No regional identification in current system

Historical Formats

  • Provincial system (1971-2000): Letters indicating province + numbers + letters
    • Examples: M-1234-AB (Madrid), B-5678-CD (Barcelona)

Special Registration Plates

  • Diplomatic: Special CD series with different formatting
  • Historical: H prefix for vintage vehicles over 30 years old
  • Temporary: Red plates for unregistered vehicles
  • Military: Special military identification series
  • Motorcycle: Same format as cars but typically on smaller plates

Understanding Spanish Vehicle Data

Fuel Type Classifications

Spanish fuel type terminology:

  • Gasolina – Petrol/Gasoline
  • Diesel – Diesel fuel
  • Eléctrico – Electric vehicle
  • Híbrido – Hybrid vehicle
  • GLP – Liquefied Petroleum Gas (Autogas)
  • Gas Natural – Compressed Natural Gas

Vehicle Type Classifications

  • Turismo – Passenger car
  • Furgoneta – Van
  • Camión – Truck
  • Motocicleta – Motorcycle
  • Ciclomotor – Moped
  • Quad – All-terrain quad vehicle

Stolen Vehicle Indicator

The Stolen field is critical for security:

  • null – No theft report on record
  • “Yes” or populated value – Vehicle reported stolen to DGT
  • Always check this field before processing vehicle transactions

Spanish Motorcycle Market

Popular Spanish Motorcycle Brands

While Spain is home to fewer motorcycle manufacturers than some European countries, it has a strong motorcycle culture:

Spanish Manufacturers:

  • RIEJU – Off-road and enduro motorcycles
  • Gas Gas – Trial and enduro specialists
  • Derbi – Scooters and small displacement motorcycles (now part of Piaggio)
  • Bultaco – Historic brand with recent electric motorcycle revival
  • Ossa – Classic motorcycle manufacturer

Popular International Brands in Spain:

  • Honda – Leading market share in Spain
  • Yamaha – Popular for both scooters and motorcycles
  • Suzuki – Strong presence in touring and adventure segments
  • BMW – Premium motorcycle segment leader
  • Harley-Davidson – Cruiser market leader

Motorcycle Registration Specifics

Spanish motorcycles follow the same registration format as cars but with motorcycle-specific data:

  • Detailed engine displacement tracking
  • Power output in horsepower
  • Transmission type (manual vs automatic/semi-automatic)
  • Seating capacity (rider only or with passenger)

Use Cases for Spanish Vehicle API

Insurance Industry

  • Premium Calculations – Engine size and power ratings for risk assessment
  • Claims Processing – Verify vehicle specifications during claims
  • Stolen Vehicle Checks – Critical fraud prevention through stolen status
  • Motorcycle Insurance – Specialized data for two-wheeled vehicle policies

Automotive and Motorcycle Dealers

  • Trade-In Valuations – Indicative pricing and specification verification
  • Vehicle History – Registration date and variant confirmation
  • Fraud Prevention – Stolen vehicle status before purchase
  • Inventory Management – Automated vehicle data for listings

Fleet Management

  • Asset Tracking – Comprehensive vehicle identification for cars and motorcycles
  • Compliance Monitoring – Ensure proper registration across fleet
  • Theft Monitoring – Regular stolen status checks for fleet vehicles
  • Maintenance Planning – Engine specifications for service schedules

Law Enforcement

  • Vehicle Identification – Quick lookups during traffic stops
  • Stolen Vehicle Detection – Immediate access to theft indicators
  • Investigation Support – Vehicle history and specification verification
  • Motorcycle Enforcement – Dedicated motorcycle data for traffic control

Mobile Applications

  • Insurance Apps – Instant vehicle verification for quotes
  • Marketplace Apps – Vehicle specification for classified listings
  • Service Booking – Technical specs for maintenance appointments
  • Parking Apps – Vehicle type identification for permit validation

Error Handling and Security Considerations

class SecureSpanishVehicleAPI extends SpanishVehicleAPI {
  constructor(username) {
    super(username);
    this.maxRetries = 3;
    this.retryDelay = 1000; // milliseconds
  }
  
  async lookupWithSecurity(registrationNumber, vehicleType = 'auto') {
    // Validate input to prevent injection
    if (!this.validateInput(registrationNumber)) {
      return {
        error: true,
        message: "Invalid registration format",
        security: "Input validation failed"
      };
    }
    
    // Perform lookup with retry logic
    let lastError;
    for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
      try {
        let result;
        
        if (vehicleType === 'car') {
          result = await this.lookupCar(registrationNumber);
        } else if (vehicleType === 'motorcycle') {
          result = await this.lookupMotorcycle(registrationNumber);
        } else {
          result = await this.lookupWithAutoDetect(registrationNumber);
        }
        
        // Check for stolen vehicle
        if (result && result.stolen) {
          console.warn(`SECURITY ALERT: Vehicle ${registrationNumber} reported stolen`);
          result.securityAlert = "STOLEN_VEHICLE";
        }
        
        return result;
        
      } catch (error) {
        lastError = error;
        
        if (attempt < this.maxRetries) {
          await new Promise(resolve => 
            setTimeout(resolve, this.retryDelay * attempt)
          );
        }
      }
    }
    
    return {
      error: true,
      message: `Lookup failed after ${this.maxRetries} attempts`,
      details: lastError.message
    };
  }
  
  validateInput(registration) {
    // Prevent SQL injection and XSS
    if (!registration || typeof registration !== 'string') {
      return false;
    }
    
    // Check for suspicious characters
    const suspiciousPattern = /[;<>'"\\]/;
    if (suspiciousPattern.test(registration)) {
      return false;
    }
    
    return true;
  }
}

Data Privacy and Compliance

GDPR Compliance

Spain follows strict EU data protection regulations:

  • Vehicle technical data is not personal information
  • Registration numbers are public vehicle identifiers
  • Implement proper data retention policies
  • Ensure secure handling of stolen vehicle information

Security Best Practices

  • Always check stolen status before vehicle transactions
  • Log all stolen vehicle alerts for audit trails
  • Implement rate limiting to prevent abuse
  • Secure API credentials and use HTTPS only

Getting Started

Account Registration

  1. Sign Up – Register for Spanish vehicle API access
  2. Verification – Complete business verification process
  3. Testing – Use sample registrations for development:
    • Cars: “5428GXS” (Renault Megane from documentation)
    • Motorcycles: Test with various Spanish motorcycle plates
  4. Production – Configure both car and motorcycle endpoints

Integration Checklist

  • [ ] Implement both car and motorcycle endpoints
  • [ ] Add stolen vehicle status checking and alerting
  • [ ] Create auto-detect logic for vehicle type
  • [ ] Design UI for Spanish registration format
  • [ ] Implement security validation for inputs
  • [ ] Add logging for stolen vehicle alerts
  • [ ] Test with both modern and historical plate formats

Sample Data for Testing

  • Cars: 5428GXS (Renault Megane Diesel)
  • Motorcycles: Various Spanish motorcycle registrations
  • Stolen checks: Verify stolen status handling

Conclusion

The Spanish Vehicle Registration API provides comprehensive access to Spain’s vehicle database, offering detailed technical specifications for both cars and motorcycles. The system’s inclusion of stolen vehicle indicators makes it particularly valuable for fraud prevention and security applications, while the dedicated motorcycle endpoint ensures proper data handling for Spain’s significant two-wheeled vehicle population.

Spain’s centralized DGT system ensures consistent data quality while the API’s dual endpoint approach allows for optimized data retrieval for different vehicle types. Understanding Spanish fuel classifications, registration formats, and the critical importance of stolen vehicle checking enhances the effectiveness of API integration.

The motorcycle-specific endpoint recognizes Spain’s vibrant motorcycle culture and provides specialized data fields for transmission types, seating configurations, and power ratings appropriate for two-wheeled vehicles.

Begin accessing Spanish vehicle data by registering for API credentials and exploring the comprehensive database covering cars and motorcycles across all Spanish regions and territories. Always implement stolen vehicle status checking to ensure secure and compliant vehicle data operations.
https://www.matriculaapi.com/

Categories: Uncategorized
  1. No comments yet.
  1. No trackbacks yet.

Leave a comment