# V4 Migration Guide

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

## Overview

This guide explains how to migrate your existing V3 ads to the new V4 API, which adds support for four additional vehicle categories with enhanced field specifications.

## Should I Migrate?

### If you're using these categories: Moped, Camper, Caravan, or Trailer

**You should migrate** to V4 to take advantage of full vehicle data support. V4 allows you to specify detailed information (brand, model, mileage, equipment) for these categories.

**Benefits:**
- ✅ Better ad quality with detailed specifications
- ✅ Improved search visibility
- ✅ Same rich features as Cars and Motorcycles
- ✅ Future-proof your integration

### If you're using other categories (Car, Motorcycle, etc.)

**Migration is optional**. These categories work identically in both V3 and V4. However, we recommend migrating to V4 as it's the current version.

**Benefits:**
- ✅ Access to latest features
- ✅ Simplified codebase (one API version)
- ✅ Future enhancements will be V4-first

## Migration Strategies

### Strategy 1: Gradual Migration (Recommended)

Migrate your integration gradually, one category or feature at a time.

**Steps:**
1. Start using `/v4/ad` endpoints for new ads
2. Keep existing V3 ads unchanged (they continue to work)
3. Migrate existing ads when convenient using the migration endpoint
4. Eventually phase out V3 endpoints from your code

**Advantages:**
- ✅ Low risk - test thoroughly before full rollout
- ✅ No downtime
- ✅ Easy rollback if issues arise

### Strategy 2: Big Bang Migration

Switch all integrations to V4 at once.

**Steps:**
1. Update all code to use `/v4/ad` endpoints
2. Migrate all existing V3 ads to V4
3. Deploy new code

**Advantages:**
- ✅ Clean cutover
- ✅ Simplified codebase immediately

**Disadvantages:**
- ❌ Higher risk
- ❌ Requires more thorough testing

## Migrating Existing Ads

### Compatible Categories (Car, Motorcycle, etc.)

For most categories, migration is **automatic** when you update ads via V4 endpoints.

**Example - Automatic Migration:**
```bash
# Update existing V3 car ad via V4 endpoint
PATCH /v4/ad/car-123
{
  "price": [{"type": "reduced", "amount": 180000, "currency": "SEK"}]
}

# Result: Ad is now V4 (automatic conversion)
```

✅ **What Happens:**
- Ad updates successfully
- `api_version` automatically changes from "v3" to "v4"
- No schema changes needed (V3 and V4 use same fields)

### Incompatible Categories (Moped, Camper, Caravan, Trailer)

For these categories, you have **two migration options**:

#### Option A: Use Migration Endpoint (Recommended)

Preserves ad ID and converts in-place.

**Example:**
```bash
POST /v4/ad/moped-123/migrate
{
  "source_id": "moped-123",
  "dealer_code": "YOUR_CODE",
  "category_id": "1121",
  "body": "Migrated to V4 with full details",
  "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}
    },
    "powertrain": {
      "transmission": "automatic",
      "fuels": ["gasoline"]
    }
  }
}
```

✅ **Advantages:**
- Same ad ID preserved
- Ad history maintained
- Single API call

❌ **Requirements:**
- Must provide complete V4 payload
- Need to gather vehicle details if not already available

#### Option B: DELETE + CREATE

Delete old ad and create new one.

**Example:**
```bash
# Step 1: Delete V3 ad
DELETE /v4/ad/moped-123

# Step 2: Create new V4 ad (can reuse same source_id)
POST /v4/ad
{
  "source_id": "moped-123",  // Same source_id OK
  "dealer_code": "YOUR_CODE",
  "category_id": "1121",
  "category_fields": { /* V4 fields */ }
}
```

✅ **Advantages:**
- Simple workflow
- Can reuse same `source_id`

❌ **Disadvantages:**
- New ad ID (different internal ID)
- Ad history lost

## Error Handling During Migration

### Error: Cannot Update V3 Incompatible Ad

If you try to PATCH/PUT a V3 Moped/Camper/Caravan/Trailer ad:

**Request:**
```bash
PATCH /v4/ad/moped-123
{"body": "Updated description"}
```

**Response (400 Bad Request):**
```json
{
  "error": "incompatible_api_version",
  "message": "Cannot update V3 legacy ad for Moped via V4 endpoint",
  "migration_options": [
    {
      "method": "DELETE + CREATE",
      "steps": [
        "1. GET /v4/ad/{source_id} (optional)",
        "2. DELETE /v4/ad/{source_id}",
        "3. POST /v4/ad (with V4 payload)"
      ]
    },
    {
      "method": "MIGRATE endpoint",
      "steps": ["POST /v4/ad/{source_id}/migrate"]
    }
  ]
}
```

**Solution:** Use one of the migration options provided in the error response.

### Error: Ad Already V4

If you try to migrate an ad that's already V4:

**Response (400 Bad Request):**
```json
{
  "error": "ad_already_v4",
  "message": "This ad is already using V4 schema",
  "suggestion": "Use PATCH /v4/ad/{source_id} to update this ad"
}
```

**Solution:** Use normal PATCH/PUT endpoints instead of migrate.

## Migration Checklist

### Before Migration

- [ ] Review V4 API documentation
- [ ] Test in development environment
- [ ] Identify which ads need migration
- [ ] Gather vehicle details for Moped/Camper/Caravan/Trailer ads
- [ ] Update your integration code to use `/v4/ad` endpoints
- [ ] Test error handling

### During Migration

- [ ] Start with low-volume categories
- [ ] Monitor API responses for errors
- [ ] Verify ads appear correctly on Blocket
- [ ] Check ad logs using `GET /v4/ad/{source_id}/log`

### After Migration

- [ ] Verify all ads migrated successfully
- [ ] Update internal documentation
- [ ] Remove V3 endpoint usage from code
- [ ] Monitor for any issues

## Code Examples

### Python Example - Migrate All Ads

```python
import requests

API_BASE = "https://pro-import-api.blocket.se"
TOKEN = "YOUR_API_TOKEN"
HEADERS = {"X-Auth-Token": TOKEN}

def get_all_ads():
    """Get all current ads"""
    response = requests.get(f"{API_BASE}/v4/ad", headers=HEADERS)
    return response.json()

def migrate_ad(source_id, v4_payload):
    """Migrate a single ad to V4"""
    url = f"{API_BASE}/v4/ad/{source_id}/migrate"
    response = requests.post(url, json=v4_payload, headers=HEADERS)
    return response.json()

# Get all ads
ads = get_all_ads()

# Filter V3 ads in incompatible categories
incompatible_categories = ["1121", "1102", "1101", "1045"]
v3_incompatible_ads = [
    ad for ad in ads 
    if ad.get("api_version") == "v3" 
    and ad.get("category_id") in incompatible_categories
]

print(f"Found {len(v3_incompatible_ads)} ads to migrate")

# Migrate each ad
for ad in v3_incompatible_ads:
    source_id = ad["source_id"]
    
    # Build V4 payload (add required fields)
    v4_payload = {
        **ad,  # Start with existing data
        "category_fields": {
            # Add required V4 fields here
            "body_type": "moped",  # Example
            "brand": "yamaha",
            "model": "aerox",
            # ... more fields
        }
    }
    
    try:
        result = migrate_ad(source_id, v4_payload)
        print(f"✅ Migrated {source_id}")
    except Exception as e:
        print(f"❌ Failed to migrate {source_id}: {e}")
```

### JavaScript Example - Auto-Migration Check

```javascript
const API_BASE = "https://pro-import-api.blocket.se";
const TOKEN = "YOUR_API_TOKEN";

async function updateAd(sourceId, updates) {
  const url = `${API_BASE}/v4/ad/${sourceId}`;
  const response = await fetch(url, {
    method: "PATCH",
    headers: {
      "X-Auth-Token": TOKEN,
      "Content-Type": "application/json"
    },
    body: JSON.stringify(updates)
  });

  if (!response.ok) {
    const error = await response.json();
    
    // Check if migration needed
    if (error.error === "incompatible_api_version") {
      console.log(`Ad ${sourceId} requires migration`);
      console.log("Migration options:", error.migration_options);
      return { needsMigration: true, error };
    }
    
    throw new Error(`Update failed: ${JSON.stringify(error)}`);
  }

  return await response.json();
}

// Usage
try {
  const result = await updateAd("moped-123", {
    price: [{ type: "reduced", amount: 32000, currency: "SEK" }]
  });
  
  if (result.needsMigration) {
    console.log("Please migrate this ad using the migration endpoint");
  } else {
    console.log("Ad updated successfully");
  }
} catch (error) {
  console.error("Error:", error);
}
```

## FAQ

### Q: Do I need to migrate all ads at once?
**A:** No. V3 ads continue to work. Migrate at your own pace.

### Q: Can I still use V3 endpoints?
**A:** Yes, V3 endpoints remain available. However, new features will be V4-only.

### Q: What happens if I don't migrate?
**A:** Existing V3 ads continue to work as before. You won't have access to V4-only features for Moped/Camper/Caravan/Trailer categories.

### Q: Can I read V3 ads using V4 endpoints?
**A:** Yes! `GET /v4/ad` returns both V3 and V4 ads.

### Q: Will V3 be deprecated?
**A:** V3 endpoints will remain available for the foreseeable future. You'll be notified well in advance of any deprecation.

### Q: Do I need to change my authentication?
**A:** No. The same API token works for both V3 and V4.

### Q: What if migration fails?
**A:** Check the error message for details. Common issues:
- Missing required fields
- Invalid field values
- Network timeouts

## Support

Need help with migration?

1. **Check Documentation:**
   - [Implementation Guide](v4-implementation-guide)
   - [Re-enabled Categories](v4-re-enabled-categories)
   - [Swagger UI](swagger-ui/)

2. **Contact Support:**
   - Reach out to your Blocket representative
   - Provide specific error messages and ad IDs

---

**Ready to Migrate?** Start with the [Implementation Guide](v4-implementation-guide) or test in the development environment first.
