Migrating to the new Published API
Choose your current API to see the specific migration steps
Please select your current API to display the appropriate migration guide:
The new Published API represents a significant evolution from the legacy Product Reviews API, designed to meet modern requirements:
This migration involves breaking changes that require code modifications. All existing integrations must be updated to work with the new API.
api-product-reviews.rr.skeepers.io/v1 to api.skeepers.io/verified-reviews/v1/publishedwebsite_id parameterref β product_variation_id)rate β review_rate)| Old API | New API | Action Required |
|---|---|---|
| No authentication required | OAuth2.0 with client credentials flow mandatory | Implement token-based authentication |
| Old API | New API |
|---|---|
https://api-product-reviews.rr.skeepers.io/v1 |
https://api.skeepers.io/verified-reviews/v1/published |
| Old Format | New Format |
|---|---|
{"data": {"product_ref": [...]}} |
[{...}, {...}] (array format) |
| Old Endpoint | New Endpoint | Purpose | Notes |
|---|---|---|---|
GET /websites/{website_id}/products/ratings |
GET /productsor GET /products/ratings |
Product ratings | Use /products for summaries with AI, /products/ratings for bulk operations |
GET /websites/{website_id}/products/reviews |
GET /products/reviews |
Individual reviews | Enhanced filtering and pagination |
| N/A | GET /brands/reviews |
New: Brand reviews | Access brand and shop-specific reviews |
| N/A | GET /brands |
New: Brand ratings | Brand rating summaries with historical data |
| Old Parameter | New Parameter | Location | Notes |
|---|---|---|---|
website_id (path) |
N/A | - | Handled via OAuth authentication |
ref |
product_variation_id |
Query | Primary product identifier |
rate |
review_rate |
Query | Rating filter (same functionality) |
limit |
limit |
Query | Same functionality (max 200) |
offset |
cursor |
Query | Changed: Cursor-based pagination |
sortBy |
sort |
Query | Enhanced field validation |
sortDirection |
desc |
Query | Specify descending fields |
// Old API - No authentication needed
fetch('https://api-product-reviews.rr.skeepers.io/v1/websites/123/products/reviews')
.then(response => response.json())
.then(data => {
// Handle response
});
// New API - OAuth2.0 authentication required
async function getOAuthToken() {
const response = await fetch('https://auth.skeepers.io/realms/skeepers/protocol/openid-connect/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'client_credentials',
client_id: 'your_client_id',
client_secret: 'your_client_secret',
scope: 'read'
})
});
const data = await response.json();
return data.access_token;
}
// Make authenticated request
const token = await getOAuthToken();
fetch('https://api.skeepers.io/verified-reviews/v1/published/products/reviews', {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(data => {
// Handle response
});
// Old API response structure
{
"data": {
"product1": [
{
"id": "50fcfe6c-3ef8-4c9f-a3db-46cf2af8bd6c",
"rate": 4,
"review": "This product is amazing!",
"product_ref": "product1"
// ... other fields
}
],
"product2": [
// reviews for product2...
]
}
}
// New API response structure
[
{
"review_id": "67d7b591-40a2-7ab4-1925-0b2db7753c90",
"review_rate": 4,
"review_content": "This product is amazing!",
"product_variation_id": "product1",
"author_firstname": "John",
"author_lastname": "Doe",
"is_verified": true,
"incentivization": "none",
"medias": [
{
"type": "IMAGE",
"small": "https://skeepers.io/image_small.png",
"medium": "https://skeepers.io/image_medium.png",
"large": "https://skeepers.io/image_large.png"
}
]
// ... other enhanced fields
}
]
// Old API - Offset pagination
let offset = 0;
const limit = 10;
function getNextPage() {
return fetch(`https://api-product-reviews.rr.skeepers.io/v1/websites/123/products/reviews?limit=${limit}&offset=${offset}`)
.then(response => response.json())
.then(data => {
offset += limit;
return data;
});
}
// New API - Cursor pagination functions
async function getNextPage(cursor = null, limit = 10) {
const url = new URL('https://api.skeepers.io/verified-reviews/v1/published/products/reviews');
url.searchParams.set('limit', limit.toString());
if (cursor) {
url.searchParams.set('cursor', cursor);
}
const response = await fetch(url, {
headers: { 'Authorization': `Bearer ${token}` }
});
const reviews = await response.json();
const linkHeader = response.headers.get('Link');
return {
data: reviews,
nextCursor: extractCursor(linkHeader, 'next'),
prevCursor: extractCursor(linkHeader, 'prev'),
hasNext: linkHeader?.includes('rel="next"'),
hasPrev: linkHeader?.includes('rel="prev"')
};
}
async function getPreviousPage(cursor, limit = 10) {
if (!cursor) {
throw new Error('Previous cursor is required');
}
const url = new URL('https://api.skeepers.io/verified-reviews/v1/published/products/reviews');
url.searchParams.set('limit', limit.toString());
url.searchParams.set('cursor', cursor);
const response = await fetch(url, {
headers: { 'Authorization': `Bearer ${token}` }
});
const reviews = await response.json();
const linkHeader = response.headers.get('Link');
return {
data: reviews,
nextCursor: extractCursor(linkHeader, 'next'),
prevCursor: extractCursor(linkHeader, 'prev'),
hasNext: linkHeader?.includes('rel="next"'),
hasPrev: linkHeader?.includes('rel="prev"')
};
}
function extractCursor(linkHeader, relation) {
if (!linkHeader) return null;
const regex = new RegExp(`<([^>]+)>;\\s*rel="${relation}"`);
const match = linkHeader.match(regex);
if (match) {
const url = new URL(match[1]);
return url.searchParams.get('cursor');
}
return null;
}
// Usage example:
let currentPage = await getNextPage(); // First page
let nextPage = await getNextPage(currentPage.nextCursor); // Next page
let prevPage = await getPreviousPage(currentPage.prevCursor); // Previous page
Automatic content analysis provides quick insights into customer sentiment and common themes.
// Access AI summary through /products endpoint
{
"review_summary": {
"content": "Customers love the build quality and performance, with many praising the excellent customer service. Some minor concerns about delivery times.",
"last_updated_at": "2024-06-24T15:12:31Z"
}
}
Beyond product reviews - access brand and shop-specific customer feedback.
// Get brand reviews with shop filtering
GET /brands/reviews?shop_key=B001&review_rate=4,5
Multiple product identifiers (GTIN, SKU, MPN) and advanced date range filtering.
// Filter by multiple product identifiers
GET /products/reviews?product_ean=1234567890123&product_sku=SKU12345
// Advanced date filtering
GET /products/reviews?review_date.gte=2024-01-01T00:00:00Z&review_date.lt=2024-06-01T00:00:00Z
Additional rating dimensions beyond the standard 1-5 scale.
// Quality criteria in product ratings
{
"extras": [
{
"type": "rate",
"display_name": "QUALITY",
"label": "Quality",
"rate": {
"average": 4.8,
"count": 95
}
}
]
}
Cross-platform review sharing with source attribution.
// Syndicated review information
{
"syndicated_review": true,
"syndicated_review_source": "Nintendo (NL)",
"syndicated_review_source_url": "https://nintendo.nl",
"translated_review": {
"en": "Great product!",
"fr": "Très bon produit!",
"de": "GroΓartiges Produkt!"
}
}
Better image handling with multiple size variants.
// Enhanced media objects
{
"medias": [
{
"type": "IMAGE",
"small": "https://skeepers.io/image_small.png",
"medium": "https://skeepers.io/image_medium.png",
"large": "https://skeepers.io/image_large.png"
}
]
}
| Status Code | Error | Common Causes | Solution |
|---|---|---|---|
| 401 | Unauthorized | Missing/expired token | Refresh OAuth token |
| 400 | Bad Request | Invalid cursor, parameter combinations | Check query parameters and cursor validity |
| 500 | Internal Server Error | Server issues | Retry request, contact support if persistent |
rate becomes review_rate, and ref becomes product_variation_id.
Once you've successfully migrated to the Published API, you'll have access to:
https://auth.skeepers.io/realms/skeepers/protocol/openid-connect/tokenhttps://api.skeepers.io/verified-reviews/v1/publishedThe new Published API represents a fundamental advancement from the Genesis API (awsapis3.netreviews.eu), designed to provide modern API capabilities:
This migration involves complete API redesign with breaking changes across all operations. The Genesis API used custom authentication, mixed HTTP methods, and different data structures that require significant code modifications.
awsapis3.netreviews.eu to api.skeepers.io/verified-reviews/v1/publishedidWebsite parameter (handled automatically via OAuth)product array to product_variation_id| Genesis API | Published API | Action Required |
|---|---|---|
SHA256 token calculationSHA256(idWebsite + secretKey + date) |
OAuth2.0 client credentials flow | Complete authentication rewrite |
| Genesis API | Published API |
|---|---|
https://awsapis3.netreviews.eu/websitehttps://awsapis3.netreviews.eu/product |
https://api.skeepers.io/verified-reviews/v1/published/* |
| Genesis API | Published API |
|---|---|
| Brand Reviews: GET with query params Product Reviews: POST with JSON body |
All endpoints: GET with query parameters |
| Genesis Format | Published Format |
|---|---|
| Mixed query params and JSON body | Consistent query parameters only |
| Genesis Endpoint | Method | Published Endpoint | Purpose | Notes |
|---|---|---|---|---|
/website |
GET | /brands/reviewsor /brands |
Brand/Website reviews | Use /brands/reviews for individual reviews, /brands for aggregated ratings |
/product(query: "reviews") |
POST | /products/reviews |
Individual product reviews | Enhanced filtering and standardized query parameters |
/product(query: "average") |
POST | /productsor /products/ratings |
Product ratings/averages | Use /products for summaries with AI, /products/ratings for bulk operations |
infosite.txt |
File | /brands |
Brand rating summary | Static text file β JSON API with enhanced data |
infoshops.txt |
File | /brands |
Shop-specific ratings | Static text file β JSON API with enhanced data |
The Genesis API era included static text files used for simple data access. These files are now replaced by modern JSON API endpoints with enhanced functionality.
Legacy Format: Simple text file with brand-level review count and average rating
// Example infosite.txt content
554;4.76
Format: {review_count};{average_rating}
New API Endpoint: GET /brands
// Published API response (JSON)
[
{
"one_year": {
"average": 4.76,
"count_5": 420,
"count_4": 89,
"count_3": 25,
"count_2": 15,
"count_1": 5
},
"five_year": {
"average": 4.74,
"count_5": 1205,
"count_4": 234,
"count_3": 67,
"count_2": 35,
"count_1": 13
},
"count_total_since_creation": 1554,
"oldest_review_publish_date": "2019-03-15T10:30:00Z",
"website_id": "99cbf50b-0c65-f174-211b-e8a1ae19cd78"
}
]
Migration Benefits:
Legacy Format: Semicolon-separated file with shop-specific data
// Example infoshops.txt content
id_shop;name_shop;review_number;rating;certificate_url
B001;Paris Store;125;4.8;https://example.com/certificate/B001
B002;Lyon Branch;89;4.6;https://example.com/certificate/B002
B003;Marseille Office;156;4.9;https://example.com/certificate/B003
New API Endpoint: GET /brands with shop filtering
// Published API response (JSON)
[
{
"shop_key": "B001",
"one_year": {
"average": 4.8,
"count_5": 98,
"count_4": 20,
"count_3": 5,
"count_2": 1,
"count_1": 1
},
"five_year": {
"average": 4.75,
"count_5": 310,
"count_4": 67,
"count_3": 15,
"count_2": 3,
"count_1": 2
},
"count_total_since_creation": 397,
"oldest_review_publish_date": "2019-03-15T10:30:00Z",
"website_id": "99cbf50b-0c65-f174-211b-e8a1ae19cd78"
}
]
Enhanced Shop Data Access:
// Get specific shop data
GET /brands?shop_key=B001
// Get all shops
GET /brands
// Get multiple specific shops
GET /brands?shop_key=B001,B002,B003
Migration Benefits:
| Genesis Parameter | Published Parameter | Location | Notes |
|---|---|---|---|
idWebsite |
N/A | - | Handled via OAuth authentication |
format |
N/A | - | Always JSON in Published API |
range |
limit |
Query | Same functionality (max 200) |
p |
cursor |
Query | Changed: Cursor-based pagination |
order_by + order_type |
sort + desc |
Query | Simplified sorting system |
iso_code |
N/A | - | All languages returned by default |
| Genesis Parameter | Published Parameter | Location | Notes |
|---|---|---|---|
query |
N/A | - | Determined by endpoint path |
product (array) |
product_variation_id |
Query | Comma-separated string instead of JSON array |
limit |
limit |
Query | Same functionality |
offset |
cursor |
Query | Changed: Cursor-based pagination |
order |
sort + desc |
Query | Enhanced field validation |
field + sign + compare |
review_rate |
Query | Simplified rating filter |
plateforme |
N/A | - | All languages returned by default |
// Genesis API - Custom token authentication
const crypto = require('crypto');
function generateToken(idWebsite, secretKey, date) {
const data = idWebsite + secretKey + date; // YYYY-MM-DD format
return crypto.createHash('sha256').update(data).digest('hex');
}
const today = new Date().toISOString().split('T')[0]; // YYYY-MM-DD
const token = generateToken('369fdcb5-631a-b004-7967-d48e238dcfbb', 'your_secret', today);
// Brand reviews request
fetch(`https://awsapis3.netreviews.eu/website?idWebsite=369fdcb5-631a-b004-7967-d48e238dcfbb&format=json&token=${token}`)
.then(response => response.json())
.then(data => {
// Handle response
});
// Published API - OAuth2.0 authentication
async function getOAuthToken() {
const response = await fetch('https://auth.skeepers.io/realms/skeepers/protocol/openid-connect/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'client_credentials',
client_id: 'your_client_id',
client_secret: 'your_client_secret',
audience: 'verified-reviews'
})
});
const data = await response.json();
return data.access_token;
}
// Brand reviews request
const token = await getOAuthToken();
fetch('https://api.skeepers.io/verified-reviews/v1/published/brands/reviews', {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(data => {
// Handle response
});
// Genesis API - POST request with JSON body
const requestBody = {
query: 'reviews',
product: ['test-developer0'],
idWebsite: '369fdcb5-631a-b004-7967-d48e238dcfbb',
plateforme: 'fr',
limit: 5,
offset: 0,
order: 'date_desc'
};
fetch('https://awsapis3.netreviews.eu/product', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(requestBody)
})
.then(response => response.json())
.then(data => {
// Handle custom response format
});
// Published API - GET request with query parameters
const url = new URL('https://api.skeepers.io/verified-reviews/v1/published/products/reviews');
url.searchParams.set('product_variation_id', 'test-developer0');
url.searchParams.set('limit', '5');
url.searchParams.set('sort', 'review_date');
url.searchParams.set('desc', 'review_date');
const token = await getOAuthToken();
fetch(url, {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(data => {
// Handle standardized JSON array
});
// Genesis API - Offset pagination
let offset = 0;
const limit = 100;
function getNextPage() {
const requestBody = {
query: 'reviews',
product: ['all'],
idWebsite: '369fdcb5-631a-b004-7967-d48e238dcfbb',
plateforme: 'fr',
limit: limit,
offset: offset
};
return fetch('https://awsapis3.netreviews.eu/product', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(requestBody)
})
.then(response => response.json())
.then(data => {
offset += limit;
return data;
});
}
// Published API - Cursor pagination
async function getNextPage(cursor = null, limit = 100) {
const url = new URL('https://api.skeepers.io/verified-reviews/v1/published/products/reviews');
url.searchParams.set('limit', limit.toString());
if (cursor) {
url.searchParams.set('cursor', cursor);
}
const token = await getOAuthToken();
const response = await fetch(url, {
headers: { 'Authorization': `Bearer ${token}` }
});
const reviews = await response.json();
const linkHeader = response.headers.get('Link');
return {
data: reviews,
nextCursor: extractCursor(linkHeader, 'next'),
hasNext: linkHeader?.includes('rel="next"')
};
}
function extractCursor(linkHeader, relation) {
if (!linkHeader) return null;
const regex = new RegExp(`<([^>]+)>;\\s*rel="${relation}"`);
const match = linkHeader.match(regex);
if (match) {
const url = new URL(match[1]);
return url.searchParams.get('cursor');
}
return null;
}
// Genesis API - Parsing static text file
async function getBrandRating() {
// Fetch static text file
const response = await fetch('https://www.avis-verifies.com/path/to/infosite.txt');
const textContent = await response.text();
// Parse semicolon-separated data
const [reviewCount, averageRating] = textContent.trim().split(';');
return {
reviewCount: parseInt(reviewCount),
averageRating: parseFloat(averageRating)
};
}
// Usage
const brandData = await getBrandRating();
console.log(`${brandData.reviewCount} reviews, ${brandData.averageRating} stars`);
// Published API - JSON endpoint with rich data
async function getBrandRating() {
const token = await getOAuthToken();
const response = await fetch('https://api.skeepers.io/verified-reviews/v1/published/brands', {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
const brands = await response.json();
const brandData = brands[0]; // Get main brand data
return {
// Current year data
currentYear: {
reviewCount: brandData.one_year.count_5 + brandData.one_year.count_4 +
brandData.one_year.count_3 + brandData.one_year.count_2 +
brandData.one_year.count_1,
averageRating: brandData.one_year.average,
ratingDistribution: {
five: brandData.one_year.count_5,
four: brandData.one_year.count_4,
three: brandData.one_year.count_3,
two: brandData.one_year.count_2,
one: brandData.one_year.count_1
}
},
// Historical data
allTime: {
totalReviews: brandData.count_total_since_creation,
firstReviewDate: brandData.oldest_review_publish_date
}
};
}
// Usage with enhanced data
const brandData = await getBrandRating();
console.log(`Current year: ${brandData.currentYear.reviewCount} reviews, ${brandData.currentYear.averageRating} stars`);
console.log(`All time: ${brandData.allTime.totalReviews} total reviews since ${brandData.allTime.firstReviewDate}`);
// Genesis API - Parsing CSV-like text file
async function getShopsData() {
// Fetch static text file
const response = await fetch('https://www.avis-verifies.com/path/to/infoshops.txt');
const textContent = await response.text();
// Parse semicolon-separated CSV-like data
const lines = textContent.trim().split('\n');
const header = lines[0].split(';');
const shops = [];
for (let i = 1; i < lines.length; i++) {
const values = lines[i].split(';');
shops.push({
shopId: values[0],
shopName: values[1],
reviewCount: parseInt(values[2]),
rating: parseFloat(values[3]),
certificateUrl: values[4]
});
}
return shops;
}
// Usage
const shops = await getShopsData();
shops.forEach(shop => {
console.log(`${shop.shopName}: ${shop.reviewCount} reviews, ${shop.rating} stars`);
});
// Published API - JSON endpoint with shop data
async function getShopsData(shopKeys = null) {
const token = await getOAuthToken();
const url = new URL('https://api.skeepers.io/verified-reviews/v1/published/brands');
// Optional: filter specific shops
if (shopKeys) {
url.searchParams.set('shop_key', shopKeys.join(','));
}
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
const brands = await response.json();
return brands.map(shop => ({
shopKey: shop.shop_key,
currentYear: {
reviewCount: shop.one_year.count_5 + shop.one_year.count_4 +
shop.one_year.count_3 + shop.one_year.count_2 +
shop.one_year.count_1,
averageRating: shop.one_year.average,
ratingDistribution: {
five: shop.one_year.count_5,
four: shop.one_year.count_4,
three: shop.one_year.count_3,
two: shop.one_year.count_2,
one: shop.one_year.count_1
}
},
allTime: {
totalReviews: shop.count_total_since_creation,
firstReviewDate: shop.oldest_review_publish_date
}
}));
}
// Usage with enhanced data
const allShops = await getShopsData();
const specificShops = await getShopsData(['B001', 'B002']);
allShops.forEach(shop => {
console.log(`Shop ${shop.shopKey}: ${shop.currentYear.reviewCount} reviews this year, ${shop.currentYear.averageRating} stars`);
console.log(`Total: ${shop.allTime.totalReviews} reviews since ${shop.allTime.firstReviewDate}`);
});
Automatic content analysis provides quick insights into customer sentiment and common themes.
// Access AI summary through /products endpoint
{
"review_summary": {
"content": "Customers love the build quality and performance, with many praising the excellent customer service. Some minor concerns about delivery times.",
"last_updated_at": "2024-06-24T15:12:31Z"
}
}
Multiple product identifiers support beyond simple product references.
// Support for GTIN, SKU, MPN identifiers
GET /products/reviews?product_ean=1234567890123&product_sku=SKU12345&product_mpn=MPN789
Precise date range filtering with multiple operators.
// Filter by review date, publish date, order date
GET /products/reviews?review_date.gte=2024-01-01T00:00:00Z&publish_date.lt=2024-06-01T00:00:00Z
Structured media objects with multiple size variants.
// Enhanced media objects in reviews
{
"medias": [
{
"type": "IMAGE",
"small": "https://skeepers.io/image_small.png",
"medium": "https://skeepers.io/image_medium.png",
"large": "https://skeepers.io/image_large.png"
}
]
}
Comprehensive filtering beyond basic rating filters.
// Advanced filtering options
GET /products/reviews?is_verified=true&incentivization=none&syndicated_review=false
Built-in support for translated content and syndicated reviews.
// Translated review content
{
"review_content": "Great product!",
"locale": "en",
"translated_review": {
"fr": "Très bon produit!",
"de": "GroΓartiges Produkt!",
"es": "Β‘Gran producto!"
}
}
| Status Code | Error | Common Causes | Solution |
|---|---|---|---|
| 401 | Unauthorized | Invalid/expired OAuth token | Refresh OAuth token using client credentials |
| 400 | Bad Request | Invalid parameters or cursor mismatch | Validate query parameters and cursor consistency |
| 429 | Too Many Requests | Rate limit exceeded | Implement exponential backoff and respect rate limits |
| 500 | Internal Server Error | Server issues | Retry request, contact support if persistent |
Once you've successfully migrated from the Genesis API to the Published API, you'll benefit from:
https://auth.skeepers.io/realms/skeepers/protocol/openid-connect/tokenhttps://api.skeepers.io/verified-reviews/v1/published