autotrader-connect-api
Version:
Production-ready TypeScript wrapper for Auto Trader UK Connect APIs
844 lines (655 loc) โข 20.1 kB
Markdown
# autotrader-connect-api
[](https://www.npmjs.com/package/autotrader-connect-api)
[](https://github.com/your-org/autotrader-connect/actions)
[](https://codecov.io/gh/your-org/autotrader-connect)
[](https://www.typescriptlang.org/)
[](https://opensource.org/licenses/MIT)
A production-ready TypeScript wrapper for the Auto Trader UK Connect APIs. This package provides a comprehensive, type-safe interface to interact with AutoTrader's vehicle data, stock management, search, and other automotive services.
## Features
- ๐ **Production Ready**: Built with enterprise-grade error handling, retry logic, and rate limiting
- ๐ **Type Safe**: Full TypeScript support with comprehensive type definitions
- ๐ **Secure Authentication**: Automatic OAuth2 token management with refresh capabilities
- โก **Performance Optimized**: Built-in rate limiting and request batching
- ๐ก๏ธ **Robust Error Handling**: Comprehensive error types and retry strategies
- ๐ **Rich Data Models**: Extensive type definitions for all API responses
- ๐งช **Well Tested**: High test coverage with unit and integration tests
- ๐ **Comprehensive Documentation**: Full API documentation with examples
## Table of Contents
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Configuration](#configuration)
- [Authentication](#authentication)
- [API Modules](#api-modules)
- [Usage Examples](#usage-examples)
- [Error Handling](#error-handling)
- [Rate Limiting](#rate-limiting)
- [Testing](#testing)
- [Next.js Integration](#nextjs-integration)
- [Contributing](#contributing)
- [API Reference](#api-reference)
- [License](#license)
## Installation
```bash
npm install autotrader-connect-api
```
Or with yarn:
```bash
yarn add autotrader-connect-api
```
## Quick Start
```typescript
import { initializeClient, getVehicle, searchVehicles } from 'autotrader-connect-api';
// Initialize the client
const client = initializeClient({
apiKey: 'your-api-key',
apiSecret: 'your-api-secret',
baseURL: 'https://api.autotrader.co.uk', // optional
});
// Search for vehicles
const vehicles = await searchVehicles({
make: 'BMW',
model: '3 Series',
priceRange: { min: 15000, max: 30000 },
yearRange: { min: 2018 },
postcode: 'SW1A 1AA',
radius: 50,
});
console.log(`Found ${vehicles.data.length} vehicles`);
// Get a specific vehicle
const vehicle = await getVehicle('ABC123', 12345);
console.log(`Vehicle: ${vehicle.make} ${vehicle.model} - ยฃ${vehicle.price}`);
```
## ๐งช Sandbox Environment Support
The package includes comprehensive sandbox support for testing and development. The API automatically detects your environment and switches between sandbox and production endpoints.
### Environment Detection
- **Development**: `NODE_ENV=development` โ Uses sandbox automatically
- **Test**: `NODE_ENV=test` โ Uses sandbox automatically
- **Production**: `NODE_ENV=production` โ Uses production API
- **Manual Override**: `AT_USE_SANDBOX=true/false` โ Explicit control
### Environment Variables
```bash
# Production API
AT_BASE_URL=https://api.autotrader.co.uk
AT_API_KEY=your_production_key
AT_API_SECRET=your_production_secret
# Sandbox API
AT_SANDBOX_BASE_URL=https://sandbox-api.autotrader.co.uk
AT_SANDBOX_API_KEY=your_sandbox_key
AT_SANDBOX_API_SECRET=your_sandbox_secret
# Environment control
NODE_ENV=development
AT_USE_SANDBOX=true
```
### Quick Setup Methods
```typescript
import { quickSetup, setupSandbox, setupProduction } from 'autotrader-connect-api';
// 1. Automatic environment detection
const client = quickSetup(); // Uses sandbox in development, production otherwise
// 2. Force sandbox mode
const sandboxClient = setupSandbox(); // Always uses sandbox
// 3. Force production mode
const prodClient = setupProduction(); // Always uses production
// 4. Override environment detection
const testClient = quickSetup({
forceSandbox: true // Force sandbox regardless of NODE_ENV
});
```
### Explicit Configuration
```typescript
import { initializeClient } from 'autotrader-connect-api';
// Sandbox configuration
const sandboxClient = initializeClient({
apiKey: 'sandbox-key',
apiSecret: 'sandbox-secret',
baseURL: 'https://sandbox-api.autotrader.co.uk',
useSandbox: true,
debug: true // Helpful for development
});
// Production configuration
const prodClient = initializeClient({
apiKey: 'prod-key',
apiSecret: 'prod-secret',
baseURL: 'https://api.autotrader.co.uk',
useSandbox: false,
debug: false
});
```
### Testing Best Practices
```typescript
// In your test files
import { setupSandbox } from 'autotrader-connect-api';
describe('Vehicle API Tests', () => {
let client;
beforeAll(() => {
// Always use sandbox for tests
client = setupSandbox({
debug: true // See all API calls in test output
});
});
it('should search for vehicles', async () => {
const results = await searchVehicles({ make: 'BMW' });
expect(results.data).toBeDefined();
});
});
```
### Development Workflow
```typescript
// .env.development
NODE_ENV=development
AT_SANDBOX_API_KEY=your_dev_key
AT_SANDBOX_API_SECRET=your_dev_secret
AT_USE_SANDBOX=true
AT_DEBUG=true
// .env.production
NODE_ENV=production
AT_API_KEY=your_prod_key
AT_API_SECRET=your_prod_secret
AT_USE_SANDBOX=false
AT_DEBUG=false
```
### Sandbox Features
โ
Automatic environment detection
โ
Separate credentials for sandbox vs production
โ
Debug mode enabled by default in sandbox
โ
Same API interface as production
โ
Perfect for CI/CD testing pipelines
โ
No accidental production API calls during development
## ๐ข Advertiser ID Management
The package now includes comprehensive advertiser ID support for proper multi-tenant operations:
### Key Features
โ
**Consistent Advertiser Context**: Use `advertiserId` (number) throughout the API
โ
**Legacy Support**: Backward compatible with `dealerId` (string)
โ
**Advertiser-Scoped Clients**: Automatic advertiser context injection
โ
**Validation Utilities**: Verify advertiser IDs before API calls
โ
**Multi-Advertiser Support**: Manage multiple dealers in one application
โ
**Comprehensive Advertiser Management**: Full CRUD operations for advertiser data
### Quick Examples
```typescript
import {
getVehicle,
searchVehicles,
createAdvertiserClient,
getCurrentAdvertiser
} from 'autotrader-connect-api';
// Get vehicle with advertiser context
const vehicle = await getVehicle('ABC123', 12345);
console.log(`Vehicle from ${vehicle.advertiser.name}`);
// Search with advertiser filtering
const results = await searchVehicles({
make: 'BMW',
advertiserId: [12345, 67890], // Multiple advertisers
priceRange: { min: 15000, max: 30000 }
});
// Create advertiser-scoped client
const dealerClient = createAdvertiserClient(12345);
// All requests now include advertiser context automatically
// Get current advertiser information
const advertiser = await getCurrentAdvertiser();
console.log(`Logged in as: ${advertiser.name} (ID: ${advertiser.id})`);
```
For comprehensive examples, see [`advertiser-examples.md`](./advertiser-examples.md).
## Configuration
### Environment Variables
Create a `.env` file in your project root:
```bash
# Required
AT_API_KEY=your_autotrader_api_key
AT_API_SECRET=your_autotrader_api_secret
# Optional
AT_BASE_URL=https://api.autotrader.co.uk
AT_TIMEOUT=30000
AT_RATE_LIMIT_REQUESTS=100
AT_RATE_LIMIT_WINDOW=60000
AT_DEBUG=false
```
### Programmatic Configuration
```typescript
import { initializeClient } from 'autotrader-connect-api';
const client = initializeClient({
apiKey: process.env.AT_API_KEY!,
apiSecret: process.env.AT_API_SECRET!,
baseURL: 'https://api.autotrader.co.uk',
timeout: 30000,
maxRetries: 3,
rateLimitRequests: 100,
rateLimitWindow: 60000,
debug: false,
});
```
### Quick Setup (Environment-based)
```typescript
import { quickSetup } from 'autotrader-connect-api';
// Uses environment variables automatically
const client = quickSetup({
debug: process.env.NODE_ENV === 'development',
timeout: 30000,
});
```
## Authentication
The package handles OAuth2 authentication automatically:
```typescript
import { getToken, getAuthManager } from 'autotrader-connect-api';
// Get current token (automatically refreshes if needed)
const token = await getToken();
// Manual auth management
const authManager = getAuthManager();
const isAuthenticated = authManager.isAuthenticated();
const authState = authManager.getAuthState();
// Force token refresh
await authManager.refreshToken();
// Clear cached token
authManager.clearToken();
```
## API Modules
### Vehicles
```typescript
import {
getVehicle,
getVehicleById,
searchVehicles,
getFeaturedVehicles,
getSimilarVehicles,
getVehicleSpecifications
} from 'autotrader-connect-api';
// Get vehicle by registration and advertiser ID
const vehicle = await getVehicle('ABC123', 12345);
// Get vehicle by ID
const vehicle = await getVehicleById('vehicle-id');
// Search vehicles with comprehensive filters
const results = await searchVehicles({
make: ['BMW', 'Audi'],
bodyType: ['Hatchback', 'Saloon'],
fuelType: ['Petrol', 'Hybrid'],
priceRange: { min: 15000, max: 40000 },
yearRange: { min: 2018 },
mileageRange: { max: 50000 },
postcode: 'M1 1AA',
radius: 25,
sortBy: 'price',
sortOrder: 'asc',
});
// Get featured vehicles
const featured = await getFeaturedVehicles(10);
// Get similar vehicles
const similar = await getSimilarVehicles('vehicle-id', 5);
// Get detailed specifications
const specs = await getVehicleSpecifications('vehicle-id');
```
### Stock Management
```typescript
import {
searchStock,
createStock,
updateStock,
publishStock,
getStockStatistics
} from 'autotrader-connect-api';
// Search stock with filters
const stock = await searchStock({
status: ['Available', 'Reserved'],
make: 'BMW',
siteId: 'site-123',
minDaysInStock: 7,
sortBy: 'stockedDate',
});
// Create new stock item
const newStock = await createStock({
make: 'BMW',
model: '3 Series',
year: 2020,
mileage: 25000,
fuelType: 'Petrol',
transmission: 'Automatic',
bodyType: 'Saloon',
doors: 4,
seats: 5,
colour: 'Black',
retailPrice: 25000,
description: 'Excellent condition BMW 3 Series',
});
// Update stock item
const updated = await updateStock('stock-id', {
retailPrice: 24000,
status: 'Available',
});
// Publish stock to AutoTrader
const result = await publishStock(['stock-id-1', 'stock-id-2']);
// Get stock statistics
const stats = await getStockStatistics({
siteId: 'site-123',
dateFrom: '2024-01-01',
});
```
### Search & Discovery
```typescript
import {
searchVehicles,
quickSearch,
saveSearch,
compareVehicles,
getPopularSearches
} from 'autotrader-connect-api';
// Enhanced search with facets
const searchResults = await searchVehicles({
make: 'BMW',
priceRange: { min: 20000, max: 40000 },
includeFacets: true,
includeMarketInsights: true,
});
// Quick search for autocomplete
const quick = await quickSearch({
query: 'BMW 3 Series',
postcode: 'M1 1AA',
maxPrice: 30000,
limit: 5,
});
// Save search for alerts
const savedSearch = await saveSearch({
name: 'My BMW Search',
filters: { make: 'BMW', priceRange: { max: 30000 } },
alertSettings: {
enabled: true,
frequency: 'Daily',
email: 'user@example.com',
},
});
// Compare multiple vehicles
const comparison = await compareVehicles(['vehicle-1', 'vehicle-2', 'vehicle-3']);
// Get popular searches
const popular = await getPopularSearches('Make');
```
### Valuations
```typescript
import {
getValuation,
getQuickValuation,
getBatchValuations,
getHistoricalValuation
} from 'autotrader-connect-api';
// Get vehicle valuation
const valuation = await getValuation({
make: 'BMW',
model: '3 Series',
year: 2020,
mileage: 25000,
condition: 'Good',
postcode: 'M1 1AA',
});
// Quick valuation by registration
const quickVal = await getQuickValuation('ABC123', 25000, 'M1 1AA');
// Batch valuations
const batchResults = await getBatchValuations([
{ make: 'BMW', model: '3 Series', year: 2020, mileage: 25000 },
{ make: 'Audi', model: 'A4', year: 2019, mileage: 30000 },
]);
// Historical valuation data
const historical = await getHistoricalValuation({
make: 'BMW',
model: '3 Series',
year: 2020,
mileage: 25000,
}, '1y');
```
### Taxonomy
```typescript
import {
getVehicleMakes,
getVehicleModels,
getBodyTypes,
searchTaxonomy
} from 'autotrader-connect-api';
// Get all vehicle makes
const makes = await getVehicleMakes();
// Get models for a make
const models = await getVehicleModels('bmw');
// Get body types
const bodyTypes = await getBodyTypes();
// Search taxonomy
const results = await searchTaxonomy('BMW 3', 'all');
```
## Usage Examples
### Next.js API Route
```typescript
// pages/api/vehicles/search.ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { searchVehicles } from 'autotrader-connect-api';
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
try {
const { make, model, maxPrice } = req.query;
const vehicles = await searchVehicles({
make: make as string,
model: model as string,
priceRange: maxPrice ? { max: Number(maxPrice) } : undefined,
});
res.status(200).json(vehicles);
} catch (error) {
console.error('Search error:', error);
res.status(500).json({ error: 'Failed to search vehicles' });
}
}
```
### React Component with SWR
```typescript
// components/VehicleSearch.tsx
import useSWR from 'swr';
import { VehicleSearchParams } from 'autotrader-connect-api';
const fetcher = (url: string) => fetch(url).then(r => r.json());
export function VehicleSearch({ filters }: { filters: VehicleSearchParams }) {
const { data, error, isLoading } = useSWR(
`/api/vehicles/search?${new URLSearchParams(filters)}`,
fetcher
);
if (error) return <div>Error loading vehicles</div>;
if (isLoading) return <div>Loading...</div>;
return (
<div>
{data?.data?.map((vehicle: any) => (
<div key={vehicle.id}>
<h3>{vehicle.make} {vehicle.model}</h3>
<p>ยฃ{vehicle.price.toLocaleString()}</p>
</div>
))}
</div>
);
}
```
### Express.js Server
```typescript
import express from 'express';
import { quickSetup, searchVehicles } from 'autotrader-connect-api';
const app = express();
const client = quickSetup();
app.get('/api/vehicles', async (req, res) => {
try {
const vehicles = await searchVehicles(req.query);
res.json(vehicles);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(3000);
```
## Error Handling
The package provides comprehensive error handling:
```typescript
import { searchVehicles } from 'autotrader-connect-api';
try {
const vehicles = await searchVehicles({ make: 'BMW' });
} catch (error) {
if (error.status === 401) {
console.error('Authentication failed');
} else if (error.status === 429) {
console.error('Rate limit exceeded');
} else if (error.status >= 500) {
console.error('Server error');
} else {
console.error('Request failed:', error.message);
}
}
```
### Health Check
```typescript
import { healthCheck } from 'autotrader-connect-api';
const health = await healthCheck();
console.log('API Health:', health);
// {
// status: 'healthy',
// timestamp: '2024-01-01T12:00:00Z',
// version: '1.0.0',
// auth: true,
// latency: 145
// }
```
## Rate Limiting
The package includes built-in rate limiting:
```typescript
import { getClient } from 'autotrader-connect-api';
const client = getClient();
// Check rate limit status
const status = client.getRateLimitStatus();
console.log('Rate limit status:', status);
// {
// reservoir: 95, // requests remaining
// running: 2, // requests in progress
// queued: 0 // requests queued
// }
```
## Testing
Run the test suite:
```bash
# Run all tests
npm test
# Run tests in watch mode
npm run test:watch
# Run tests with coverage
npm run test:coverage
# Run linting
npm run lint
# Fix linting issues
npm run lint:fix
```
### Writing Tests
```typescript
import { getVehicle } from 'autotrader-connect-api';
// Mock the client for testing
jest.mock('autotrader-connect-api', () => ({
getVehicle: jest.fn(),
}));
test('should fetch vehicle data', async () => {
const mockVehicle = { id: '123', make: 'BMW', model: '3 Series' };
(getVehicle as jest.Mock).mockResolvedValue(mockVehicle);
const result = await getVehicle('ABC123', 12345);
expect(result).toEqual(mockVehicle);
});
```
## Next.js Integration
### App Router (Recommended)
```typescript
// app/api/vehicles/route.ts
import { searchVehicles } from 'autotrader-connect-api';
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
try {
const vehicles = await searchVehicles({
make: searchParams.get('make') || undefined,
model: searchParams.get('model') || undefined,
});
return Response.json(vehicles);
} catch (error) {
return Response.json(
{ error: 'Failed to search vehicles' },
{ status: 500 }
);
}
}
```
### Server Component
```typescript
// app/vehicles/page.tsx
import { searchVehicles } from 'autotrader-connect-api';
export default async function VehiclesPage() {
const vehicles = await searchVehicles({ make: 'BMW' });
return (
<div>
<h1>BMW Vehicles</h1>
{vehicles.data.map(vehicle => (
<div key={vehicle.id}>
<h3>{vehicle.make} {vehicle.model}</h3>
<p>ยฃ{vehicle.price.toLocaleString()}</p>
</div>
))}
</div>
);
}
```
## API Reference
For complete API documentation, see the [TypeDoc generated documentation](./docs).
### Core Types
```typescript
// Import types for use in your application
import type {
Vehicle,
VehicleSearchParams,
VehicleResponse,
StockItem,
SearchResponse,
ValuationResponse,
ApiResponse,
PaginatedResponse,
} from 'autotrader-connect-api';
```
## Building and Publishing
### Development
```bash
# Install dependencies
npm install
# Run in development mode
npm run dev
# Build the package
npm run build
# Generate documentation
npm run docs
```
### Publishing
```bash
# Version bump (patch, minor, or major)
npm version patch
# Build and test before publishing
npm run prepublishOnly
# Publish to NPM
npm publish
# Or publish with tag
npm publish --tag beta
```
### Automated Publishing
The package includes GitHub Actions for automated publishing:
1. Create a release tag: `git tag v1.0.1`
2. Push the tag: `git push origin v1.0.1`
3. GitHub Actions will automatically build, test, and publish
## Contributing
1. Fork the repository
2. Create a feature branch: `git checkout -b feature/your-feature`
3. Make your changes and add tests
4. Ensure tests pass: `npm test`
5. Commit your changes: `git commit -am 'Add your feature'`
6. Push to the branch: `git push origin feature/your-feature`
7. Submit a pull request
### Development Guidelines
- Follow the existing code style
- Add tests for new features
- Update documentation as needed
- Ensure all tests pass
- Follow semantic versioning
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Support
- ๐ง Email: support@your-org.com
- ๐ฌ Issues: [GitHub Issues](https://github.com/your-org/autotrader-connect/issues)
- ๐ Documentation: [API Docs](./docs)
## Changelog
See [CHANGELOG.md](CHANGELOG.md) for release history.
---
Made with โค๏ธ by [Your Organization](https://your-org.com)