POST
Ingest Phone Data (Single or Batch)
/api/v1/phones/ingest
Ingest a single phone's technical data (as JSON object) or multiple phones (as JSON array), normalize it, and store it in Elasticsearch. Performs an upsert based on SKU. This is the primary way to add or update phone variant specifications.
Parameters
| Name |
Type |
Description |
| imei |
string |
Unique IMEI identifier for the phone (optional, but recommended for linking to specific devices) |
| brand |
string |
Brand name (e.g., Samsung, Apple) |
| model |
string |
Model name (e.g., Galaxy S25 Ultra, iPhone 15 Pro) |
| internal_memory |
integer |
Internal storage in MB (e.g., 256000 for 256GB) or GB (e.g., 256 for 256GB - heuristic applied) |
| ram |
integer |
RAM in MB (e.g., 12000 for 12GB) or GB (e.g. 12 for 12GB - heuristic applied) |
| colors |
string |
Available colors, comma-separated (primarily for initial seeding if original_color is not provided per variant later) |
| year_of_production |
string |
Production year (e.g., 2024). Defaults to current year if invalid/missing. |
| month_of_production |
string |
Production month (1-12). Defaults to '01' if invalid/missing. |
| (...other specs) |
various |
See example for other optional fields like physical dimensions, battery, connectivity, etc. |
Responses
| Code |
Description |
| 201 |
Single phone data successfully ingested/updated |
| 200 |
Batch processed successfully (all items succeeded) |
| 207 |
Batch processed with partial success (Multi-Status) |
| 400 |
Invalid request (bad JSON, missing fields, normalization error) |
| 500 |
Server error during processing or storage |
Example Request
Single Object:
{
"imei": "354222650219092",
"brand": "SAMSUNG",
"model": "Galaxy S25 Ultra",
"internal_memory": 256000,
"ram": 12000,
"colors": "Titanium Silver Blue, Titanium Black",
"year_of_production": "2024",
"month_of_production": "01",
"_5g": true,
"height": 162.8,
"width": 77.6,
"thickness": 8.2,
"weight": 218,
"certification": "IP68",
"battery_type": "Li-Ion",
"battery_capacity": 5000.0,
"wireless_charging": true
}
Array for Batch:
[
{
"imei": "354222650219092",
"brand": "SAMSUNG",
"model": "Galaxy S25 Ultra",
"internal_memory": 256000,
"ram": 12000,
"colors": "Titanium Silver Blue",
"year_of_production": "2024", "month_of_production": "01"
},
{
"imei": "358244958411136",
"brand": "APPLE",
"model": "iPhone 16 Pro",
"internal_memory": 512000,
"ram": 8000,
"colors": "Natural Titanium",
"year_of_production": "2024", "month_of_production": "09"
}
]
Example Response
Single Success (201):
{
"status": "success",
"sku": "SAMSUNG_GALAXY_S25_ULTRA_256GB",
"imei": "354222650219092"
}
Batch Success (200):
{
"status": "success",
"processed_count": 2,
"success_count": 2,
"results": [
{"status": "success", "sku": "SAMSUNG_GALAXY_S25_ULTRA_256GB", "imei": "354222650219092"},
{"status": "success", "sku": "APPLE_IPHONE_16_PRO_512GB", "imei": "358244958411136"}
]
}
Batch Partial Success (207):
{
"status": "partial_success",
"processed_count": 2,
"success_count": 1,
"results": [
{"status": "success", "sku": "SAMSUNG_GALAXY_S25_ULTRA_256GB", "imei": "354222650219092"},
{"status": "error", "error": "Normalization failed: Could not normalize storage...", "imei": "MISSING_IMEI"}
]
}
GET
Search Product Variants (Get SKUs)
/api/search-variants
Search for product variants (which include SKUs) based on a query string. Useful for finding the SKUs needed for other API calls. Extracts storage from the query and searches text fields.
Parameters
| Name |
Type |
Description |
| q |
string |
Query string (e.g., "iPhone 15 Pro 256gb", "samsung s24") |
Responses
| Code |
Description |
| 200 |
Returns an array of matching product variant objects, each containing a 'sku'. |
| 400 |
Missing query parameter 'q' |
| 500 |
Internal server error during search |
Example Request
curl -X GET "http://localhost:4000/api/search-variants?q=iphone+15+pro+256gb"
Example Response
[
{
"sku": "apple_iphone-15-pro_256gb",
"brand": "Apple",
"model": "iPhone 15 Pro",
"storage": 256,
"manufacturing_year": 2023,
"release_date": "2023-09-22",
"specs": { "...": "..." },
"color": "Natural Titanium",
"imei": null
}
]
GET
Get Price Estimate for SKUs
/api/price-search/price-estimate
Get price estimates for a list of SKUs broken down by condition. This is a key step after identifying SKUs via the search variants endpoint. Provides detailed price estimates including baseline data, confidence intervals, Kuusakoski wholesale prices, and AI-generated price estimates for each condition of the specified SKUs. Response includes: estimate (median price), min_estimate (10th percentile), max_estimate (90th percentile), wholesale_price (Kuusakoski maximum purchase price for applicable conditions), wholesale_fallback (true if estimate is based on wholesale price with retail markup), and ai_price (ML model prediction).
Parameters
| Name |
Type |
Description |
| skus |
string |
Comma-separated list of product SKUs for which to get price estimates (e.g., 'apple_iphone-se_128,apple_iphone-se_256') |
| reference_date |
string |
Optional reference date in YYYY-MM-DD format. Defaults to current date if not provided |
Responses
| Code |
Description |
| 200 |
Returns price estimates for each SKU with new structured format including SKU_Name and Conditions array |
| 400 |
Invalid request (e.g., missing SKUs parameter or invalid reference_date format) |
| 503 |
Elasticsearch service not available |
| 500 |
Internal server error |
Example Request
curl -X GET "http://localhost:4000/api/price-search/price-estimate?skus=apple_iphone-15-plus_128,apple_iphone-se_64&reference_date=2025-04-08"
Example Response
{
"estimates_by_sku": [
{
"SKU_Name": "apple_iphone-15-plus_128",
"Conditions": [
{
"conditionName": "fair",
"conditionPrices": {
"baseline_count": 351,
"baseline_end_date": "2025-04-08",
"baseline_start_date": "2015-04-11",
"estimate": 734.82,
"max_estimate": 864.08,
"min_estimate": 664.17,
"wholesale_price": 150.00,
"wholesale_fallback": false,
"ai_price": 720.50
}
},
{
"conditionName": "good",
"conditionPrices": {
"baseline_count": 716,
"baseline_end_date": "2025-04-08",
"baseline_start_date": "2015-04-11",
"estimate": 764.65,
"max_estimate": 874.03,
"min_estimate": 685.1,
"wholesale_price": 220.00,
"wholesale_fallback": false,
"ai_price": 750.30
}
},
{
"conditionName": "mint",
"conditionPrices": {
"baseline_count": 1901,
"baseline_end_date": "2025-04-08",
"baseline_start_date": "2015-04-11",
"estimate": 844.2,
"max_estimate": 923.74,
"min_estimate": 724.87
}
},
{
"conditionName": "new",
"conditionPrices": {
"baseline_count": 3,
"baseline_end_date": "2025-04-08",
"baseline_start_date": "2015-04-11",
"estimate": 840.22,
"max_estimate": 883.17,
"min_estimate": 840.22
}
}
]
}
],
"reference_date": "2025-04-08",
"shared_erosion_rate": -0.0039
}
GET
Get All Unique Colors
/api/colors
Retrieves all unique colors from product variants. Handles comma-separated color values and provides sorting options. Colors are extracted from the specs.physical_specs.colors field and normalized for consistency.
Parameters
| Name |
Type |
Description |
| limit |
integer |
Maximum number of colors to return (1-10000, default: 1000) |
| sort |
string |
Sort order: 'alpha' for alphabetical, 'count' for frequency (default: 'alpha') |
Responses
| Code |
Description |
| 200 |
Successfully retrieved colors list |
| 400 |
Invalid parameters (limit out of range or invalid sort option) |
| 500 |
Internal server error or Elasticsearch connection failure |
Example Request
curl -X GET "http://localhost:4000/api/colors?limit=10&sort=count"
Example Response
{
"colors": [
"Black",
"Blue",
"Gold",
"Silver",
"White"
],
"total_count": 5,
"sort_order": "count"
}
GET
Get Color Statistics
/api/colors/stats
Provides detailed color statistics including frequency counts and percentages. Shows how many products have each color and their relative popularity.
Parameters
| Name |
Type |
Description |
| limit |
integer |
Maximum number of colors to return (1-1000, default: 100) |
Responses
| Code |
Description |
| 200 |
Successfully retrieved color statistics |
| 400 |
Invalid limit parameter (out of range 1-1000) |
| 500 |
Internal server error or Elasticsearch connection failure |
Example Request
curl -X GET "http://localhost:4000/api/colors/stats?limit=5"
Example Response
{
"colors": [
{
"color": "Black",
"count": 525,
"percentage": 39.68
},
{
"color": "Blue",
"count": 301,
"percentage": 22.75
},
{
"color": "White",
"count": 251,
"percentage": 18.97
}
],
"total_unique_colors": 406,
"total_variants": 1323,
"returned_count": 3
}
GET
Get All Unique SKUs
/api/skus
Retrieves all unique SKUs from product variants. Provides sorting options and allows filtering by limit. SKUs are extracted from the product_variants index and represent unique product identifiers.
Parameters
| Name |
Type |
Description |
| limit |
integer |
Maximum number of SKUs to return (1-10000, default: 1000) |
| sort |
string |
Sort order: 'alpha' for alphabetical, 'count' for frequency (default: 'alpha') |
Responses
| Code |
Description |
| 200 |
Successfully retrieved SKUs list |
| 400 |
Invalid parameters (limit out of range or invalid sort option) |
| 500 |
Internal server error or Elasticsearch connection failure |
Example Request
curl -X GET "http://localhost:4000/api/skus?limit=10&sort=alpha"
Example Response
{
"skus": [
"apple_iphone-13_128",
"apple_iphone-13_256",
"apple_iphone-14_128",
"samsung_galaxy-s21_128",
"samsung_galaxy-s21_256"
],
"total_count": 5,
"sort_order": "alpha"
}
GET
Get SKU Statistics
/api/skus/stats
Provides detailed SKU statistics including frequency counts and percentages. Shows how many variants exist for each SKU and their relative distribution in the database.
Parameters
| Name |
Type |
Description |
| limit |
integer |
Maximum number of SKUs to return (1-1000, default: 100) |
Responses
| Code |
Description |
| 200 |
Successfully retrieved SKU statistics |
| 400 |
Invalid limit parameter (out of range 1-1000) |
| 500 |
Internal server error or Elasticsearch connection failure |
Example Request
curl -X GET "http://localhost:4000/api/skus/stats?limit=5"
Example Response
{
"skus": [
{
"sku": "apple_iphone-13_128",
"count": 1,
"percentage": 0.21
},
{
"sku": "samsung_galaxy-s21_256",
"count": 1,
"percentage": 0.21
},
{
"sku": "google_pixel-6_128",
"count": 1,
"percentage": 0.21
}
],
"total_unique_skus": 466,
"total_variants": 466,
"returned_count": 3
}
GET
Get Available Colors for an SKU
/api/v1/sku/<string:sku>/colors
Fetches unique pairs of (normalized_color, original_color) available for a given SKU. This helps in understanding color variations for a specific product variant.
Parameters
| Name |
Type |
Description |
| sku |
string (in path) |
The product SKU (e.g., apple_iphone-15-pro_256gb) |
Responses
| Code |
Description |
| 200 |
Returns a list of available color details for the SKU. |
| 400 |
SKU parameter is missing or invalid. |
| 404 |
SKU not found (implicitly, if no colors are returned, though the endpoint itself doesn't 404 for non-existent SKUs, just returns empty list). |
| 500 |
Internal server error. |
Example Request
curl -X GET "http://localhost:4000/api/v1/sku/apple_iphone-15-pro_256gb/colors"
Example Response
{
"sku": "apple_iphone-15-pro_256gb",
"color_details": [
{
"normalized_color": "blue",
"original_color": "Natural Blue"
},
{
"normalized_color": "white",
"original_color": "Natural Titanium"
}
]
}
GET
Get Kuusakoski Price for a SKU
/api/kuusakoski/sku-price/<sku>
Retrieves Kuusakoski pricing information for a specific SKU. This provides the minimum stock price that Kuusakoski pays for phones, which should never be exceeded in purchase price estimates. Returns all pricing tiers (100%, 70%, 40%) along with the calculated minimum price.
Parameters
| Name |
Type |
Description |
| sku |
string (in path) |
The product SKU to get pricing for (e.g., apple_iphone-11_128) |
Responses
| Code |
Description |
| 200 |
Returns detailed pricing information for the SKU |
| 404 |
SKU not found in Kuusakoski pricing data |
| 500 |
Internal server error |
Example Request
curl -X GET "http://localhost:4000/api/kuusakoski/sku-price/apple_iphone-11_128"
Example Response
{
"sku": "apple_iphone-11_128",
"brand": "APPLE",
"model": "IPHONE 11",
"storage": 128,
"storage_unit": "gb",
"manufacturing_year": 2019,
"unit_amount": 31200,
"pricing": {
"kuusakoski_100_percent": 101.0,
"kuusakoski_70_percent": 71.0,
"kuusakoski_40_percent": 40.0,
"minimum_price": 40.0
},
"created_at": "2025-01-12T10:30:00.000Z",
"updated_at": "2025-01-12T10:30:00.000Z"
}
GET
Search Kuusakoski Pricing Data
/api/kuusakoski/search
Search Kuusakoski pricing data with various filters. Allows filtering by brand, model, price range, manufacturing year, and storage capacity. Useful for finding pricing information for multiple products or analyzing pricing patterns.
Parameters
| Name |
Type |
Description |
| brand |
string |
Filter by brand (e.g., APPLE, SAMSUNG) |
| model |
string |
Filter by model (partial match, case insensitive) |
| min_price |
number |
Minimum price filter (searches across all pricing tiers) |
| max_price |
number |
Maximum price filter (searches across all pricing tiers) |
| manufacturing_year |
integer |
Filter by manufacturing year |
| storage_min |
integer |
Minimum storage capacity |
| storage_max |
integer |
Maximum storage capacity |
| limit |
integer |
Maximum number of results (default: 20) |
Responses
| Code |
Description |
| 200 |
Returns search results with pricing information |
| 400 |
Invalid request parameters |
| 500 |
Internal server error |
Example Request
curl -X GET "http://localhost:4000/api/kuusakoski/search?brand=APPLE&manufacturing_year=2019&limit=5"
Example Response
{
"total": 15,
"count": 5,
"items": [
{
"sku": "apple_iphone-11_64",
"brand": "APPLE",
"model": "IPHONE 11",
"storage": 64,
"storage_unit": "gb",
"manufacturing_year": 2019,
"unit_amount": 33491,
"pricing": {
"kuusakoski_100_percent": 92.0,
"kuusakoski_70_percent": 64.0,
"kuusakoski_40_percent": 37.0,
"minimum_price": 37.0
}
}
]
}
POST
Get Minimum Prices for Multiple SKUs
/api/kuusakoski/minimum-prices
Retrieves minimum Kuusakoski prices for a list of SKUs in a single request. This is the key endpoint for ensuring purchase price estimates never exceed Kuusakoski's minimum stock prices. Returns pricing information for found SKUs and identifies missing ones.
Parameters
| Name |
Type |
Description |
| skus |
array |
List of SKUs to get minimum prices for |
Responses
| Code |
Description |
| 200 |
Returns minimum prices for requested SKUs |
| 400 |
Invalid request body or missing SKUs list |
| 500 |
Internal server error |
Example Request
curl -X POST "http://localhost:4000/api/kuusakoski/minimum-prices" \
-H "Content-Type: application/json" \
-d '{"skus": ["apple_iphone-11_128", "samsung_galaxy-s20_256", "unknown_sku"]}'
Example Response
{
"requested_count": 3,
"found_count": 2,
"missing_count": 1,
"missing_skus": ["unknown_sku"],
"prices": {
"apple_iphone-11_128": {
"sku": "apple_iphone-11_128",
"brand": "APPLE",
"model": "IPHONE 11",
"minimum_price": 40.0,
"pricing_tiers": {
"100_percent": 101.0,
"70_percent": 71.0,
"40_percent": 40.0
}
},
"samsung_galaxy-s20_256": {
"sku": "samsung_galaxy-s20_256",
"brand": "SAMSUNG",
"model": "GALAXY S20",
"minimum_price": 25.0,
"pricing_tiers": {
"100_percent": 75.0,
"70_percent": 50.0,
"40_percent": 25.0
}
},
"unknown_sku": {
"sku": "unknown_sku",
"minimum_price": null,
"error": "SKU not found in Kuusakoski pricing data"
}
}
}
GET
Get Kuusakoski Pricing Statistics
/api/kuusakoski/stats
Provides comprehensive statistics about the Kuusakoski pricing data including brand distribution, manufacturing year ranges, pricing tier statistics, and storage unit distribution. Useful for understanding the scope and quality of the pricing data.
Responses
| Code |
Description |
| 200 |
Returns detailed statistics about Kuusakoski pricing data |
| 500 |
Internal server error |
Example Request
curl -X GET "http://localhost:4000/api/kuusakoski/stats"
Example Response
{
"total_records": 1289,
"brands": {
"count": 34,
"top_brands": [
{"brand": "SAMSUNG", "count": 314},
{"brand": "NOKIA", "count": 171},
{"brand": "XIAOMI", "count": 114}
]
},
"manufacturing_years": {
"range": {"min": 1997, "max": 2025},
"distribution": [
{"year": 2019, "count": 99},
{"year": 2020, "count": 156}
]
},
"storage_units": [
{"unit": "gb", "count": 1205},
{"unit": "mb", "count": 118}
],
"pricing_statistics": {
"100_percent_tier": {
"count": 1289,
"min": 2.0,
"max": 838.0,
"avg": 60.12
},
"70_percent_tier": {
"count": 1289,
"min": 2.0,
"max": 587.0,
"avg": 42.35
},
"40_percent_tier": {
"count": 1289,
"min": 2.0,
"max": 335.0,
"avg": 24.46
}
},
"unit_amount_statistics": {
"count": 1289,
"min": 0.0,
"max": 33491.0,
"avg": 2634.56
}
}