Archive
How to Integrate the RegCheck Vehicle Lookup #API with #OpenAI Actions
In today’s AI-driven world, connecting specialized APIs to large language models opens up powerful possibilities. One particularly useful integration is connecting vehicle registration lookup services to OpenAI’s custom GPTs through Actions. In this tutorial, we’ll walk through how to integrate the RegCheck API with OpenAI Actions, enabling your custom GPT to look up vehicle information from over 30 countries.
What is RegCheck?
RegCheck is a comprehensive vehicle data API that provides detailed information about vehicles based on their registration numbers (license plates). With support for countries including the UK, USA, Australia, and most of Europe, it’s an invaluable tool for automotive businesses, insurance companies, and vehicle marketplace platforms.
Why Integrate with OpenAI Actions?
OpenAI Actions allow custom GPTs to interact with external APIs, extending their capabilities beyond text generation. By integrating RegCheck, you can create a GPT assistant that:
- Instantly looks up vehicle specifications for customers
- Provides insurance quotes based on real vehicle data
- Assists with vehicle valuations and sales listings
- Answers detailed questions about specific vehicles
Prerequisites
Before you begin, you’ll need:
- An OpenAI Plus subscription (for creating custom GPTs)
- A RegCheck API account with credentials
- Basic familiarity with OpenAPI specifications
Step-by-Step Integration Guide
Step 1: Create Your Custom GPT
Navigate to OpenAI’s platform and create a new custom GPT. Give it a name like “Vehicle Lookup Assistant” and configure its instructions to handle vehicle-related queries.
Step 2: Add the OpenAPI Schema
In your GPT configuration, navigate to the “Actions” section and add the following OpenAPI specification:
yaml
openapi: 3.0.0
info:
title: RegCheck Vehicle Lookup API
version: 1.0.0
description: API for looking up vehicle registration information across multiple countries
servers:
- url: https://www.regcheck.org.uk/api/json.aspx
paths:
/Check/{registration}:
get:
operationId: checkUKVehicle
summary: Get details for a vehicle in the UK
parameters:
- name: registration
in: path
required: true
schema:
type: string
description: UK vehicle registration number
responses:
'200':
description: Successful response
content:
application/json:
schema:
type: object
/CheckSpain/{registration}:
get:
operationId: checkSpainVehicle
summary: Get details for a vehicle in Spain
parameters:
- name: registration
in: path
required: true
schema:
type: string
description: Spanish vehicle registration number
responses:
'200':
description: Successful response
content:
application/json:
schema:
type: object
/CheckFrance/{registration}:
get:
operationId: checkFranceVehicle
summary: Get details for a vehicle in France
parameters:
- name: registration
in: path
required: true
schema:
type: string
description: French vehicle registration number
responses:
'200':
description: Successful response
content:
application/json:
schema:
type: object
/VinCheck/{vin}:
get:
operationId: checkVehicleByVin
summary: Get details for a vehicle by VIN number
parameters:
- name: vin
in: path
required: true
schema:
type: string
description: Vehicle Identification Number
responses:
'200':
description: Successful response
content:
application/json:
schema:
type: object
Note: You can expand this schema to include additional endpoints for other countries as needed. The RegCheck API supports over 30 countries.
Step 3: Configure Authentication
- In the Authentication section, select Basic authentication
- Enter your RegCheck API username
- Enter your RegCheck API password
- OpenAI will securely encrypt and store these credentials
The authentication header will be automatically included in all API requests made by your GPT.
Step 4: Test Your Integration
Use the built-in test feature in the Actions panel to verify the connection:
- Select the
checkUKVehicleoperation - Enter a test registration like
YYO7XHH - Click “Test” to see the response
You should receive a JSON response with vehicle details including make, model, year, engine size, and more.
Step 5: Configure GPT Instructions
Update your GPT’s instructions to effectively use the new Actions:
You are a vehicle information assistant. When users provide a vehicle
registration number, use the appropriate CheckVehicle action based on
the country. Present the information in a clear, user-friendly format.
Always ask which country the registration is from if not specified.
Provide helpful context about the vehicle data returned.
Example Use Cases
Once integrated, your GPT can handle queries like:
User: “What can you tell me about UK registration YYO7XHH?”
GPT: [Calls checkUKVehicle action] “This is a 2007 Peugeot 307 X-line with a 1.4L petrol engine. It’s a 5-door manual transmission vehicle with right-hand drive…”
User: “Look up Spanish plate 0075LTJ”
GPT: [Calls checkSpainVehicle action] “Here’s the information for that Spanish vehicle…”
Best Practices and Considerations
API Limitations
- The RegCheck API is currently in BETA and may change without notice
- Consider implementing error handling in your GPT instructions
- Be aware of rate limits on your API account
Privacy and Security
- Never expose API credentials in your GPT’s instructions or responses
- Inform users that vehicle lookups are being performed
- Comply with data protection regulations in your jurisdiction
Optimizing Performance
- Cache frequently requested vehicle information where appropriate
- Use the most specific endpoint (e.g., CheckSpain vs. generic Check)
- Consider implementing fallback behavior for failed API calls
Expanding the Integration
The RegCheck API offers many more endpoints you can integrate:
- UKMOT: Access MOT test history for UK vehicles
- WheelSize: Get wheel and tire specifications
- CarSpecifications: Retrieve detailed specs by make/model/year
- Country-specific checks: Add support for Australia, USA, and 25+ other countries
Simply add these endpoints to your OpenAPI schema following the same pattern.
Troubleshooting Common Issues
Authentication Errors: Double-check your username and password are correct in the Authentication settings.
404 Not Found: Verify the registration format matches the country’s standard format.
Empty Responses: Some vehicles may not have complete data in the RegCheck database.
Conclusion
Integrating the RegCheck API with OpenAI Actions transforms a standard GPT into a powerful vehicle information assistant. Whether you’re building tools for automotive dealerships, insurance platforms, or customer service applications, this integration provides instant access to comprehensive vehicle data from around the world.
The combination of AI’s natural language understanding with RegCheck’s extensive vehicle database creates a seamless user experience that would have required significant custom development just a few years ago.
Ready to get started? Create your RegCheck account, set up your custom GPT, and start building your vehicle lookup assistant today!
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:
- Cars:
/CheckSpain– For passenger vehicles, vans, and trucks - 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
- Sign Up – Register for Spanish vehicle API access
- Verification – Complete business verification process
- Testing – Use sample registrations for development:
- Cars: “5428GXS” (Renault Megane from documentation)
- Motorcycles: Test with various Spanish motorcycle plates
- 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/
Fixing .NET 8 HttpClient Permission Denied Errors on Google Cloud Run
If you’re deploying a .NET 8 application to Google Cloud Run and encountering a mysterious NetworkInformationException (13): Permission denied error when making HTTP requests, you’re not alone. This is a known issue that stems from how .NET’s HttpClient interacts with Cloud Run’s restricted container environment.
The Problem
When your .NET application makes HTTP requests using HttpClient, you might see an error like this:
System.Net.NetworkInformation.NetworkInformationException (13): Permission denied
at System.Net.NetworkInformation.NetworkChange.CreateSocket()
at System.Net.NetworkInformation.NetworkChange.add_NetworkAddressChanged(NetworkAddressChangedEventHandler value)
at System.Net.Http.HttpConnectionPoolManager.StartMonitoringNetworkChanges()
This error occurs because .NET’s HttpClient attempts to monitor network changes and handle advanced HTTP features like HTTP/3 and Alt-Svc (Alternative Services). To do this, it tries to create network monitoring sockets, which requires permissions that Cloud Run containers don’t have by default.
Cloud Run’s security model intentionally restricts certain system-level operations to maintain isolation and security. While this is great for security, it conflicts with .NET’s network monitoring behavior.
Why Does This Happen?
The .NET runtime includes sophisticated connection pooling and HTTP version negotiation features. When a server responds with an Alt-Svc header (suggesting alternative protocols or endpoints), .NET tries to:
- Monitor network interface changes
- Adapt connection strategies based on network conditions
- Support HTTP/3 where available
These features require low-level network access that Cloud Run’s sandboxed environment doesn’t permit.
The Solution
Fortunately, there’s a straightforward fix. You need to disable the features that require elevated network permissions by setting two environment variables:
Environment.SetEnvironmentVariable("DOTNET_SYSTEM_NET_DISABLEIPV6", "1");
Environment.SetEnvironmentVariable("DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP3SUPPORT", "false");
Place these lines at the very top of your Program.cs file, before any HTTP client initialization or web application builder creation.
What These Variables Do
- DOTNET_SYSTEM_NET_DISABLEIPV6: Disables IPv6 support, which also disables the network change monitoring that requires socket creation.
- DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP3SUPPORT: Explicitly disables HTTP/3 support, preventing .NET from trying to negotiate HTTP/3 connections.
Alternative Approaches
Option 1: Set in Dockerfile
You can bake these settings into your container image:
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
# Disable network monitoring features
ENV DOTNET_SYSTEM_NET_DISABLEIPV6=1
ENV DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP3SUPPORT=false
COPY publish/ .
ENTRYPOINT ["dotnet", "YourApp.dll"]
Option 2: Set via Cloud Run Configuration
You can configure these as environment variables in your Cloud Run deployment:
gcloud run deploy your-service \
--image gcr.io/your-project/your-image \
--set-env-vars DOTNET_SYSTEM_NET_DISABLEIPV6=1,DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP3SUPPORT=false
Or through the Cloud Console when configuring your service’s environment variables.
Performance Impact
You might wonder if disabling these features affects performance. In practice:
- HTTP/3 isn’t widely used yet, and most services work perfectly fine with HTTP/2 or HTTP/1.1
- Network change monitoring is primarily useful for long-running desktop applications that move between networks (like a laptop switching from WiFi to cellular)
- In a Cloud Run container with a stable network environment, these features provide minimal benefit
The performance impact is negligible, and the tradeoff is well worth it for a working application.
Why It Works Locally But Fails in Cloud Run
This issue often surprises developers because their code works perfectly on their development machine. That’s because:
- Local development environments typically run with full system permissions
- Your local machine isn’t running in a restricted container
- Cloud Run’s security sandbox is much more restrictive than a typical development environment
This is a classic example of environment-specific behavior where security constraints in production expose issues that don’t appear during development.
Conclusion
The Permission denied error when using HttpClient in .NET 8 on Google Cloud Run is caused by the runtime’s attempt to use network monitoring features that aren’t available in Cloud Run’s restricted environment. The fix is simple: disable these features using environment variables.
This solution is officially recognized by the .NET team as the recommended workaround for containerized environments with restricted permissions, so you can use it with confidence in production.
Related Resources
Have you encountered other .NET deployment issues on Cloud Run? Feel free to share your experiences in the comments below.