# V4 API Implementation Guide

**Last Updated:** February 2026  
**API Version:** v4

## Overview

The V4 API is an enhanced version of our vehicle advertising API that adds support for four additional vehicle categories with full field specifications. This guide will help you integrate with the V4 API to create, update, and manage vehicle ads.

## What's New in V4?

### Re-enabled Categories

V4 API adds support for four vehicle categories as full registered vehicles:

- 🛵 **Moped** (category_id: `1121`)
- 🚐 **Camper** (category_id: `1102`)
- 🏕️ **Caravan** (category_id: `1101`)
- 🪝 **Trailer** (category_id: `1045`)

These categories now support the same rich vehicle data as Cars, Motorcycles, and other vehicles (brand, model, mileage, equipment, etc.).

### Full Field Support

All fields available in the Blocket admin interface are now accessible via the API for these categories.

## Getting Started

### Base URL

```
Production: https://api.blocket.se/pro-import-api
```

### Authentication

All endpoints require authentication using the `X-Auth-Token` header:

```bash
curl -H "X-Auth-Token: YOUR_API_TOKEN" \
     https://api.blocket.se/pro-import-api/v4/ad
```

Contact Blocket to obtain your API token.

### API Endpoints

**V4 Endpoints:**
```
POST   /v4/ad                 - Create new ad
GET    /v4/ad                 - List all ads
GET    /v4/ad/{source_id}     - Get specific ad
PUT    /v4/ad/{source_id}     - Update ad (complete replacement)
PATCH  /v4/ad/{source_id}     - Partial update
DELETE /v4/ad/{source_id}     - Delete ad
GET    /v4/ad/{source_id}/log - Get ad activity logs
```

**Special Endpoint:**
```
POST   /v4/ad/{source_id}/migrate - Migrate V3 ad to V4 (see Migration Guide)
```

## Supported Categories

### All Categories

The V4 API supports all vehicle categories:

| Category | ID | V4 Support               |
|----------|-------|--------------------------|
| 🚗 Car | 1020 | ✅ No changes |
| 🚛 Transport | 1021 | ✅ No changes           |
| 🏍️ Motorcycle | 1140 | ✅ No changes           |
| 🛵 Moped | 1121 | ✨ **NEW in V4**          |
| 🛷 Snowmobile | 1180 | ✅ No changes           |
| 🏎️ ATV | 1143 | ✅ No changes           |
| 🚐 Camper | 1102 | ✨ **NEW in V4**          |
| 🏕️ Caravan | 1101 | ✨ **NEW in V4**          |
| 🪝 Trailer | 1045 | ✨ **NEW in V4**          |
| 🚤 Motor Boat | 1061 | ✅ No changes           |
| ⛵ Sail Boat | 1062 | ✅ No changes           |
| 🦌 Hunting | 6141 | ✅ No changes           |

## Creating Ads

### Basic Structure

All ads require these core fields:

```json
{
  "source_id": "string",        // Your unique identifier
  "dealer_code": "string",      // Your dealer code
  "category_id": "string",      // See table above
  "body": "string",             // Ad description
  "price": [                    // Price information
    {
      "type": "list",           // or "reduced", "monthly", "call"
      "amount": 100000,         // Price in minor units (öre)
      "currency": "SEK"
    }
  ],
  "visible": true,              // Publish immediately (true/false)
  "location": {                 // Ad location
    "longitude": 18.0686,
    "latitude": 59.3293
  },
  "category_fields": {          // Category-specific fields
    // See category examples below
  }
}
```

### Example: Create Moped Ad

```bash
curl -X POST https://pro-import-api.blocket.se/v4/ad \
  -H "X-Auth-Token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "source_id": "moped-001",
  "dealer_code": "YOUR_DEALER_CODE",
  "category_id": "1121",
  "body": "Excellent condition Yamaha Aerox moped, well maintained",
  "price": [{
    "type": "list",
    "amount": 35000,
    "currency": "SEK"
  }],
  "visible": true,
  "location": {
    "longitude": 18.0686,
    "latitude": 59.3293
  },
  "category_fields": {
    "body_type": "moped",
    "brand": "yamaha",
    "model": "aerox",
    "model_year": 2020,
    "registration_number": "ABC123",
    "condition": {
      "mileage": {
        "unit": "km",
        "value": 5000
      },
      "is_new_vehicle": false
    },
    "powertrain": {
      "transmission": "automatic",
      "fuels": ["gasoline"]
    }
  }
}'
```

### Example: Create Camper Ad

```json
{
  "source_id": "camper-001",
  "dealer_code": "YOUR_DEALER_CODE",
  "category_id": "1102",
  "body": "Spacious Mercedes camper with 4 beds and full kitchen",
  "price": [{
    "type": "list",
    "amount": 450000,
    "currency": "SEK"
  }],
  "visible": true,
  "location": {
    "longitude": 18.0686,
    "latitude": 59.3293
  },
  "category_fields": {
    "body_type": "integrated",
    "brand": "mercedes-benz",
    "model": "sprinter",
    "model_year": 2019,
    "registration_number": "DEF456",
    "condition": {
      "mileage": {
        "unit": "km",
        "value": 50000
      }
    },
    "physics": {
      "gross_weight": {
        "unit": "kg",
        "value": 3500
      },
      "length": {
        "unit": "m",
        "value": 7.5
      },
      "number_of_beds": 4
    },
    "powertrain": {
      "transmission": "manual",
      "fuels": ["diesel"]
    }
  }
}
```

## Updating Ads

### Full Update (PUT)

Replace entire ad with new data. All fields required:

```bash
curl -X PUT https://pro-import-api.blocket.se/v4/ad/moped-001 \
  -H "X-Auth-Token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ /* complete ad payload */ }'
```

### Partial Update (PATCH)

Update specific fields only:

```bash
curl -X PATCH https://pro-import-api.blocket.se/v4/ad/moped-001 \
  -H "X-Auth-Token: YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "price": [{
    "type": "reduced",
    "amount": 32000,
    "currency": "SEK"
  }]
}'
```

## Images and Videos

### Adding Images

```json
{
  "image_urls": [
    "https://example.com/image1.jpg",
    "https://example.com/image2.jpg"
  ]
}
```

**Requirements:**
- HTTPS URLs only
- JPEG or PNG format
- Maximum 20 images per ad
- Recommended size: 1024x768 or larger

### Adding Videos

```json
{
  "video_url": "https://www.youtube.com/watch?v=VIDEO_ID"
}
```

**Supported platforms:**
- YouTube
- Vimeo

## Price Types

### Available Price Types

```json
{
  "price": [
    {
      "type": "list",          // Regular list price
      "amount": 100000,
      "currency": "SEK"
    }
  ]
}
```

**Price types:**
- `list` - Regular list price
- `reduced` - Reduced/sale price
- `monthly` - Monthly payment
- `call` - Call for price (amount: 0)

**Note:** Amount is in minor currency units (öre for SEK):
- 100000 öre = 1000 SEK

## Error Handling

### Common Error Responses

**400 Bad Request** - Validation error:
```json
{
  "category_fields": {
    "brand": ["This field is required."]
  }
}
```

**401 Unauthorized** - Invalid or missing token:
```json
{
  "detail": "Authentication credentials were not provided."
}
```

**404 Not Found** - Ad not found:
```json
{
  "detail": "Not found."
}
```

**409 Conflict** - Duplicate source_id:
```json
{
  "source_id": ["Ad with this source_id already exists."]
}
```

## Field Reference

### Common Fields

All categories support these common fields:

- `body_type` - Vehicle body type (varies by category)
- `brand` - Vehicle brand (e.g., "volvo", "yamaha")
- `model` - Vehicle model (e.g., "v60", "aerox")
- `model_year` - Manufacturing year (integer)
- `registration_number` - Vehicle registration number

### Condition Fields

```json
{
  "condition": {
    "mileage": {
      "unit": "km",    // or "mil"
      "value": 50000
    },
    "is_new_vehicle": false
  }
}
```

### Powertrain Fields

```json
{
  "powertrain": {
    "transmission": "manual",    // or "automatic"
    "fuels": ["diesel"],         // "gasoline", "electric", "hybrid"
    "power": {
      "unit": "hp",              // or "kw"
      "value": 150
    }
  }
}
```

## Best Practices

### 1. Use Unique source_id

```json
{
  "source_id": "dealer123-vehicle456"  // Unique per ad
}
```

### 2. Handle Errors Gracefully

```python
try:
    response = create_ad(ad_data)
except ValidationError as e:
    log_error(e.errors)
    # Fix validation issues and retry
except AuthError as e:
    # Refresh token and retry
```

### 3. Batch Operations

For multiple ads, use async/parallel requests:

```python
import asyncio

ads = [ad1, ad2, ad3]
results = await asyncio.gather(*[create_ad(ad) for ad in ads])
```

### 4. Monitor Ad Status

Use the logs endpoint to track ad processing:

```bash
GET /v4/ad/{source_id}/log
```

## Rate Limiting

- No hard rate limits currently enforced
- Recommended: Max 10 requests/second
- Use batch operations for bulk updates

## Support

### Getting Help

1. **API Documentation:** [Swagger UI](swagger-ui/)
2. **Field Specifications:** [Re-enabled Categories Guide](v4-re-enabled-categories)
3. **Migration Guide:** [Backward Compatibility Guide](v4-backward-compatibility)
4. **Technical Support:** Contact your Blocket representative

### Useful Resources

- **Swagger UI:** Interactive API documentation
- **Postman Collection:** Available on request
- **Test Environment:** Use dev environment for testing

## Changelog

### V4 (2026-02)
- ✨ Added Moped (1121) with full vehicle data
- ✨ Added Camper (1102) with physics and powertrain
- ✨ Added Caravan (1101) with physics specifications
- ✨ Added Trailer (1045) with cargo support
- 🔄 Migration endpoint for V3→V4 upgrades

### V3 (Previous)
- All other categories supported
- Base functionality

---

**Questions?** Contact your Blocket representative or check the [Swagger documentation](swagger-ui/).
