# Operation Versioning

> How Easyparser versions operation responses, how to select a version with operation_version, and which operations have more than one version.

Source: https://docs.easyparser.com/essentials/operation-versioning

Easyparser versions each operation's response structure separately. You choose the version with the optional `operation_version` request parameter, so you can test and adopt a new response structure before it becomes the default.

## How versioning works

Operations change over time: fields are added, restructured or removed. When an operation's response structure changes, the new structure is released as a new version of that operation, so existing integrations keep working until they switch. Version numbers are integers and are defined per operation: one operation can have versions `1` and `2` while another has only one version.

At any time, an operation has at most two active versions:

- **Live:** the default version. You receive it when you do not send `operation_version`.
- **Beta:** the upcoming version. It is ready for production use and becomes the Live version on an announced date. You receive it only when you send its version number.

Live and Beta are labels, not fixed numbers. When a Beta version is promoted, it becomes the new Live version, and the next change to that operation is released as a new Beta with a higher version number.

## Current operation versions

Best Sellers Rank is currently the only versioned operation. All other operations have a single version and do not need `operation_version`.

| Operation | Code | Versions | Live version | Migration guide |
|---|---|---|---|---|
| Best Sellers Rank | `BEST_SELLERS_RANK` | `1`, `2` | `2` (since November 1, 2026) | [Migrating from version 1 to version 2](/real-time-integration/best-sellers-rank/response#migrating-from-version-1-to-version-2) |

Since November 1, 2026, version `2` is the Live version of Best Sellers Rank: requests without `operation_version` receive it. Version `1` is the legacy response structure; it stays documented on the response page to help you migrate. Both versions cost 1 credit per request (see [Credit Consumption](/essentials/credit-consumption)).

> **INFO:** Version `2` of Best Sellers Rank returns the main category and subcategory ranks and responds faster. It does not include price, currency or review data. The [response page](/real-time-integration/best-sellers-rank/response) documents both structures.

## Selecting a version

`operation_version` is an optional parameter in both the Real-Time API and the Bulk API. You send it together with the other parameters of the operation.

| Parameter | Type | Required | Description |
|---|---|---|---|
| `operation_version` | integer | No | Response version to return for a versioned operation. Default: the current Live version. Allowed: `1`, `2` (`BEST_SELLERS_RANK` only). |

This Real-Time API request pins version `2` of Best Sellers Rank:

**cURL**

```bash
curl --get "https://realtime.easyparser.com/v1/request" \
  --data-urlencode "api_key=YOUR_API_KEY" \
  --data-urlencode "platform=AMZ" \
  --data-urlencode "operation=BEST_SELLERS_RANK" \
  --data-urlencode "domain=.com" \
  --data-urlencode "asin=B0CJB6V2L5" \
  --data-urlencode "operation_version=2"
```

**Python**

```python
import requests

params = {
    "api_key": "YOUR_API_KEY",
    "platform": "AMZ",
    "operation": "BEST_SELLERS_RANK",
    "domain": ".com",
    "asin": "B0CJB6V2L5",
    "operation_version": "2",
}

response = requests.get("https://realtime.easyparser.com/v1/request", params=params)
print(response.json())
```

**Node.js**

```javascript
const params = new URLSearchParams({
  api_key: "YOUR_API_KEY",
  platform: "AMZ",
  operation: "BEST_SELLERS_RANK",
  domain: ".com",
  asin: "B0CJB6V2L5",
  operation_version: "2",
});

const response = await fetch(`https://realtime.easyparser.com/v1/request?${params}`);
const data = await response.json();
console.log(data);
```

**HTTP**

```http
GET /v1/request?api_key=YOUR_API_KEY&platform=AMZ&operation=BEST_SELLERS_RANK&domain=.com&asin=B0CJB6V2L5&operation_version=2 HTTP/1.1
Host: realtime.easyparser.com
```

**PHP**

```php
<?php
$params = [
    'api_key' => 'YOUR_API_KEY',
    'platform' => 'AMZ',
    'operation' => 'BEST_SELLERS_RANK',
    'domain' => '.com',
    'asin' => 'B0CJB6V2L5',
    'operation_version' => '2',
];

$url = 'https://realtime.easyparser.com/v1/request?' . http_build_query($params);
$response = file_get_contents($url);
$data = json_decode($response, true);
print_r($data);
```

**Go**

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
)

func main() {
	params := url.Values{}
	params.Add("api_key", "YOUR_API_KEY")
	params.Add("platform", "AMZ")
	params.Add("operation", "BEST_SELLERS_RANK")
	params.Add("domain", ".com")
	params.Add("asin", "B0CJB6V2L5")
	params.Add("operation_version", "2")

	resp, err := http.Get("https://realtime.easyparser.com/v1/request?" + params.Encode())
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	fmt.Println(string(body))
}
```

**C#**

```csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;

var parameters = new Dictionary<string, string>
{
    ["api_key"] = "YOUR_API_KEY",
    ["platform"] = "AMZ",
    ["operation"] = "BEST_SELLERS_RANK",
    ["domain"] = ".com",
    ["asin"] = "B0CJB6V2L5",
    ["operation_version"] = "2",
};

var query = string.Join("&", parameters.Select(p =>
    $"{Uri.EscapeDataString(p.Key)}={Uri.EscapeDataString(p.Value)}"));

using var client = new HttpClient();
var response = await client.GetStringAsync($"https://realtime.easyparser.com/v1/request?{query}");
Console.WriteLine(response);
```

**Java**

```java
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class EasyparserRequest {
    public static void main(String[] args) throws Exception {
        Map<String, String> params = new LinkedHashMap<>();
        params.put("api_key", "YOUR_API_KEY");
        params.put("platform", "AMZ");
        params.put("operation", "BEST_SELLERS_RANK");
        params.put("domain", ".com");
        params.put("asin", "B0CJB6V2L5");
        params.put("operation_version", "2");

        String query = params.entrySet().stream()
            .map(e -> URLEncoder.encode(e.getKey(), StandardCharsets.UTF_8) + "="
                + URLEncoder.encode(e.getValue(), StandardCharsets.UTF_8))
            .collect(Collectors.joining("&"));

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://realtime.easyparser.com/v1/request?" + query))
            .GET()
            .build();

        HttpResponse<String> response = HttpClient.newHttpClient()
            .send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println(response.body());
    }
}
```

Bulk API jobs also accept `operation_version`. Send it at the root of each group, next to `operation`, not inside `payload`. See [Bulk Service Request](/bulk-integration/bulk-service-request) for the request body format.

## Confirming the applied version

The response echoes the version that was applied in `request_parameters.operation_version`. The operation itself is echoed as `type`.

```json
"request_parameters": {
    "asin": "B0CJB6V2L5",
    "type": "BEST_SELLERS_RANK",
    "operation_version": 2
}
```

See the [response envelope](/real-time-integration/overview#response-envelope) for the other `request_parameters` fields.

## Version lifecycle

A response structure change goes through three stages:

1. **Beta release:** the new structure is released as the Beta version, and the date it becomes Live is announced. Requests without `operation_version` keep receiving the Live version.
2. **Transition period:** you test the Beta version by sending its version number and update your integration using the operation's migration guide.
3. **Promotion:** on the announced date, the Beta version becomes the new Live version. From then on, every request to the operation returns the new Live version, including requests that send an older version number.

> **WARNING:** After a Beta version is promoted, older versions are no longer returned. Make sure your integration works with the Beta version before its promotion date.

### Best practices

- **Switch early:** start sending the Beta version number as soon as a Beta is released, so your integration is already compatible on the promotion date.
- **Pin the version you built for:** send the version number explicitly instead of relying on the default. Every request then states the response structure your code expects.
- **Check the echo:** read `request_parameters.operation_version` in the response to confirm which version was applied.

## Unsupported version values

If you send a version number that does not exist for the operation, the request fails with this error:

```json
{"error": "[!] The operation_version is not supported for this operation."}
```

## Related

- [Best Sellers Rank request](/real-time-integration/best-sellers-rank/request)
- [Best Sellers Rank response](/real-time-integration/best-sellers-rank/response)
- [Common Request Fields](/real-time-integration/common-required-request-fields)
- [Bulk Service Request](/bulk-integration/bulk-service-request)
- [Credit Consumption](/essentials/credit-consumption)
