Integrate bicycle valuations into your systems with our REST API.
The buycycle Valuations API gives you programmatic access to real-time bicycle residual values derived from first-party marketplace data — actual listing and sale prices across thousands of transactions.
A typical integration follows three steps:
/basic-info to get valid condition codes, component groups, and pre-filled defaults./value with the bike details and receive a price recommendation with comparable sales data.All responses are wrapped in a standard envelope: { "success": true, "data": ... }. Errors follow the same shape with { "success": false, "error": "..." }.
Every request must include your API key in the X-API-Key header. You can create and manage keys on the API Keys page in your dashboard. Keys that are revoked or expired will return a 401 error.
curl -H "X-API-Key: bc_live_..." \
/api/v1/brands/api/v1All endpoint paths below are relative to this base URL.
/brandsSearch for bicycle brands by name. Returns all brands when no search term is provided.
| Parameter | Type | Required | Description |
|---|---|---|---|
| search | string | Optional | Filter brands by name (case-insensitive partial match) |
// GET /brands?search=Canyon
{
"success": true,
"data": [
{ "id": 21, "name": "Canyon", "slug": "canyon" }
]
}/familiesList model families (e.g. Endurace, Aeroad) for a given brand.
| Parameter | Type | Required | Description |
|---|---|---|---|
| brand_id | integer | Required | The brand ID returned from /brands |
// GET /families?brand_id=21
{
"success": true,
"data": [
{ "id": 1111, "name": "Aeroad", "slug": "aeroad" },
{ "id": 1108, "name": "Endurace", "slug": "endurace" }
]
}/templatesList specific bike templates (year + spec combinations) for a brand. Optionally narrow by family.
| Parameter | Type | Required | Description |
|---|---|---|---|
| brand_id | integer | Required | The brand ID |
| family_id | integer | Optional | Narrow results to a specific family |
// GET /templates?brand_id=21&family_id=1108
{
"success": true,
"data": [
{
"id": 135879,
"name": "Endurace 6 2022",
"year": 2022,
"msrp": 1499,
"image_url": "https://..."
}
]
}/basic-infoRetrieve form options and pre-filled defaults for a specific template. Use the returned values to populate the POST /value request.
| Parameter | Type | Required | Description |
|---|---|---|---|
| bike_template_id | integer | Required | The template ID returned from /templates |
// GET /basic-info?bike_template_id=135879
{
"success": true,
"data": {
"static_data": {
"bike_types": [{ "id": 1, "name": "Road & Gravel" }, ...],
"bike_categories": [{ "id": 1, "name": "Road" }, ...],
"bike_components": [{ "id": 18, "name": "Shimano Tiagra" }, ...],
"condition_codes": [{ "code": "5", "name": "Brand new with warranty" }, ...],
"brake_type_codes": [{ "code": "disc", "name": "disc" }, ...],
"frame_material_codes": [{ "code": "carbon", "name": "Carbon" }, ...],
"shifting_codes": [{ "code": "mechanical", "name": "mechanical" }, ...]
},
"prefilled": {
"template_id": 135879,
"name": "Endurace 6 2022",
"year": 2022,
"msrp": 1499,
"brand_id": 21,
"family_id": 1108,
"bike_type_id": 1,
"bike_category_id": 1,
"bike_component_id": 18,
"frame_material_code": "aluminum",
"brake_type_code": "disc",
"shifting_code": "mechanical",
"is_ebike": false,
"is_frameset": false
}
}
}/valueRequest a bike valuation. Costs 1 request from your usage allowance. If there is insufficient market data to generate a valuation, 0 requests are charged.
| Parameter | Type | Required | Description |
|---|---|---|---|
| bike_template_id | integer | Required | Template ID from /templates |
| condition_code | integer | Required | Condition code from /basic-info (e.g. 2 = good) |
| bike_type_id | integer | Required | Bike type ID from /basic-info |
| bike_category_id | integer | Required | Category ID from /basic-info |
| is_ebike | boolean | Required | Whether the bike is electric |
| is_frameset | boolean | Required | Whether this is a frameset only |
| bike_brand | string | Required | Brand name (e.g. "Canyon") |
| bike_model | string | Required | Model name (e.g. "Endurace 6 2022") |
| bike_year | integer | Optional | Model year |
| msrp | number | Optional | Original retail price in EUR |
| bike_component_id | integer | Optional | Component group ID from /basic-info |
| brake_type_code | string | Optional | Brake type code from /basic-info |
| frame_material_code | string | Optional | Frame material code from /basic-info |
| shifting_code | string | Optional | Shifting type code from /basic-info |
| zip | string | Optional | Postal code for regional pricing |
| radius_km | integer | Optional | Search radius in km (used with zip) |
// POST /value
{
"bike_template_id": 135879,
"condition_code": 2,
"bike_type_id": 1,
"bike_category_id": 1,
"is_ebike": false,
"is_frameset": false,
"bike_brand": "Canyon",
"bike_model": "Endurace 6 2022",
"bike_year": 2022,
"msrp": 1499,
"bike_component_id": 18,
"brake_type_code": "disc",
"frame_material_code": "aluminum",
"shifting_code": "mechanical"
}// Response
{
"success": true,
"data": {
"id": "5cef4123-eb86-4355-93aa-7abc3bea56e9",
"response": {
"price_recommendation": {
"price": 750,
"price_min": 710,
"price_max": 790,
"sample_size": 12
},
"sold_bikes": [
{
"id": 2256459,
"name": "Endurace 6 2022",
"year": 2022,
"price": 950,
"sold_price": 950,
"condition_code": 3,
"sold_date": 1768030393,
"image_url": "https://...",
"product_url": "https://buycycle.com/product/..."
}
],
"active_bikes": [
{
"id": 2482424,
"name": "Endurace 6 2022",
"year": 2022,
"price": 999,
"condition_code": 3,
"created_at": "2026-04-06 21:21:32",
"image_url": "https://...",
"product_url": "https://buycycle.com/product/..."
}
]
},
"creditsCharged": 1,
"creditsRefunded": false
}
}/usageCheck your current usage allowance and billing status.
// GET /usage
{
"success": true,
"data": {
"billingStatus": "FREE_TIER",
"totalUsed": 2,
"freeLimit": 5,
"remainingFree": 3,
"currentMonthUsage": 0,
"monthlyUsageCap": null
}
}Every response returns a JSON object with a success boolean. Successful responses include a data field. Errors include an error message string.
Success
{
"success": true,
"data": { ... },
"timestamp": "2026-04-10T..."
}Error
{
"success": false,
"error": "Missing or invalid X-API-Key header",
"timestamp": "2026-04-10T..."
}| Status | Meaning |
|---|---|
| 400 | Bad Request — missing or invalid parameters |
| 401 | Unauthorized — missing, invalid, or revoked API key |
| 402 | Payment Required — usage allowance exhausted |
| 403 | Forbidden — account pending approval, suspended, or monthly cap reached |
| 404 | Not Found — the requested resource does not exist |
| 429 | Too Many Requests — rate limit exceeded, retry after backoff |
| 500 | Internal Server Error — unexpected failure on our end |
| Endpoint type | Limit |
|---|---|
| Read endpoints (brands, families, templates, basic-info, usage) | 300 requests / minute |
| Valuation endpoint (POST /value) | 100 requests / minute |
Limits are per API key. If you exceed the limit you will receive a 429 response. Wait and retry with exponential backoff.