Introduction
Welcome to the PriceHubble API! The PriceHubble API is based on REST and is easy to use. Please read the following information to get started.
Every endpoint has an URL of the form {BASE_URL/ENDPOINT_SUFFIX}
. The BASE_URL is https://api.pricehubble.com/api/v1
.
Example of a full endpoint URL: https://api.pricehubble.com/api/v1/valuation_light/property_value
.
Every request should contain a valid access token. See section Authentication for how to obtain one.
POST requests should have the following header: content-type: application/json
.
In the endpoint descriptions below, mandatory request/response fields are written in bold.
Authentication
Example Request:
curl -X POST \
https://api.pricehubble.com/auth/login/credentials \
-H 'content-type: application/json' \
-d '{
"username": "Maverick",
"password": "TOPSECRET"
}'
Make sure to replace
Maverick
andTOPSECRET
with your username and your password.Example Response:
{
"access_token": "74126eab0a9048d993bda4b1b55ae074",
"expires_in": 7200
}
POST
https://api.pricehubble.com/auth/login/credentials
Logs in with the specified credentials and returns an access token which can then be used in subsequent requests. The token expires every 2 hours. Thereafter, it has to be acquired anew.
Error Handling
The endpoints return standard HTTP status codes. The list of status includes:
Code | Meaning |
---|---|
200 | Success |
400 | Bad request |
401 | Unauthorized |
403 | Forbidden |
404 | Not found |
500 | Internal server error |
Example 400 Response:
{
"message": "Unsupported country code"
}
Example 401 Response:
{
"error_description": "The access token is invalid or has expired",
"error": "invalid_token"
}
In case of an error (4xx or 5xx status), the response body generally has the following structure:
Field | Description | Type |
---|---|---|
message | Description of the error condition intended for a human audience | string |
Note though that some authentication errors might have a slightly different structure:
Field | Description | Type |
---|---|---|
error_description | Description of the error condition intended for a human audience | string |
error | Error category | string |
INTERNATIONAL
Valuation Light
POST
valuation/property_value_light
Performs a simple valuation of the specified property.
If you would like to perform valuations for multiple properties (in a single call), create time series, or achieve better valuations by taking more parameters into account, consider using the full-fledged Valuation endpoint.
Request
Example Request:
curl -X POST 'https://api.pricehubble.com/api/v1/valuation/property_value_light?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'content-type: application/json' \
-d '{
"dealType": "sale",
"property": {
"location": {
"address": {
"city": "Zurich",
"houseNumber": "391",
"postCode": "8037",
"street": "Nordstrasse"
},
"coordinates": {
"latitude": 47.3968601,
"longitude": 8.5153549
}
},
"propertyType": {
"code": "house"
},
"buildingYear": 2000,
"livingArea": 200,
"landArea": 100,
"condition": "well_maintained"
},
"countryCode": "CH"
}'
Field | Description | Type | Remarks |
---|---|---|---|
dealType | Deal type of the valuation | enum | sale or rent |
property | Property description | PropertyLight | |
countryCode | ISO country code | string |
Response
Example Response:
{
"confidence": "medium",
"currency": "CHF",
"valueRange": {
"lower": 1694600,
"upper": 2156800
}
}
Field | Description | Type | Remarks |
---|---|---|---|
confidence | Confidence of the valuation | enum | poor , medium or good |
currency | Currency of valueRange |
enum | CHF or EUR |
valueRange.lower | Estimated lower bound of the property's market value (sale price value if dealType is sale or gross or net rent value if dealType is rent ). For JP net rent and for all other countries gross rent is returned |
integer | |
valueRange.upper | Estimated upper bound of the property's market value (sale price value if dealType is sale or gross or net rent value if dealType is rent ). For JP net rent and for all other countries gross rent is returned |
integer |
Valuation
POST
valuation/property_value
Performs valuations for the specified real estate properties on the specified valuation dates. The endpoint can be used to do a valuation of a single property, to create time series or to perform bulk valuations.
The number of valuations per call may not exceed 50, i.e. you can perform valuations for 1 property on 50 dates or for 50 properties on 1 date, but not for 50 properties on 50 dates.
Request
Example Request (Simple):
curl -X POST 'https://api.pricehubble.com/api/v1/valuation/property_value?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'Content-Type: application/json' \
-d '{
"dealType": "sale",
"valuationInputs": [
{
"property": {
"location": {
"address": {
"postCode": "8037",
"city": "Zurich",
"street": "Nordstrasse",
"houseNumber": "391"
}
},
"propertyType": {
"code": "apartment"
},
"buildingYear": 1990,
"livingArea": 100
}
}
],
"countryCode": "CH"
}'
Example Request (Advanced):
curl -X POST 'https://api.pricehubble.com/api/v1/valuation/property_value?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'Content-Type: application/json' \
-d '{
"dealType": "sale",
"valuationDates": [
"2018-10-01",
"2019-01-01"
],
"valuationInputs": [
{
"property": {
"location": {
"coordinates": {
"latitude": 47.3968601,
"longitude": 8.5153549
}
},
"propertyType": {
"code": "apartment",
"subcode": "apartment_normal"
},
"buildingYear": 1990,
"livingArea": 100,
"numberOfRooms": 3.5,
"numberOfBathrooms": 1,
"balconyArea": 6,
"gardenArea": 10,
"numberOfIndoorParkingSpaces": 1,
"numberOfOutdoorParkingSpaces": 2,
"floorNumber": 2,
"hasLift": false,
"energyLabel": "minergie",
"quality": {
"bathrooms": "simple",
"kitchen": "normal",
"flooring": "high_quality",
"windows": "luxury"
},
"condition": {
"bathrooms": "renovation_needed",
"kitchen": "renovation_needed",
"flooring": "well_maintained",
"windows": "new_or_recently_renovated"
}
}
}
],
"returnScores": true,
"countryCode": "CH"
}'
Field | Description | Type | Remarks |
---|---|---|---|
dealType | Deal type of the valuation | enum | sale or rent |
valuationDates | List of dates for each property to be valuated against | array of dates | default: [<current date>], min items: 1, max items: 50, date format: "YYYY-MM-DD" |
valuationInputs | array | min items: 1, max items: 50 | |
valuationInputs[i].property | Property description | Property | |
valuationInputs[i].valuationDates | List of dates for current property to be valuated against | array of dates | Overrides the global valuationDates default: [<current date>], min items: 1, max items: 50, date format: "YYYY-MM-DD" |
returnScores | Whether to return scores in the response | boolean | default: true Scores are currently only supported for CH country code. Valuations without scores might perform faster. |
countryCode | ISO country code | string |
Response
Example Response (Simple):
{
"valuations": [
[
{
"salePrice": 374000,
"salePriceRange": {
"lower": 329000,
"upper": 418000
},
"confidence": "medium",
"currency": "CHF",
"coordinates": {
"latitude": 47.3968677,
"longitude": 8.515364
}
}
]
]
}
Example Response (Advanced):
{
"valuations": [
[
{
"salePrice": 374000,
"salePriceRange": {
"lower": 329000,
"upper": 418000
},
"confidence": "medium",
"coordinates": {
"latitude": 47.3968601,
"longitude": 8.5153549
},
"currency": "CHF",
"scores": {
"condition": 0.514,
"location": 0.551,
"quality": 0.684
}
},
{
"salePrice": 374000,
"salePriceRange": {
"lower": 329000,
"upper": 418000
},
"confidence": "medium",
"currency": "CHF",
"scores": {
"condition": 0.514,
"location": 0.551,
"quality": 0.684
}
}
]
]
}
Example Error Response 1 ("Local" error):
HTTP Status Code: 200
{
"valuations": [
[
{
"salePrice": 374000,
"salePriceRange": {
"lower": 329000,
"upper": 418000
},
"confidence": "medium",
"coordinates": {
"latitude": 47.3968601,
"longitude": 8.5153549
},
"currency": "CHF",
"scores": {
"condition": 0.514,
"location": 0.551,
"quality": 0.684
}
},
{
"status": {
"code": 400,
"message": "numberOfRooms: Must be between 1 and 12."
}
}
]
]
}
Example Error Response 2 ("Global" error):
HTTP Status Code: 400
{
"message": "'1990' is not of type 'integer'"
}
Field | Description | Type | Remarks |
---|---|---|---|
valuations | List of valuations per each property per each date | array of arrays of Valuations | valuations[i][j] contains the valuation for property i on date j |
Field | Description | Type | Remarks |
---|---|---|---|
currency | Currency of the valuation | enum | CHF or EUR |
coordinates | Coordinates resolved from the address specified in the request (or coordinates from the request if they have been provided) | Coordinates | |
salePrice | Estimated sale price value of the property | integer | Only present if dealType is sale |
salePriceRange.lower | Estimated lower bound of the property's sale price value | integer | Only present if dealType is sale |
salePriceRange.upper | Estimated upper bound of the property's sale price value | integer | Only present if dealType is sale |
rentGross | Estimated monthly gross rent value of the property | integer | Only present if dealType is rent . Currently not available in JP |
rentGrossRange.lower | Estimated lower bound of the property's gross rent value | integer | Only present if dealType is rent . Currently not available in JP |
rentGrossRange.upper | Estimated upper bound of the property's gross rent value | integer | Only present if dealType is rent . Currently not available in JP |
rentNet | Estimated monthly net rent value of the property | integer | Only present if dealType is rent . Currently not available in AT |
rentNetRange.lower | Estimated lower bound of the property's net rent value | integer | Only present if dealType is rent . Currently not available in AT |
rentNetRange.upper | Estimated upper bound of the property's net rent value | integer | Only present if dealType is rent . Currently not available in AT |
value | Estimated market value of the property | integer | Deprecated since 2019-05-20. Replaced by salePrice (if dealType is sale ) and rentGross (if dealType is rent ) |
valueRange.lower | Estimated lower bound of the property's market value | integer | Deprecated since 2019-05-20. Replaced by salePriceRange.lower (if dealType is sale ) and rentGrossRange.lower (if dealType is rent ) |
valueRange.upper | Estimated upper bound of the property's market value | integer | Deprecated since 2019-05-20. Replaced by salePriceRange.upper (if dealType is sale ) and rentGrossRange.upper (if dealType is rent ) |
confidence | Confidence of the valuation | enum | poor , medium or good |
scores.quality | Quality score | Score | Currently only available in CH |
scores.condition | Condition score | Score | Currently only available in CH |
scores.location | Location score | Score | Currently only available in CH |
status | Failure status of the valuation | object | If the valuation for a specific property/date combination could not be performed, a "local" status object might be returned. The overall HTTP response status code can still be 200 in this case. The motivation for this behaviour is to avoid making the whole request fail if only 1 out of 50 property is invalid (bulk valuation case). If you perform a valuation of a single property on a single date (single valuation case), errors will always be reported "globally", i.e. the HTTP response status code will reflect the error. |
status.code | The error code | integer | The error codes in the status object are inspired by HTTP status codes. The only code returned by the current implementation is:
|
status.message | Details about the error | string |
Below some more typical usage examples.
d1
,d2
andd3
are dates of the formatYYYY-MM-DD
.p1
andp2
are Properties.p1today
,p2today
,p1d1
,p1d2
,p2d3
are Valuations. The mandatory parametersdealType
andcountryCode
have been omitted for the sake of brevity.Valuation of a single property on the current date
Request:
{
"valuationInputs": [
{
"property": p1
}
]
}
Response:
{
"valuations": [
[p1today]
]
}
Valuation of a single property on multiple dates (time series)
Request:
{
"valuationDates": [d1, d2],
"valuationInputs": [
{
"property": p1
}
]
}
Response:
{
"valuations": [
[p1d1, p1d2]
]
}
Valuation of multiple properties on the current date
Request:
{
"valuationInputs": [
{
"property": p1
},
{
"property": p2
}
]
}
Response:
{
"valuations": [
[p1today],
[p2today]
]
}
Valuation of multiple properties on multiple distinct dates
Request:
{
"valuationDates": [d1],
"valuationInputs": [
{
"property": p1
},
{
"property": p2,
"valuationDates": [d2, d3]
}
]
}
Response:
{
"valuations": [
[p1d1],
[p2d2, p2d3]
]
}
Dossier Creation
POST
dossiers
Creates a new dossier. The dossier can then be shared using the Dossier Sharing endpoint.
Request
Example Request:
curl -X POST 'https://api.pricehubble.com/api/v1/dossiers?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'Content-Type: application/json' \
-d '{
"title": "My dossier",
"description": "My description",
"dealType": "sale",
"property": {
"location": {
"address": {
"postCode": "8037",
"city": "Zurich",
"street": "Nordstrasse",
"houseNumber": "391"
},
"coordinates": {
"latitude": 47.3968601,
"longitude": 8.5153549
}
},
"propertyType": {
"code": "house",
"subcode": "house_detached"
},
"buildingYear": 1990,
"livingArea": 100,
"landArea": 900,
"volume": 900,
"numberOfRooms": 3,
"numberOfBathrooms": 1,
"numberOfIndoorParkingSpaces": 0,
"numberOfOutdoorParkingSpaces": 0,
"hasPool": true,
"condition": {
"bathrooms": "renovation_needed",
"kitchen": "renovation_needed",
"flooring": "well_maintained",
"windows": "new_or_recently_renovated"
},
"quality": {
"bathrooms": "simple",
"kitchen": "normal",
"flooring": "high_quality",
"windows": "luxury"
}
},
"images": [
{
"filename": "633390e8-0455-4520-87ba-3c5c8c234cb3.jpg",
"caption": "Front view"
}
],
"logo": "b7219677-f4d5-4e99-9d7f-7cf1dee68900.png",
"countryCode": "CH"
}'
Field | Description | Type | Remarks |
---|---|---|---|
title | Dossier title | string | |
description | Dossier description | string | Maximum of 2000 characters |
dealType | Deal type of the dossier | enum | sale or rent |
property | Information about the property | Property | |
property.location.coordinates | Coordinates of the property | Coordinates | If property.location.coordinates is not provided, property.location.address is used to perform a geocoding lookup. |
property.location.address | Address of the property | Address | postCode and city are mandatory fields of the address. The address provided will be shown in the shared dossier. |
askingSalePrice | Asking price in the main currency of the dossier’s country. The asking price will show up in dossier permalinks (see Dossier Sharing). | integer | Only relevant if dealType is sale |
valuationOverrideSalePrice | Custom sale price valuation to override PriceHubble's valuation | integer | Only relevant if dealType is sale |
valuationOverrideRentNet | Custom net rent valuation to override PriceHubble's valuation | integer | Only relevant if dealType is rent |
valuationOverrideRentGross | Custom gross rent valuation to override PriceHubble's valuation | integer | Only relevant if dealType is rent |
valuationOverrideReasonFreetext | A reason why valuation overriding is needed | string | Required when any of the valuationOverride* fields are provided |
images | Dossier images | array of Dossier Images | max items: 20 |
logo | Dossier logo filename | string | Get the filename from Dossier Logos endpoint |
countryCode | ISO country code | string |
Response
Example Response:
{
"id": "119a6ead-4ac4-4b4b-b264-195a2895618e"
}
Field | Description | Type | Remarks |
---|---|---|---|
id | ID of the newly created dossier | string |
Dossier Update
PUT
dossiers/<dossier_id>
Updates the dossier specified in the request path by replacing the fields with the ones provided.
Request
Example Request:
curl -X PUT 'https://api.pricehubble.com/api/v1/dossiers/119a6ead-4ac4-4b4b-b264-195a2895618e?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'Content-Type: application/json' \
-d '{
"title": "My dossier",
"description": "My description",
"dealType": "sale",
"property": {
"location": {
"address": {
"postCode": "8037",
"city": "Zurich",
"street": "Nordstrasse",
"houseNumber": "391"
},
"coordinates": {
"latitude": 47.3968601,
"longitude": 8.5153549
}
},
"propertyType": {
"code": "house",
"subcode": "house_detached"
},
"buildingYear": 1990,
"livingArea": 100,
"landArea": 900,
"volume": 900,
"numberOfRooms": 3,
"numberOfBathrooms": 1,
"numberOfIndoorParkingSpaces": 0,
"numberOfOutdoorParkingSpaces": 0,
"hasPool": true,
"condition": {
"bathrooms": "renovation_needed",
"kitchen": "renovation_needed",
"flooring": "well_maintained",
"windows": "new_or_recently_renovated"
},
"quality": {
"bathrooms": "simple",
"kitchen": "normal",
"flooring": "high_quality",
"windows": "luxury"
}
},
"images": [
{
"filename": "633390e8-0455-4520-87ba-3c5c8c234cb3.jpg",
"caption": "Front view"
}
],
"logo": "b7219677-f4d5-4e99-9d7f-7cf1dee68900.png",
"countryCode": "CH"
}'
Field | Description | Type | Remarks |
---|---|---|---|
title | Dossier title | string | |
description | Dossier description | string | Maximum of 2000 characters |
dealType | Deal type of the dossier | enum | sale or rent |
property | Information about the property | Property | The location of a dossier’s property cannot be updated. Please create a new dossier if you want a dossier with a different location. |
askingSalePrice | Asking price in the main currency of the dossier’s country. The asking price will show up in dossier permalinks (see Dossier Sharing). | integer | Only relevant if dealType is sale |
valuationOverrideSalePrice | Custom sale price valuation to override PriceHubble's valuation | integer | Only relevant if dealType is sale |
valuationOverrideRentNet | Custom net rent valuation to override PriceHubble's valuation | integer | Only relevant if dealType is rent |
valuationOverrideRentGross | Custom gross rent valuation to override PriceHubble's valuation | integer | Only relevant if dealType is rent |
valuationOverrideReasonFreetext | A reason why valuation overriding is needed | string | Required when any of the valuationOverride* fields are provided |
images | Dossier images | array of Dossier Images | max items: 20 |
logo | Dossier logo filename | string | Get the filename from Dossier Logos endpoint |
countryCode | ISO country code | string |
Dossier Deletion
Example Request:
curl -X DELETE 'https://api.pricehubble.com/api/v1/dossiers/119a6ead-4ac4-4b4b-b264-195a2895618e?access_token=74126eab0a9048d993bda4b1b55ae074'
DELETE
dossiers/<dossier_id>
Deletes the dossier specified in the request path.
Dossier Search
POST
dossiers/search
Returns dossiers that match the specified search criteria.
Request
Example Request:
curl -X POST 'https://api.pricehubble.com/api/v1/dossiers/search?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'Content-Type: application/json' \
-d '{
"filters": {
"dealType": "sale",
"createdAt": {
"min": "2018-01-01"
},
"propertyType": [
{
"code": "apartment",
"subcode": "apartment_normal"
},
{
"code": "apartment",
"subcode": "apartment_attic"
}
],
"numberOfRooms": {
"min": 4,
"max": 4.5
},
},
"offset": 0,
"limit": 10,
"orderBy": {
"field": "createdAt",
"direction": "desc"
},
"countryCode": "CH"
}'
Field | Description | Type | Remarks |
---|---|---|---|
referenceLocation | Reference location of the search if ordered by distance. Distances of results are computed relative to this location | Location | Mandatory if orderBy contains distance |
filters | Allows to specify various search criteria | object | |
filters.createdAt | Filter on dossier creation date | object | |
filters.createdAt.min | Lower bound for dossier creation date | date | Date format: YYYY-MM-DD |
filters.createdAt.max | Upper bound for dossier creation date | date | Date format: YYYY-MM-DD |
filters.dealType | Filter on dossier deal type | enum | sale or rent |
filters.propertyType | Filter on property type. Matches dossiers which have one of the specified property types | array of PropertyTypes | |
filters.location | Filters on location. If multiple filters are provided, they are connected by a logical "or" | array of LocationFilters | |
filters.buildingYear | Filter on building year | object | |
filters.buildingYear.min | Lower bound for building year | integer | |
filters.buildingYear.max | Upper bound for building year | integer | |
filters.numberOfRooms | Filter on number of rooms | object | |
filters.numberOfRooms.min | Lower bound for number of rooms | float | |
filters.numberOfRooms.max | Upper bound for number of rooms | float | |
filters.livingArea | Filter on net living area | object | |
filters.livingArea.min | Lower bound for net living area, in m2 | integer | |
filters.livingArea.max | Upper bound for net living area, in m2 | integer | |
filters.askingSalePrice | Filter on asking sale price in the main currency of the dossier’s country | object | Only relevant if dealType is sale |
filters.askingSalePrice.min | Lower bound for asking sale price | integer | |
filters.askingSalePrice.max | Upper bound for asking sale price | integer | |
offset | Offset of the query (allows pagination) | integer | min: 0, max: 10'000, default: 0 |
limit | Maximum number of results to return | integer | min: 0, max: 300, default: 50 |
orderBy | Sort order | array of OrderByCriterions | |
countryCode | ISO country code | string | CH , DE and FR are currently supported |
Field | Description | Type | Remarks |
---|---|---|---|
circle | Location filter of type "circle". Matches dossiers which lie within the circle defined by center and radius |
object | |
circle.center | Center of the circle | Location | |
circle.radius | Radius of the circle, in m | integer | min: 0, max: 30'000, default: 20'000 |
Field | Description | Type | Remarks |
---|---|---|---|
field | Field by which to sort | enum | createdAt or distance |
direction | Sort direction | enum | asc (default) or desc |
Response
Example Response:
{
"items": [
{
"id": "c41924a0fb86b4e2e2da33f2ff468b72f2...",
"dealType": "sale",
"createdAt": "2018-07-31T16:06:05Z",
"modifiedAt": "2018-08-03T14:00:00Z",
"title": "Family home",
"description": "My description",
"askingSalePrice": 200000,
"numberOfRooms": 3,
"livingArea": 100,
"images": [{
"caption": "Front view",
"filename": "...b7879b37e.jpg",
"url": "https://storage.googleapis.com/.../...b7879b37e.jpg"
}],
"location" : {
"address": {
"city": "Oberglatt",
"houseNumber": "1",
"postCode": "8154",
"street": "Allmendstrasse"
},
"coordinates": {
"latitude": 47.4741020202637,
"longitude": 8.51667785644531
},
},
"propertyType": {
"code": "apartment",
"subcode": "apartment_normal"
},
},
...
],
}
Field | Description | Type | Remarks |
---|---|---|---|
items | List of matching dossiers | array of Dossiers | empty array if no results |
Field | Description | Type | Remarks |
---|---|---|---|
id | Technical ID of the dossier | string | |
dealType | Deal type of the dossier | enum | sale or rent |
createdAt | Creation date of the dossier | date-time | Format: YYYY-MM-DDTHH:MM:SSZ |
createdBy | Username of the dossier's creator | string | |
modifiedAt | Date of the dossier's last modification | date-time | Format: YYYY-MM-DDTHH:MM:SSZ |
title | Title of the dossier | string | |
description | Description of the dossier | string | |
askingSalePrice | Asking price of the dossier in the main currency of the dossier’s country | integer | Only present if dealType is sale |
numberOfRooms | Number of rooms of the property | float | |
livingArea | Net living area (SIA standard) of the property, in m2 | integer | |
landArea | Total area of the lot/parcel on which the house is standing, in m2 | integer | |
images | Images of the dossier | array of DossierImages | max items: 3 |
propertyType | Type of the property | PropertyType | |
location | Location of the dossier | Location | |
distance | Distance of the property to the reference location, in m | integer | Only returned if the request contains a referenceLocation |
Field | Description | Type | Remarks |
---|---|---|---|
filename | Name of the file | string | |
url | Url of the image | string | |
caption | Caption of the image | string |
Dossier Images
POST
dossiers/images
Uploads the specified image and returns a filename. The image can then be added to a dossier using the Dossier Creation endpoint.
Request
Example Request:
curl -X POST 'https://api.pricehubble.com/api/v1/dossiers/images?access_token=74126eab0a9048d993bda4b1b55ae074' \
-F 'image=@/path/to/image.jpg'
Field | Description | Type | Remarks |
---|---|---|---|
image | The file to upload | file | Only JPEG files are supported. Max size of 5MB . |
Response
Example Response:
{
"filename": "...e9742b1f0f55.jpg",
"url": "https://storage.googleapis.com/.../...e9742b1f0f55.jpg"
}
Field | Description | Type | Remarks |
---|---|---|---|
filename | Name of the file | string | |
url | Url of the uploaded image | string |
Dossier Logos
POST
dossiers/logos
Uploads the specified logo image and returns a filename. The logo image can then be added to a dossier using the Dossier Creation endpoint.
Request
Example Request:
curl -X POST 'https://api.pricehubble.com/api/v1/dossiers/logos?access_token=74126eab0a9048d993bda4b1b55ae074' \
-F 'image=@/path/to/image.png'
Field | Description | Type | Remarks |
---|---|---|---|
image | The file to upload | file | Only PNG files are supported. Max size of 1MB . |
Response
Example Response:
{
"filename": "...3fdb77531380.png",
"url": "https://storage.googleapis.com/.../...3fdb77531380.png"
}
Field | Description | Type | Remarks |
---|---|---|---|
filename | Name of the file | string | |
url | Url of the uploaded image | string |
Dossier Sharing
POST
dossiers/links
Generates a permalink for the specified dossier which will expire after the set number of days.
Request
Example Request:
curl -X POST 'https://api.pricehubble.com/api/v1/dossiers/links?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'Content-Type: application/json' \
-d '{
"dossierId": "2ec6d24e-8587-4ab5-a41e-0c4e4bd4faa7",
"daysToLive": 14,
"countryCode": "CH",
"locale": "en_GB"
}'
Field | Description | Type | Remarks |
---|---|---|---|
dossierId | Unique ID of the dossier | string | See Dossier Creation |
daysToLive | Number of days for the link to be valid | integer | min: 1, max: 365, default: 365 |
countryCode | ISO country code | string | |
locale | User locale | string |
Response
Example Response:
{
"id": "6ffce5fe-26bb-43ce-9a6e-56b93f5b351a",
"url": "https://dash.pricehubble.com/shared/dossier/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzaGFyZUlkIjoiNmZmY2U1ZmUtMjZiYi00M2NlLTlhNmUtNTZiOTNmNWIzNTFhIiwic2hhcmVUeXBlIjoidmFsdWF0aW9uIiwiY3JlYXRlZEJ5IjowLCJjcmVhdGVkQnlPcmciOjAsImxvY2FsZSI6ImVuX0dCIiwiaWF0IjoxNTQyMzczNzM3fQ.MwXyiGud88ogJBAsfaBFLCWTCDO7sh_B6kkiJFWQqoc"
}
Field | Description | Type | Remarks |
---|---|---|---|
id | Unique ID of the generated link | string | |
url | Shareable link to PriceHubble Dash. The UI language can be set by adding the suffix ?lang=en to the shareable link (Supported languages: de , en , fr , it , ja ) |
string |
Offer Search
POST
offers/search
Returns offers that match the specified search criteria.
Request
Example Request:
curl -X POST 'https://api.pricehubble.com/api/v1/offers/search?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'Content-Type: application/json' \
-d '{
"referenceLocation": {
"address": {
"city": "Zurich",
"houseNumber": "19",
"postCode": "8001",
"street": "Gerechtigkeitsgasse"
}
},
"filters": {
"dealType": "sale",
"startDate": {
"min": "2018-01-01"
},
"isActive": true,
"salePrice": {
"currency": "CHF",
"max": 1000000
},
"location": [
{
"circle": {
"center": {
"coordinates": {
"latitude": 47.36925,
"longitude": 8.531118
}
},
"radius": 30000
}
}
],
"propertyType": [
{
"code": "apartment",
"subcode": "apartment_normal"
},
{
"code": "apartment",
"subcode": "apartment_attic"
}
],
"livingArea": {
"min": 80,
"max": 110
},
"numberOfRooms": {
"min": 4,
"max": 4.5
},
"hasLift": true,
"hasParkingSpaces": true
},
"offset": 0,
"limit": 10,
"orderBy": [
{
"field": "distance"
},
{
"field": "startDate",
"direction": "desc"
}
],
"countryCode": "CH"
}'
Field | Description | Type | Remarks |
---|---|---|---|
referenceLocation | Reference location of the search. Distances of offers are computed relative to this location | Location | |
filters | Allows to specify various search criteria | object | |
filters.offerIds | IDs of offers returned in a previous call (see response.items[i].offerId ); can be used to get the latest state of the respective offers |
array of strings | min items: 0, max items: 10 |
filters.dealType | Filter on offer deal type | enum | sale or rent ; required unless offerIds is specified |
filters.startDate | Filter on offer start date | object | |
filters.startDate.min | Lower bound for offer start date | date | Date format: YYYY-MM-DD |
filters.startDate.max | Upper bound for offer start date | date | Date format: YYYY-MM-DD |
filters.isActive | Filter on offer's isActive flag |
boolean | |
filters.isNew | Filter on offer’s isNew flag |
boolean | |
filters.salePrice | Filter on offer sale price | object | Only relevant if filters.dealType is sale |
filters.salePrice.currency | Currency of the sale price filter | string | CHF or EUR |
filters.salePrice.min | Lower bound for offer sale price | integer | |
filters.salePrice.max | Upper bound for offer sale price | integer | |
filters.rentGross | Filter on rent gross | object | Only relevant if filters.dealType is rent |
filters.rentGross.currency | Currency of the rent gross filter | string | CHF or EUR |
filters.rentGross.min | Lower bound for rent gross | integer | |
filters.rentGross.max | Upper bound for rent gross | integer | |
filters.location | Filters on location. If multiple filters are provided, they are connected by a logical "or" | array of LocationFilters | |
filters.propertyType | Filter on property type. Matches offers which have one of the specified property types | array of PropertyTypes | |
filters.livingArea | Filter on net living area | object | |
filters.livingArea.min | Lower bound for net living area, in m2 | integer | |
filters.livingArea.max | Upper bound for net living area, in m2 | integer | |
filters.landArea | Filter on land area | object | |
filters.landArea.min | Lower bound for land area, in m2 | integer | min: 50, max: 5'000 |
filters.landArea.max | Upper bound for land area, in m2 | integer | min: 50, max: 5'000 |
filters.buildingYear | Filter on building year | object | |
filters.buildingYear.min | Lower bound for building year | integer | |
filters.buildingYear.max | Upper bound for building year | integer | |
filters.numberOfRooms | Filter on number of rooms | object | |
filters.numberOfRooms.min | Lower bound for number of rooms | float | |
filters.numberOfRooms.max | Upper bound for number of rooms | float | |
filters.noise.min | Lower bound for noise score | Score | Only available in CH . |
filters.noise.max | Upper bound for noise score | Score | Only available in CH . |
filters.slope.min | Lower bound for slope, in degrees | integer | min: 0, max: 90 Only available in CH . |
filters.slope.max | Upper bound for slope, in degrees | integer | min: 0, max: 90 Only available in CH . |
filters.distanceHospital.max | Upper bound for the distance to the closest hospital POI, in meters | integer | max: 2'000 |
filters.distanceGroceryStore.max | Upper bound for the distance to the closest grocery store POI, in meters | integer | max: 2'000 |
filters.distancePublicTransport.max | Upper bound for the distance to the closest public transport POI, in meters | integer | max: 2'000 |
filters.hasLift | Filter on the offer's hasLift flag |
boolean | |
filters.hasParkingSpaces | Filter on the offer's hasParkingSpaces flag |
boolean | |
filters.isWheelchairAccessible | Filter on the offer's isWheelchairAccessible flag |
boolean | |
includeShareableLinks | Return shareable links to PriceHubble Dash? | boolean | default: false Shareable links are currently only supported for CH country and sale deal type. |
offset | Offset of the query (allows pagination) | integer | min: 0, max: 1'000, default: 0 |
limit | Maximum number of results to return | integer | min: 0, max: 500, default: 10 |
orderBy | Sort order | array of OrderByCriterions | |
countryCode | ISO country code | string | CH , DE and FR are currently supported |
locale | User locale | string | Required if includeShareableLinks is set to true |
LocationFilter:
To filter by location, either a circle
or a divisionLevel*
must be provided.
If you would like to filter by division levels but only have an address or coordinates and don't know the official ID of the administrative division, you can use the Administrative Divisions endpoint to look up the administrative division and the respective ID.
Field | Description | Type | Remarks |
---|---|---|---|
circle | Location filter of type "circle". Matches offers which lie within the circle defined by center and radius |
object | |
circle.center | Center of the circle | Location | |
circle.radius | Radius of the circle, in m | integer | min: 0, max: 30'000, default: 20'000 |
divisionLevel6 | The official ID of the level 6 division | string | |
divisionLevel8 | The official ID of the level 8 division | string | |
divisionLevel100 | The official ID of the level 100 division | string |
Field | Description | Type | Remarks |
---|---|---|---|
field | Field by which to sort | enum | distance , startDate , salePrice or rentGross |
direction | Sort direction | enum | asc (default) or desc |
Response
Example Response:
{
"items": [
{
"offerId": "c41924a0fb86b4e2e2da33f2ff468b72f2...",
"dealType": "sale",
"startDate": "2018-07-31",
"isActive": true,
"isNew": true,
"title": "Wohnen mit Aus- und Weitsicht",
"description": "An toller Lage, angrenzend an die Landwirtschafts-...",
"images": [
{
"url": "https://storage.googleapis.com/.../...b7879b37e.jpg"
},
{
"url": "https://storage.googleapis.com/.../...0f771be42.jpg"
}
],
"contactInfo": {
"organization": {
"raw": "Bachmann & Partner Immobilien\nEglisau\n\n\n044 854 00 00"
}
},
"isExclusive": false,
"url": "https://example.org/realestate/offers/123",
"salePrice": 490000,
"currency": "CHF",
"address": {
"city": "Oberglatt",
"houseNumber": "1",
"postCode": "8154",
"street": "Allmendstrasse"
},
"coordinates": {
"latitude": 47.4741020202637,
"longitude": 8.51667785644531
},
"distance": 11708,
"floorNumber": 2,
"buildingYear": 1971,
"propertyType": {
"code": "apartment",
"subcode": "apartment_normal"
},
"livingArea": 95,
"numberOfRooms": 4.5,
"hasLift": true,
"hasParkingSpaces": true,
"numberOfIndoorParkingSpaces": 0,
"numberOfOutdoorParkingSpaces": 1,
"shareableLink": "https://dash.pricehubble.com/shared/offer/3e545020-fc94-4458-957a-9ab6caee4d2b/"
},
...
],
"totalItems": 18
}
Field | Description | Type | Remarks |
---|---|---|---|
totalItems | Total number of matching offers found | integer | min: 0 This field is capped and is only accurate if there are less than 1’500 results. If there are more results, this field will equal 1’500 |
items | List of matching offers | array of Offers | empty array if no results |
Field | Description | Type | Remarks |
---|---|---|---|
offerId | Technical ID of the offer | string | |
dealType | Deal type of the offer | enum | sale or rent |
startDate | Start date of the offer, i.e. date when the offer was first published | date | Format: YYYY-MM-DD |
endDate | End date of the offer, i.e. date when the offer disappeared from the market; only set for historical (inactive) offers | date | Format: YYYY-MM-DD |
daysOnMarket | Number of days that the offer has stayed on the market | integer | |
isActive | Is the offer still active, i.e. is the property still available? | boolean | |
isNew | Has the property never been used before, i.e. has it never been sold or rented out? | boolean | |
title | Title of the offer | string | |
description | Description of the offer | string | |
images | Images of the offer | array | |
contactInfo | Contact information for the offer | object | Possible subfields: raw , organization.raw , viewPerson.raw , inquiryPerson.raw |
isExclusive | Is the offer exclusively published on the PriceHubble API? | boolean | |
url | Original url of the offer ad | string | |
salePrice | Sale price of the offer | integer | Only present if dealType is sale |
rentNet | Monthly net rent of the offer | integer | Only present if dealType is rent |
rentGross | Monthly gross rent of the offer | integer | Only present if dealType is rent |
currency | Currency of the offer | string | CHF or EUR |
address | Address of the property | Address | |
coordinates | Coordinates of the property | Coordinates | |
distance | Distance of the property to the reference location, in m | integer | Only returned if the request contains a referenceLocation |
distanceHospital | Distance to the closest hospital POI, in m | integer | Only returned if the request contains filters.distanceHospital.max |
distanceGroceryStore | Distance to the closest grocery store POI, in m | integer | Only returned if the request contains filters.distanceGroceryStore.max |
distancePublicTransport | Distance to the closest public transport POI, in m | integer | Only returned if the request contains filters.distancePublicTransport.max |
floorNumber | Floor number | integer | |
buildingYear | Building year of the property | integer | |
propertyType | Type of the property | PropertyType | |
livingArea | Net living area (SIA standard) of the property, in m2 | integer | |
landArea | Total area of the lot/parcel on which the house is standing, in m2 | integer | |
volume | Volume of the property (house), in m3 | integer | |
numberOfRooms | Number of rooms of the property | float | |
noise | Property area noise levels score | Score | min: 0.0, max: 1.0 Only returned if the request contains noise filter |
slope | Property area slope, in degrees | float | min: 0.0, max: 90.0 Only returned if the request contains slope filter |
hasLift | Does the building have a lift? | boolean | |
hasParkingSpaces | Does the property have parking spaces? | boolean | |
isWheelchairAccessible | Is the property wheelchair accessible? | boolean | |
numberOfIndoorParkingSpaces | Number of indoor parking spaces | integer | |
numberOfOutdoorParkingSpaces | Number of outdoor parking spaces | integer | |
shareableLink | Shareable link to PriceHubble Dash. The UI language can be set by adding the suffix ?lang=en to the shareable link (Supported languages: de , en , fr , it , ja ) |
string |
Transaction Search
POST
transactions/search
Returns transactions that match the specified search criteria.
Request
Example Request:
curl -X POST 'https://api.pricehubble.com/api/v1/transactions/search?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'Content-Type: application/json' \
-d '{
"referenceLocation": {
"address": {
"city": "Paris",
"houseNumber": "5",
"postCode": "75013",
"street": "Parvis Alan Turing"
}
},
"filters": {
"transactionDate": {
"min": "2018-01-01"
},
"salePrice": {
"currency": "EUR",
"max": 1000000
},
"location": [
{
"circle": {
"center": {
"coordinates": {
"latitude": 48.833985,
"longitude": 2.371335
}
},
"radius": 30000
}
}
],
"propertyType": [
{
"code": "apartment",
"subcode": "apartment_normal"
},
{
"code": "apartment",
"subcode": "apartment_attic"
}
],
"livingArea": {
"min": 80,
"max": 110
},
"numberOfRooms": {
"min": 4,
"max": 4.5
}
},
"offset": 0,
"limit": 10,
"orderBy": [
{
"field": "distance"
},
{
"field": "transactionDate",
"direction": "desc"
}
],
"countryCode": "FR"
}'
Field | Description | Type | Remarks |
---|---|---|---|
referenceLocation | Reference location of the search. Distances of transactions are computed relative to this location | Location | |
filters | Allows to specify various search criteria | object | |
filters.transactionDate | Filter on transaction date | object | |
filters.transactionDate.min | Lower bound for transaction date | date | Date format: YYYY-MM-DD |
filters.transactionDate.max | Upper bound for transaction date | date | Date format: YYYY-MM-DD |
filters.salePrice | Filter on sale price | object | |
filters.salePrice.currency | Currency of the sale price filter | string | Only EUR is currently supported |
filters.salePrice.min | Lower bound for sale price | integer | |
filters.salePrice.max | Upper bound for sale price | integer | |
filters.location | Filters on location. If multiple filters are provided, they are connected by a logical "or" | array of LocationFilters | |
filters.propertyType | Filter on property type. Matches transactions which have one of the specified property types | array of PropertyTypes | |
filters.livingArea | Filter on net living area | object | |
filters.livingArea.min | Lower bound for net living area, in m2 | integer | |
filters.livingArea.max | Upper bound for net living area, in m2 | integer | |
filters.buildingYear | Filter on building year | object | |
filters.buildingYear.min | Lower bound for building year | integer | |
filters.buildingYear.max | Upper bound for building year | integer | |
filters.numberOfRooms | Filter on number of rooms | object | |
filters.numberOfRooms.min | Lower bound for number of rooms | float | |
filters.numberOfRooms.max | Upper bound for number of rooms | float | |
filters.hasParkingSpaces | Filter on the transaction's hasParkingSpaces flag |
boolean | |
filters.isNew | Filter on the transaction's isNew flag |
boolean | |
offset | Offset of the query (allows pagination) | integer | min: 0, max: 1'000, default: 0 |
limit | Maximum number of results to return | integer | min: 0, max: 500, default: 10 |
orderBy | Sort order | array of OrderByCriterions | |
countryCode | ISO country code | string | Only FR is currently supported |
LocationFilter:
To filter by location, either a circle
or a divisionLevel*
must be provided.
If you would like to filter by division levels but only have an address or coordinates and don't know the official ID of the administrative division, you can use the Administrative Divisions endpoint to look up the administrative division and the respective ID.
Field | Description | Type | Remarks |
---|---|---|---|
circle | Location filter of type "circle". Matches transactions which lie within the circle defined by center and radius |
object | |
circle.center | Center of the circle | Location | |
circle.radius | Radius of the circle, in m | integer | min: 0, max: 30'000, default: 20'000 |
divisionLevel6 | The official ID of the level 6 division | string | |
divisionLevel8 | The official ID of the level 8 division | string | |
divisionLevel100 | The official ID of the level 100 division | string |
Field | Description | Type | Remarks |
---|---|---|---|
field | Field by which to sort | enum | distance , transactionDate , or salePrice |
direction | Sort direction | enum | asc (default) or desc |
Response
Example Response:
{
"items": [
{
"address": {
"city": "PARIS ",
"houseNumber": "181",
"postCode": "75013",
"street": "RUE DU CHEVALERET"
},
"buildingYear": 1958,
"coordinates": {
"latitude": 48.833667755127,
"longitude": 2.36874389648438
},
"currency": "EUR",
"distance": 193,
"floorNumber": 11,
"hasParkingSpaces": false,
"isNew": false,
"livingArea": 83,
"numberOfParkingSpaces": 0,
"numberOfRooms": 4,
"propertyType": {
"code": "apartment",
"subcode": "apartment_normal"
},
"salePrice": 600000,
"transactionDate": "2018-05-01",
"transactionId": "FR-532e76828877d9ec9d67bf738f5956734c3526830b3f3eba58019639aa6bccb6"
},
...
],
"totalItems": 5068
}
Field | Description | Type | Remarks |
---|---|---|---|
totalItems | Total number of matching transactions found | integer | min: 0 This field is capped and is only accurate if there are less than 1’500 results. If there are more results, this field will equal 1’500 |
items | List of matching transactions | array of Transactions | empty array if no results |
Field | Description | Type | Remarks |
---|---|---|---|
transactionId | Technical ID of the transaction | string | |
transactionDate | Transaction date | date | Format: YYYY-MM-DD |
salePrice | Transaction price | integer | |
currency | Currency of the transaction | string | |
address | Address of the property | Address | |
coordinates | Coordinates of the property | Coordinates | |
distance | Distance of the property to the reference location, in m | integer | Only returned if the request contains a referenceLocation |
floorNumber | Floor number | integer | |
buildingYear | Building year of the property | integer | |
propertyType | Type of the property | PropertyType | |
livingArea | Net living area (SIA standard) of the property, in m2 | integer | |
landArea | Total area of the lot/parcel on which the house is standing, in m2 | integer | |
numberOfRooms | Number of rooms of the property | float | |
hasParkingSpaces | Does the property have parking spaces? | boolean | |
numberOfParkingSpaces | Number of parking spaces | integer | |
isNew | Has the property never been used before, i.e. has it never been sold or rented out? | boolean |
Offer Statistics Light
POST
offers/statistics_light
Returns a percentage of offers (percentile rank) of the same type (apartment
or house
) in the given location which are cheaper than the provided price (salePrice
).
If for a salePrice
of 750’000
the returned percentileRank
is 32
that means in the selected location 32% of similar properties are cheaper and 68% of similar properties are more expensive.
The location currently can only be specified by a post code (divisionLevel100
).
This endpoint is a simplified version of Offer Statistics. For advanced requirements, use that endpoint instead.
Request
Example Request:
curl -X POST 'https://api.pricehubble.com/api/v1/offers/statistics_light?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'Content-Type: application/json' \
-d '{
"salePrice": 750000,
"divisionLevel100": "8001",
"propertyType": "apartment",
"countryCode": "CH"
}'
Field | Description | Type | Remarks |
---|---|---|---|
salePrice | Price to which the offers will be compared against | integer | |
propertyType | enum | apartment or house |
|
divisionLevel100 | Postal code / official ID of the level 100 division | string | |
countryCode | ISO country code | string | AT , CH , DE and FR are currently supported |
Response
Example Response:
{
"percentileRank": 32
}
Field | Description | Type | Remarks |
---|---|---|---|
percentileRank | Percentage of offers that are cheaper in the specified area than the provided salePrice |
integer |
Offer Statistics
POST
offers/statistics
Returns offer statistics for the specified administrative division and time period. For example, average yearly offer prices in Zurich for a time period between 2010 and 2014 can be obtained.
Statistics can only be obtained for one administrative division at a time. If you want to obtain statistics for multiple administrative divisions, you need to make multiple calls.
Request
Example Request 1:
curl -X POST 'https://api.pricehubble.com/api/v1/offers/statistics?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'Content-Type: application/json' \
-d '{
"statistics": [
{
"metric": "rent_gross",
"type": "mean"
},
{
"metric": "rent_gross",
"type": "count"
},
{
"metric": "rent_gross",
"type": "percentile",
"parameters": {
"percentileRank": 50
}
},
{
"metric": "rent_gross",
"type": "percentile_rank",
"parameters": {
"percentileValue": 2350
}
},
{
"metric": "rent_gross",
"type": "percentile_rank",
"parameters": {
"percentileValue": 2580
}
},
{
"metric": "days_on_market",
"type": "percentile",
"parameters": {
"percentileRank": 50
}
}
],
"filters": {
"dealType": "rent",
"propertyType": "apartment",
"divisionLevel100": "8001",
"startDate": {
"min": "2017-01",
"max": "2018-12"
}
},
"countryCode": "CH"
}'
Example Request 2 (group by year):
curl -X POST 'https://api.pricehubble.com/api/v1/offers/statistics?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'Content-Type: application/json' \
-d '{
"statistics": [
{
"metric": "rent_gross",
"type": "count"
}
],
"groupBy": {
"field": "start_date",
"period": "year"
},
"filters": {
"dealType": "rent",
"propertyType": "apartment",
"divisionLevel100": "8001",
"startDate": {
"min": "2017-01",
"max": "2018-12"
}
},
"countryCode": "CH"
}'
Example Request 3 (group by price):
curl -X POST 'https://api.pricehubble.com/api/v1/offers/statistics?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'Content-Type: application/json' \
-d '{
"statistics": [
{
"metric": "rent_gross",
"type": "count"
}
],
"groupBy": {
"field": "rent_gross",
"groups": [
{
"upperBound": 1000
},
{
"lowerBound": 1000,
"upperBound": 2000
},
{
"lowerBound": 2000
}
]
},
"filters": {
"dealType": "rent",
"propertyType": "apartment",
"divisionLevel100": "8001",
"startDate": {
"min": "2017-01",
"max": "2018-12"
}
},
"countryCode": "CH"
}'
Exactly one divisionLevel* must be provided. If you only have an address or coordinates and don't know the official ID of the administrative division, you can use the Administrative Divisions endpoint to look up the administrative division and the respective ID.
Field | Description | Type | Remarks |
---|---|---|---|
statistics | array of objects | ||
statistics[i].type | enum | mean , count , percentile or percentile_rank |
|
statistics[i].metric | enum | sale_price , sale_price_per_square_meter , rent_gross , rent_gross_per_square_meter , rent_net , rent_net_per_square_meter , living_area , number_of_rooms or days_on_market |
|
statistics[i].parameters | object | Parameters for the chosen statistic type, currently only required by percentile & percentile_rank . |
|
statistics[i].parameters.percentileRank | integer | - min: 0, max: 100 Only required by percentile statistic type (try 25 , 50 , 75 or 95 to get the 25th, 50th (median), 75th or 95th percentiles) |
|
statistics[i].parameters.percentileValue | integer | - min: 0 Only required by percentile_rank statistic type (the percentile rank of a value relative to the list of all values) |
|
groupBy | object | ||
groupBy.field | The field by which to group the results | enum | sale_price , sale_price_per_square_meter , rent_gross , rent_gross_per_square_meter , rent_net , rent_net_per_square_meter , living_area , number_of_rooms , start_date or days_on_market |
groupBy.groups | List of explicit groups | array | required if groupBy.field is sale_price , sale_price_per_square_meter , rent_gross , rent_gross_per_square_meter , rent_net , rent_net_per_square_meter , living_area , number_of_rooms or days_on_market ; min items: 1, max items: 24 |
groupBy.groups[i] | object | Either lowerBound or upperBound is required |
|
groupBy.groups[i].lowerBound | float or integer | ||
groupBy.groups[i].upperBound | float or integer | ||
groupBy.period | enum | month , quarter or year ; required if groupBy.field is start_date |
|
filters | object | ||
filters.dealType | enum | sale or rent |
|
filters.startDate | Filter on the offers' start date (= first publishing date) | object | |
filters.startDate.min | string | Format: YYYY-MM | |
filters.startDate.max | string | Format: YYYY-MM | |
filters.coordinates | Filter by location from the given set of coordinates | Coordinates | Requires filters.radius to be passed along |
filters.radius | Radius of the location filter, in m | integer | min: 0, max: 10'000 Requires filters.coordinates to be passed along |
filters.isActive | Filter on offer's isActive flag |
boolean | |
filters.isNew | Filter on offer's isNew flag |
boolean | |
filters.salePrice | Filter on offer sale price | object | Only relevant if filters.dealType is sale |
filters.salePrice.currency | Currency of the sale price filter | string | CHF or EUR |
filters.salePrice.min | Lower bound for offer sale price | integer | |
filters.salePrice.max | Upper bound for offer sale price | integer | |
filters.rentGross | Filter on rent gross | object | Only relevant if filters.dealType is rent |
filters.rentGross.currency | Currency of the rent gross filter | string | CHF or EUR |
filters.rentGross.min | Lower bound for rent gross | integer | |
filters.rentGross.max | Upper bound for rent gross | integer | |
filters.propertyType | enum | apartment or house |
|
filters.livingArea | Filter on net living area | object | |
filters.livingArea.min | Lower bound for net living area, in m2 | integer | |
filters.livingArea.max | Upper bound for net living area, in m2 | integer | |
filters.buildingYear | Filter on building year | object | |
filters.buildingYear.min | Lower bound for building year | integer | |
filters.buildingYear.max | Upper bound for building year | integer | |
filters.numberOfRooms | Filter on number of rooms | object | |
filters.numberOfRooms.min | Lower bound for number of rooms | float | |
filters.numberOfRooms.max | Upper bound for number of rooms | float | |
filters.divisionLevel6 | The official ID of the level 6 division | string | |
filters.divisionLevel8 | The official ID of the level 8 division | string | |
filters.divisionLevel100 | The official ID of the level 100 division | string | |
countryCode | ISO country code | string | AT , CH , DE and FR are currently supported |
Response
Example Response 1:
{
"items": [
{
"statistics": [
{
"metric": "rent_gross",
"type": "mean",
"value": 3170.22
},
{
"metric": "rent_gross",
"type": "count",
"value": 630
},
{
"metric": "rent_gross",
"type": "percentile",
"parameters": {
"percentileRank": 50
},
"value": 2840.0
},
{
"metric": "rent_gross",
"type": "percentile_rank",
"parameters": {
"percentileValue": 2350
},
"value": 33.81
},
{
"metric": "rent_gross",
"type": "percentile_rank",
"parameters": {
"percentileValue": 2580
},
"value": 42.22
},
{
"metric": "days_on_market",
"type": "percentile",
"parameters": {
"percentileRank": 50
},
"value": 14.0
}
]
}
]
}
Example Response 2 (group by year):
{
"items": [
{
"groupId": "2017",
"statistics": [
{
"metric": "rent_gross",
"type": "count",
"value": 229
}
]
},
{
"groupId": "2018",
"statistics": [
{
"metric": "rent_gross",
"type": "count",
"value": 401
}
]
}
]
}
Example Response 3 (group by price):
{
"items": [
{
"groupId": "0",
"groupUpperBound": 1000,
"statistics": [
{
"metric": "rent_gross",
"type": "count",
"value": 27
}
]
},
{
"groupId": "1",
"groupLowerBound": 1000,
"groupUpperBound": 2000,
"statistics": [
{
"metric": "rent_gross",
"type": "count",
"value": 137
}
]
},
{
"groupId": "2",
"groupLowerBound": 2000,
"statistics": [
{
"metric": "rent_gross",
"type": "count",
"value": 466
}
]
}
]
}
Prices are returned in the country's main currency. Rents are per month.
Field | Description | Type | Remarks |
---|---|---|---|
items | List of statistics; per “group" if grouping was requested | array of objects | If grouping by start_date was requested, the list is sorted by time in ascending order and the length of the array is equal to the number of periods between request.filters.startDate.min and request.filters.startDate.max ; if any other grouping was requested the order corresponds to the order of the groups in the request (i.e. the order of request.groupBy.groups ) and the length of the array is equal to the length of request.groupBy.groups |
items[i].groupId | string | E.g. "2018-01", "2018-Q1" or "2018" if grouping by start_date was requested, or the (zero-based) index of the group (as a string) if any other grouping was requested |
|
items[i].groupLowerBound | float or integer | Corresponds to what was set in request.groupBy.groups[i].lowerBound |
|
items[i].groupUpperBound | float or integer | Corresponds to what was set in request.groupBy.groups[i].upperBound |
|
items[i].statistics | array of objects | ||
items[i].statistics[i].type | enum | mean , count , percentile or percentile_rank |
|
items[i].statistics[i].metric | enum | sale_price , sale_price_per_square_meter , rent_gross , rent_gross_per_square_meter , rent_net , rent_net_per_square_meter , living_area , number_of_rooms or days_on_market |
|
items[i].statistics[i].parameters | Parameters for the chosen statistic type, if provided in the request | object | |
items[i].statistics[i].value | Value of the requested statistic | float or integer | Not set if there is not enough data to compute the requested statistic for the requested group |
Transaction Statistics
POST
transactions/statistics
Returns transaction statistics for the specified administrative division and time period. For example, average yearly sale prices in Zurich for a time period between 2010 and 2014 can be obtained.
Statistics can only be obtained for one administrative division at a time. If you want to obtain statistics for multiple administrative divisions, you need to make multiple calls.
Request
Example Request 1:
curl -X POST 'https://api.pricehubble.com/api/v1/transactions/statistics?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'Content-Type: application/json' \
-d '{
"statistics": [
{
"metric": "sale_price",
"type": "mean"
},
{
"metric": "sale_price",
"type": "count"
},
{
"metric": "sale_price",
"type": "percentile",
"parameters": {
"percentileRank": 50
}
},
{
"metric": "sale_price",
"type": "percentile_rank",
"parameters": {
"percentileValue": 750000
}
},
{
"metric": "sale_price",
"type": "percentile_rank",
"parameters": {
"percentileValue": 1000000
}
}
],
"filters": {
"propertyType": "apartment",
"divisionLevel8": "261",
"transactionDate": {
"min": "2017-01",
"max": "2018-12"
}
},
"countryCode": "CH"
}'
Example Request 2 (group by year):
curl -X POST 'https://api.pricehubble.com/api/v1/transactions/statistics?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'Content-Type: application/json' \
-d '{
"statistics": [
{
"metric": "sale_price",
"type": "count"
}
],
"groupBy": {
"field": "transaction_date",
"period": "year"
},
"filters": {
"propertyType": "apartment",
"divisionLevel8": "261",
"transactionDate": {
"min": "2017-01",
"max": "2018-12"
}
},
"countryCode": "CH"
}'
Example Request 3 (group by price):
curl -X POST 'https://api.pricehubble.com/api/v1/transactions/statistics?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'Content-Type: application/json' \
-d '{
"statistics": [
{
"metric": "sale_price",
"type": "count"
}
],
"groupBy": {
"field": "sale_price",
"groups": [
{
"upperBound": 1000000
},
{
"lowerBound": 1000000,
"upperBound": 2000000
},
{
"lowerBound": 2000000
}
]
},
"filters": {
"propertyType": "apartment",
"divisionLevel8": "261",
"transactionDate": {
"min": "2017-01",
"max": "2018-12"
}
},
"countryCode": "CH"
}'
Either filters.coordinates
and filters.radius
or exactly one filters.divisionLevel*
must be provided.
If you would like to filter by division levels but only have an address or coordinates and don't know the official ID of the administrative division, you can use the Administrative Divisions endpoint to look up the administrative division and the respective ID.
Field | Description | Type | Remarks |
---|---|---|---|
statistics | array of objects | ||
statistics[i].type | enum | mean , count , percentile or percentile_rank |
|
statistics[i].metric | enum | sale_price , sale_price_per_square_meter , living_area or number_of_rooms |
|
statistics[i].parameters | object | Parameters for the chosen statistic type, currently only required by percentile & percentile_rank . |
|
statistics[i].parameters.percentileRank | integer | - min: 0, max: 100 Only required by percentile statistic type (try 25 , 50 , 75 or 95 to get the 25th, 50th (median), 75th or 95th percentiles) |
|
statistics[i].parameters.percentileValue | integer | - min: 0 Only required by percentile_rank statistic type (the percentile rank of a value relative to the list of all values) |
|
groupBy | object | ||
groupBy.field | The field by which to group the results | enum | sale_price , sale_price_per_square_meter , living_area , number_of_rooms or transaction_date |
groupBy.groups | List of explicit groups | array | required if groupBy.field is sale_price , sale_price_per_square_meter , living_area or number_of_rooms ; min items: 1, max items: 24 |
groupBy.groups[i] | object | Either lowerBound or upperBound is required |
|
groupBy.groups[i].lowerBound | float or integer | ||
groupBy.groups[i].upperBound | float or integer | ||
groupBy.period | enum | month , quarter or year ; required if groupBy.field is transaction_date |
|
filters | object | ||
filters.transactionDate | Filter on the transactions' sale date | object | |
filters.transactionDate.min | string | Format: YYYY-MM | |
filters.transactionDate.max | string | Format: YYYY-MM | |
filters.coordinates | Filter by location from the given set of coordinates | Coordinates | Requires filters.radius to be passed along |
filters.radius | Radius of the location filter, in m | integer | min: 0, max: 10'000 Requires filters.coordinates to be passed along |
filters.divisionLevel6 | The official ID of the level 6 division | string | |
filters.divisionLevel8 | The official ID of the level 8 division | string | |
filters.divisionLevel100 | The official ID of the level 100 division | string | |
filters.salePrice | Filter on transaction sale price | object | |
filters.salePrice.currency | Currency of the sale price filter | string | CHF or EUR |
filters.salePrice.min | Lower bound for transaction sale price | integer | |
filters.salePrice.max | Upper bound for transaction sale price | integer | |
filters.propertyType | enum | apartment or house |
|
filters.livingArea | Filter on net living area | object | |
filters.livingArea.min | Lower bound for net living area, in m2 | integer | |
filters.livingArea.max | Upper bound for net living area, in m2 | integer | |
filters.buildingYear | Filter on building year | object | |
filters.buildingYear.min | Lower bound for building year | integer | |
filters.buildingYear.max | Upper bound for building year | integer | |
filters.numberOfRooms | Filter on number of rooms | object | |
filters.numberOfRooms.min | Lower bound for number of rooms | float | |
filters.numberOfRooms.max | Upper bound for number of rooms | float | |
filters.isNew | Filter on transaction's isNew flag |
boolean | |
countryCode | ISO country code | string | Only CH and FR are currently supported |
Response
Example Response 1:
{
"items": [
{
"statistics": [
{
"metric": "sale_price",
"type": "mean",
"value": 1328515.26
},
{
"metric": "sale_price",
"type": "count",
"value": 544
},
{
"metric": "sale_price",
"parameters": {
"percentileRank": 50
},
"type": "percentile",
"value": 1200000.0
},
{
"metric": "sale_price",
"parameters": {
"percentileValue": 750000
},
"type": "percentile_rank",
"value": 13.6
},
{
"metric": "sale_price",
"parameters": {
"percentileValue": 1000000
},
"type": "percentile_rank",
"value": 34.38
}
]
}
]
}
Example Response 2 (group by year):
{
"items": [
{
"groupId": "2017",
"statistics": [
{
"metric": "sale_price",
"type": "count",
"value": 265
}
]
},
{
"groupId": "2018",
"statistics": [
{
"metric": "sale_price",
"type": "count",
"value": 279
}
]
}
]
}
Example Response 3 (group by price):
{
"items": [
{
"groupId": "0",
"groupUpperBound": 1000000,
"statistics": [
{
"metric": "sale_price",
"type": "count",
"value": 187
}
]
},
{
"groupId": "1",
"groupLowerBound": 1000000,
"groupUpperBound": 2000000,
"statistics": [
{
"metric": "sale_price",
"type": "count",
"value": 290
}
]
},
{
"groupId": "2",
"groupLowerBound": 2000000,
"statistics": [
{
"metric": "sale_price",
"type": "count",
"value": 67
}
]
}
]
}
Prices are returned in the country's main currency.
Field | Description | Type | Remarks |
---|---|---|---|
items | List of statistics; per “group" if grouping was requested | array of objects | If grouping by transaction_date was requested, the list is sorted by time in ascending order and the length of the array is equal to the number of periods between request.filters.transactionDate.min and request.filters.transactionDate.max ; if any other grouping was requested the order corresponds to the order of the groups in the request (i.e. the order of request.groupBy.groups ) and the length of the array is equal to the length of request.groupBy.groups |
items[i].groupId | string | E.g. "2018-01", "2018-Q1" or "2018" if grouping by transaction_date was requested, or the (zero-based) index of the group (as a string) if any other grouping was requested |
|
items[i].groupLowerBound | float or integer | Corresponds to what was set in request.groupBy.groups[i].lowerBound |
|
items[i].groupUpperBound | float or integer | Corresponds to what was set in request.groupBy.groups[i].upperBound |
|
items[i].statistics | array of objects | ||
items[i].statistics[i].type | enum | mean , count , percentile or percentile_rank |
|
items[i].statistics[i].metric | enum | sale_price , sale_price_per_square_meter , living_area or number_of_rooms |
|
items[i].statistics[i].parameters | Parameters for the chosen statistic type, if provided in the request | object | |
items[i].statistics[i].value | Value of the requested statistic | float or integer | Not set if there is not enough data to compute the requested statistic for the requested group |
Administrative Divisions
POST
location/divisions
Returns the administrative divisions which enclose the point specified by the given coordinates or by the given address.
The levels are based on the OSM administrative divisions. The following tables show the level designations for each country.
AT:
Level | Level Designation | Example | |
---|---|---|---|
(Local) Name | Official ID | ||
4 | Bundesland | Burgenland | 1 |
6 | Politischer Bezirk | Eisenstadt(Stadt) | 101 |
8 | Gemeinde | Eisenstadt | 10101 |
100 | Postleitzahl | 7000 | 7000 |
CH:
Level | Level Designation | Example | ||||
---|---|---|---|---|---|---|
English | German | French | Italian | (Local) Name | Official ID | |
4 | Canton | Kanton | Canton | Cantone | Zürich | 1 |
6 | District | Bezirk | District | Distretto | Zürich | 112 |
8 | Municipality | Gemeinde | Commune | Comune | Zürich | 261 |
100 | Postal code | Postleitzahl | Code postal | Codice postale | Zürich | 8001 |
DE:
Level | Level Designation | Example | |
---|---|---|---|
(Local) Name | Official ID | ||
4 | Bundesland | Hamburg | 02 |
6 | Landkreis / Kreis / Kreisfreie Stadt / Stadtkreis | Hamburg | 02000 |
8 | Stadt / Gemeinde | Hamburg | 020000000000 |
11 | Stadtviertel | HafenCity | 02000000034 |
100 | Postleitzahl | 20354 | 20354 |
FR:
Level | Level Designation | Example | |
---|---|---|---|
(Local) Name | Official ID | ||
4 | Region | Île-de-France | 11 |
6 | Département | Paris | 75 |
8 | Commune | Paris | 75056 |
9 | Arrondissement | Paris 7e Arrondissement | 75107 |
11 | IRIS | Champ de Mars | 751072812 |
100 | Code postal | 75013 | 75013 |
Request
Example Request:
curl -X POST 'https://api.pricehubble.com/api/v1/location/divisions?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'Content-Type: application/json' \
-d '{
"location": {
"coordinates": {
"latitude": 47.3968601,
"longitude": 8.5153549
},
"address": {
"postCode": "8037",
"city": "Zurich",
"street": "Nordstrasse",
"houseNumber": "391"
}
},
"countryCode": "CH"
}'
Field | Description | Type | Remarks |
---|---|---|---|
location | Location for which information should be retrieved | Location | |
countryCode | ISO country code | string | AT , CH , DE and FR are currently supported |
Response
Example Response:
{
"coordinates": {
"latitude": 47.3968601,
"longitude": 8.5153549
},
"divisionLevel4": {
"officialId": "1",
"name": "Zürich",
"levelDesignation": "Kanton",
"geometry": {
"coordinates": [
[8.41007342863389, 47.2483758360245],
...
],
"type": "Polygon"
}
},
"divisionLevel6": {
"officialId": "112",
"name": "Zürich",
"levelDesignation": "Bezirk",
"geometry": {
"coordinates": [
[8.59715430748838, 47.4060055090607],
...
],
"type": "Polygon"
}
},
"divisionLevel8": {
"officialId": "261",
"name": "Zürich",
"levelDesignation": "Stadt",
"geometry": {
"coordinates": [
[8.5736748773714, 47.4200362257283],
...
],
"type": "Polygon"
}
},
"divisionLevel100": {
"officialId": "8037",
"name": "8037",
"levelDesignation": "Postleitzahl",
"geometry": {
"coordinates": [
[8.51312630529578, 47.3944516312076],
...
],
"type": "Polygon"
}
}
}
Field | Description | Type | Remarks |
---|---|---|---|
coordinates | Coordinates resolved from the address specified in the request (or coordinates from the request if they have been provided) | Coordinates | |
divisionLevel4 | The level 4 division | Division | |
divisionLevel6 | The level 6 division | Division | |
divisionLevel8 | The level 8 division | Division | |
divisionLevel9 | The level 9 division | Division | Only available in FR |
divisionLevel11 | The level 11 division | Division | Only available in FR and DE |
divisionLevel100 | The level 100 division | Division |
Field | Description | Type | Remarks |
---|---|---|---|
officialId | The official ID of the administrative division as defined by the administration/government | string | |
name | The name of the administrative division | string | The name is returned in the local language (e.g. "Genève" and not "Geneva" is returned) |
levelDesignation | The administrative division level designation | string | The designation is returned in the local language (e.g. "Stadt" and not "City" is returned for the city of Zürich) |
geometry | The geometry of the administrative division | GeoJSON Polygon or GeoJSON MultiPolygon. |
Administrative Division Children
POST
location/division_children
Returns administrative divisions (children) of the specified child level intersecting with the specified administrative division (parent). Results are sorted by name.
Request
Example Request:
curl -X POST 'https://api.pricehubble.com/api/v1/location/division_children?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'Content-Type: application/json' \
-d '{
"divisionLevel8": "261",
"childLevel": 100,
"countryCode": "CH"
}'
Exactly one divisionLevel* must be provided. If you only have an address or coordinates and don't know the official ID of the administrative division, you can use the Administrative Divisions endpoint to look up the administrative division and the respective ID.
Field | Description | Type | Remarks |
---|---|---|---|
divisionLevel2 | The official ID of the level 2 division | string | |
divisionLevel4 | The official ID of the level 4 division | string | |
divisionLevel6 | The official ID of the level 6 division | string | |
divisionLevel8 | The official ID of the level 8 division | string | |
divisionLevel9 | The official ID of the level 9 division | string | Only available in FR |
divisionLevel11 | The official ID of the level 11 division | string | Only available in FR and DE |
childLevel | The level of the division children to return | integer | 4 , 6 , 8 , 9 , 11 or 100 |
returnGeometries | Whether to return the geometries of each division child | boolean | default: false |
countryCode | ISO country code | string |
Response
Example Response:
{
"items": [
{
"geometry": {
"coordinates": [[
[8.54210712309264, 47.3632042551477],
...
]],
"type": "Polygon"
},
"levelDesignation": "Postleitzahl",
"name": "8001",
"officialId": "8001"
},
{
"geometry": {
"coordinates": [[
[8.52343289124586, 47.3524742860765],
...
]],
"type": "Polygon"
},
"levelDesignation": "Postleitzahl",
"name": "8002",
"officialId": "8002"
},
...
]
}
Field | Description | Type | Remarks |
---|---|---|---|
items | List of administrative divisions of a given level | array | At most 200 items are returned. |
items[i].officialId | The official ID of the administrative division as defined by the administration/government | string | |
items[i].name | The name of the administrative division | string | The name is returned in the local language (e.g. "Genève" and not "Geneva" is returned) |
items[i].levelDesignation | The administrative division level designation | string | The designation is returned in the local language (e.g. "Stadt" and not "City" is returned for the city of Zürich) |
items[i].geometry | Geometry of the administrative division | GeoJSON Polygon or GeoJSON MultiPolygon. Returned only when returnGeometries is set to true . |
Socio-Economics
POST
socio_economics
Returns socio-economics data of a given type for the list of specified administrative divisions and time period. For example, population growth could be compared in two municipalities over the years.
Request
Example Request:
curl -X POST 'https://api.pricehubble.com/api/v1/socio_economics?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'Content-Type: application/json' \
-d '{
"type": "education_levels",
"divisionsLevel6": [
"103",
"112"
],
"years": {
"min": 2017,
"max": 2017
},
"countryCode": "CH"
}'
Exactly one divisionsLevel* must be provided. If you only have an address or coordinates and don't know the official ID of the administrative division, you can use the Administrative Divisions endpoint to look up the administrative division and the respective ID.
Field | Description | Type | Remarks |
---|---|---|---|
type | Socio-Economics type | string | |
divisionsLevel4 | Official IDs of the level 4 division | array of strings | |
divisionsLevel6 | Official IDs of the level 6 division | array of strings | |
divisionsLevel8 | Official IDs of the level 8 division | array of strings | |
divisionsLevel9 | Official IDs of the level 9 division | array of strings | Only available in FR |
divisionsLevel11 | Official IDs of the level 11 division | array of strings | Only available in FR and DE |
divisionsLevel100 | Official IDs of the level 100 division | array of strings | Not available in DE |
years | Years filter on socio-economics data | object | |
years.min | integer | ||
years.max | integer | ||
countryCode | ISO country code | string | CH , DE and FR are currently supported |
Response
Example Response:
{
"divisions":[
{
"officialId": "103",
"years":[
{
"values":[
{
"absoluteValue": 5000,
"relativeValue": 0.25,
"subtype": "compulsory_education"
},
{
"absoluteValue": 1000,
"relativeValue": 0.05,
"subtype": "no_education"
},
{
"absoluteValue": 4000,
"relativeValue": 0.2,
"subtype": "tertiary_education"
},
{
"absoluteValue": 10000,
"relativeValue": 0.5,
"subtype": "upper_secondary_education"
}
],
"year":2017
}
]
},
{
"officialId": "112",
"years":[
{
"values":[
{
"absoluteValue": 30000,
"relativeValue": 0.3,
"subtype": "compulsory_education"
},
{
"absoluteValue": 10000,
"relativeValue": 0.1,
"subtype": "no_education"
},
{
"absoluteValue": 20000,
"relativeValue": 0.2,
"subtype": "tertiary_education"
},
{
"absoluteValue": 40000,
"relativeValue": 0.4,
"subtype": "upper_secondary_education"
}
],
"year": 2017
}
]
}
]
}
Field | Description | Type | Remarks |
---|---|---|---|
divisions | List of matching socio-economics data grouped by administrative divisions and years | array | |
divisions[i].officialId | Official ID of the administrative division for the returned socio-economics data group | string | |
divisions[i].years | List of socio-economics data, grouped and sorted by year in ascending order for the given administrative division | array | |
divisions[i].years[i].values | List of socio-economics values, per socio-economics subtype, if any | array | |
divisions[i].years[i].values[i].subtype | A socio-economics subtype if one exists for the requested type | string | |
divisions[i].years[i].values[i].absoluteValue | Absolute value for the given year, type and subtype | float | |
divisions[i].years[i].values[i].relativeValue | Relative value compared to the other subtypes | float | min: 0, max: 1 |
divisions[i].years[i].year | The year of the returned socio-economics data | integer |
Socio-Economics Types
POST
socio_economics_types
Returns meta information (unit, available subtypes, subtype translations) about the specified socio-economics types.
Request
Example Request:
curl -X POST 'https://api.pricehubble.com/api/v1/socio_economics_types?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'Content-Type: application/json' \
-d '{
"types": [
"population_size",
"foreign_nationals",
"education_levels"
],
"countryCode": "CH"
}'
Field | Description | Type | Remarks |
---|---|---|---|
types | A list of socio-economics types | array of strings | |
countryCode | ISO country code | string | CH , DE and FR are currently supported |
Response
Example Response:
{
"types":[
{
"code": "population_size"
},
{
"code": "foreign_nationals",
"unit": "%"
},
{
"code": "education_levels",
"subtypes":[
{
"code": "no_education",
"translations":[
{
"language": "en",
"value": "uneducated"
},
{
"language": "de",
"value": "ungebildet"
},
{
"language": "fr",
"value": "ignare"
}
]
},
{
"code": "compulsory_education",
"translations":[
{
"language": "en",
"value": "compulsory education"
},
{
"language": "de",
"value": "obligatorische schule"
},
{
"language": "fr",
"value": "scolarité obligatoire"
}
]
},
{
"code": "upper_secondary_education",
"translations":[
{
"language": "en",
"value": "upper_secondary_education"
},
{
"language": "de",
"value": "sekundarstufe ii"
},
{
"language": "fr",
"value": "degré scondaire ii"
}
]
},
{
"code": "tertiary_level_education",
"translations":[
{
"language": "en",
"value": "tertiary_level_education"
},
{
"language": "de",
"value": "tertiärstufe"
},
{
"language": "fr",
"value": "degré tertiaire"
}
]
}
]
}
]
}
Field | Description | Type | Remarks |
---|---|---|---|
types | List of matching socio-economics types | array | |
types[i].code | Code of the socio-economics type | string | |
types[i].unit | Measurement unit of the socio-economics type | string | |
types[i].subtypes | List of subtypes of the socio-economics type | array | empty array if there are no subtypes |
types[i].subtypes[i].code | Code of the subtype | string | |
types[i].subtypes[i].translations | List of translations of the subtype (in the locally relevant languages) | array | |
types[i].subtypes[i].translations[i].language | ISO language code of the translation | enum | |
types[i].subtypes[i].translations[i].value | Value of the translation | string |
Location Scores
POST
location/scores
Returns scores for the specified location.
Request
Example Request 1:
curl -X POST 'https://api.pricehubble.com/api/v1/location/scores?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'content-type: application/json' \
-d '{
"location": {
"coordinates": {
"latitude": 47.36925,
"longitude": 8.531118
}
},
"countryCode": "CH"
}'
Example Request 2:
curl -X POST 'https://api.pricehubble.com/api/v1/location/scores?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'content-type: application/json' \
-d '{
"location": {
"address": {
"street": "Gerechtigkeitsgasse",
"houseNumber": "19",
"postCode": "8001",
"city": "Zurich"
}
},
"countryCode": "CH"
}'
Field | Description | Type | Remarks |
---|---|---|---|
location | Location for which information should be retrieved | Location | |
countryCode | ISO country code | string | CH , DE and FR are currently supported |
Response
Example Response:
{
"catering": 0.98,
"family": 0.98,
"health": 1,
"leisure": 0.92,
"location": 0.464,
"noise": 0.546,
"nuisance": 0.951,
"shopping": 0.98,
"view": 0.575
}
Field | Description | Type | Remarks |
---|---|---|---|
family | Family score | Score | |
location | Overall location score | Score | Only available in CH |
noise | Noise score | Score | Only available in CH |
nuisance | Nuisance score | Score | Only available in CH |
shopping | Shopping score | Score | |
view | View score | Score | Only available in CH |
catering | Catering score | Score | |
health | Health score | Score | |
leisure | Leisure score | Score |
Points of Interest
POST
pois
Returns points of interests such as schools, shops, etc. that match the specified search criteria.
Request
Example Request:
curl -X POST 'https://api.pricehubble.com/api/v1/pois?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'Content-Type: application/json' \
-d '{
"coordinates": {
"latitude": 47.3968601,
"longitude": 8.5153549
},
"radius": 1000,
"category": [
"education",
"leisure"
],
"subcategory": [
"kindergarten",
"playground"
],
"offset": 0,
"limit": 10,
"countryCode": "CH"
}'
Field | Description | Type | Remarks |
---|---|---|---|
coordinates | Filter on POI location. Matches POIs that lie within the circle defined by coordinates and radius |
Coordinates | |
radius | Radius of the circle around coordinates , in meters |
integer | min: 0, max: 30'000, default: 3'000 |
category | Filter on POI category. Matches POIs which have one of the specified category or a combination of category + subcategory if a subcategory is also specified. | array of PoiCategory | |
subcategory | Filter on POI subcategory. Matches POIs which have one of the specified subcategory or a combination of category + subcategory if a category is also specified | array of PoiSubcategory | |
offset | Offset of the query (allows pagination) | integer | min: 0, max: 1'000, default: 0 |
limit | Maximum number of results to return | integer | min: 0, max: 500, default: 10 |
countryCode | ISO country code | string |
The following table shows the currently available POI categories/subcategories. Additional categories/subcategories could be added in the future.
PoiCategory | PoiSubcategory |
---|---|
education |
kindergarten |
primary_school |
|
secondary_school |
|
university |
|
shopping |
supermarket |
convenience_store |
|
catering |
restaurant |
bar |
|
cafe |
|
health |
hospital |
pharmacy |
|
doctor |
|
clinic |
|
dentist |
|
nursing_home |
|
veterinary |
|
leisure |
park |
sport |
|
playground |
|
entertainment |
|
transport |
bus |
tram |
|
subway |
|
train |
|
airport |
|
highway_ramp |
Response
Example Response:
{
"totalItems": 1,
"items": [
{
"name": "Waidfussweg",
"category": "education",
"subcategory": "kindergarten",
"location": {
"coordinates": {
"latitude": 47.39780,
"longitude": 8.51751
},
"address": {
"postCode": "8037",
"city": "Zürich",
"street": "Waidfussweg",
"houseNumber": "61"
}
},
"distance": 193
}
]
}
Field | Description | Type | Remarks |
---|---|---|---|
totalItems | Total number of matching POIs found | integer | |
items | List of matching POIs, sorted by distance in ascending order | array of POIs | empty array if no results |
Field | Description | Type | Remarks |
---|---|---|---|
name | Name of the POI in the local language | string | |
category | PoiCategory | ||
subcategory | PoiSubcategory | ||
location | Location | ||
distance | Distance in meters to the coordinates specified in the request |
integer |
Isochrones
POST
accessibility/isochrones
Returns the isochrone for the specified location, mode of transport and cutoff minutes, e.g. the area that can be reached by car within 15 minutes. Optionally, densities of points of interest can be obtained (see also Points of Interest).
Request
Example Request:
curl -X POST 'https://api.pricehubble.com/api/v1/accessibility/isochrones?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'content-type: application/json' \
-d '{
"coordinates": {
"latitude": 47.36925,
"longitude": 8.531118
},
"mode": "CAR",
"cutoff": 15,
"returnDensities": true,
"countryCode": "CH"
}'
Field | Description | Type | Remarks |
---|---|---|---|
coordinates | Location for which information should be retrieved | Coordinates | |
mode | Mode of transport | enum | WALK , BICYCLE , CAR or PUBLIC_TRANSPORT (PUBLIC_TRANSPORT is currently only supported in CH , DE and FR ) |
cutoff | Cutoff in minutes for which isochrone should be returned | integer | min: 1, max: 60 |
returnDensities | Whether to return densities of points of interest in response | boolean | default: false |
countryCode | ISO country code | string | CH , DE , FR and JP are currently supported |
Response
Example Response:
{
"densities": {
"catering": 1770,
"education": 570,
"health": 257,
"leisure": 527,
"shopping": 423
},
"isochrone": {
"geometry": {
"coordinates": [
[
[
[
8.5817244,
47.2587292
],
...
]
]
],
"type": "MultiPolygon"
}
}
}
Field | Description | Type | Remarks |
---|---|---|---|
densities.education | Number of education POIs within the requested isochrone |
integer | |
densities.shopping | Number of shopping POIs within the requested isochrone |
integer | |
densities.catering | Number of catering POIs within the requested isochrone |
integer | |
densities.health | Number of health POIs within the requested isochrone |
integer | |
densities.leisure | Number of leisure POIs within the requested isochrone |
integer | |
isochrone.geometry | Isochrone geometry | GeoJSON MultiPolygon |
Building Projects
POST
building_projects
Returns building projects that match the specified search criteria.
Request
Example Request:
curl -X POST 'https://api.pricehubble.com/api/v1/building_projects?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'Content-Type: application/json' \
-d '{
"coordinates": {
"latitude": 47.773,
"longitude": 6.23344
},
"radius": 5000,
"isResidential": true,
"status": [
"construction_started"
],
"constructionStartYear": {
"min": 2017
},
"offset": 0,
"limit": 10,
"countryCode": "CH"
}'
Field | Description | Type | Remarks |
---|---|---|---|
coordinates | Filter on building project location. Matches building projects that lie within the circle defined by coordinates and radius |
Coordinates | |
radius | Radius of the circle around coordinates , in meters |
integer | min: 0, max: 30'000, default: 3'000 |
isResidential | Filter on the building project's isResidential flag |
boolean | Do not set this field if you want to search for building projects of any kind (residential, non-residential, unknown). |
isCommercial | Filter on the building project's isCommercial flag |
boolean | Do not set this field if you want to search for building projects of any kind (commercial, non-commercial, unknown). |
status | Filter on building project status. Matches building projects which have one of the specified status | array of BuildingProjectStatus | |
constructionStartYear.min | Lower bound for construction start date | integer | Format: YYYY |
constructionStartYear.max | Upper bound for construction start date | integer | Format: YYYY |
numberOfApartments.min | Lower bound the for number of apartments affected | integer | min: 0, max: 1'000 |
numberOfApartments.max | Upper bound the for number of apartments affected | integer | min: 0, max: 1'000 |
numberOfHouses.min | Lower bound for the number of (single-family) houses to be built | integer | min: 0, max: 500 |
numberOfHouses.max | Upper bound for the number of (single-family) houses to be built | integer | min: 0, max: 500 |
numberOfBuildings.min | Lower bound for the number of buildings affected | integer | min: 0, max: 500 |
numberOfBuildings.max | Upper bound for the number of buildings affected | integer | min: 0, max: 500 |
offset | Offset of the query (allows pagination) | integer | min: 0, max: 1'000, default: 0 |
limit | Maximum number of results to return | integer | min: 0, max: 500, default: 10 |
countryCode | ISO country code | string |
projected
, building_permit_requested
, building_permit_issued
, construction_started
construction_ended
or abandoned
Response
Example Response:
{
"items": [
{
"constructionStartDate": "2017",
"distance": 313,
"fullDescription": "Neubau/Ersatzbau eines 5-1/2-/6-1/2-Zimmer-Einfamilienhauses in Einsteinmauerwerk/Massivbau mit einem Schrägdach und Betoneindeckung. Einbau einer Wärmepumpe und Fussbodenheizung. Umgebungsveränderung, ein Autoabstellplatz und Veloabstellplatz im Freien.",
"location": {
"address": {
"city": "Zürich",
"houseNumber": "64",
"postCode": "8037",
"street": "Trottenstrasse"
},
"coordinates": {
"latitude": 47.3959884643555,
"longitude": 8.5192985534668
}
},
"numberOfApartments": 6,
"numberOfBuildings": 1,
"numberOfFloorsInBuilding": 3,
"provider": "baublatt",
"shortDescription": "Ersatzneubau Einfamilienhaus",
"status": "construction_started",
"title": "Ersatzneubau Einfamilienhaus"
}
],
"totalItems": 1
}
Field | Description | Type | Remarks |
---|---|---|---|
totalItems | Total number of matching building projects found | integer | |
items | List of matching building projects, sorted by distance in ascending order | array of BuildingProjects | empty array if no results |
Field | Description | Type | Remarks |
---|---|---|---|
title | Title of the building project (in the local language) | string | |
shortDescription | Short description of the building project (in the local language) | string | |
fullDescription | Full description of the building project (in the local language) | string | |
location | Location | ||
distance | Distance in meters to the coordinates specified in the request |
integer | |
isResidential | Is the building project of residential nature, e.g. new apartments are being built? | boolean | |
isCommercial | Is the building project of commercial nature, e.g. new offices are being built? | boolean | |
status | Status of the building project | BuildingProjectStatus | |
buildingPermitRequestedDate | The date the building permit was requested | date | Format: YYYY-MM-DD |
buildingPermitIssuedDate | The date the building permit was issued | date | Format: YYYY-MM-DD |
constructionStartDate | Start date of the construction | date | Format: YYYY-MM-DD |
constructionEndDate | End date of the construction | date | Format: YYYY-MM-DD |
numberOfHouses | The number of (single-family) houses affected by this building project, e.g. the number of houses to be built | integer | |
numberOfApartments | The number of apartments affected by this building project, e.g. the number of apartments to be built | integer | |
numberOfBuildings | The number of buildings affected by this building project, e.g. the number of buildings to be built | integer | |
numberOfFloorsInBuilding | The number of floors in the building. If the building project encompasses multiple buildings, the field indicates the number of floors in the highest building | integer | |
provider | Data provider/source | string | Examples: sitadel , baublatt , osm |
Buildings
POST
buildings
Returns information about the building at the specified location.
Request
Example Request:
curl -X POST 'https://api.pricehubble.com/api/v1/buildings?access_token=74126eab0a9048d993bda4b1b55ae074' \
-H 'content-type: application/json' \
-d '{
"location": {
"address": {
"street": "Brandschenkestrasse",
"houseNumber": "30",
"postCode": "8001",
"city": "Zürich"
}
},
"countryCode": "CH"
}'
Field | Description | Type | Remarks |
---|---|---|---|
location | Location of the building | Location | Currently address is required and coordinates have no affect |
countryCode | ISO country code | string | Only CH is supported |
Response
Example Response:
{
"buildingYear": 1981,
"landArea": 1635,
"livingArea": 9144
}
Field | Description | Type | Remarks |
---|---|---|---|
buildingYear | Building's year of construction | integer | |
landArea | Land area associated with the building, in m2 | integer | |
livingArea | Living area within the building, in m2 | integer |
Fisher Widget
Our Fisher Widget can be embedded into your website using only a few lines of code.
Basic Configuration
<iframe id="fisher-widget"></iframe>
<script src="https://fisher.pricehubble.com/widget.js"></script>
<script type="text/javascript">
FisherWidget.init({
apiKey: 'apiKeyValue',
iframe: '#fisher-widget',
textColor: '222222',
activeColor: 'aabbcc'
});
</script>
<style>
iframe#fisher-widget {
width: 100%;
}
</style>
There are a few parameters you can configure in your widget. Your new configuration will look like the one on the right hand, where the different options are:
Parameter | Definition | Example |
---|---|---|
apiKey | String that uniquely identifies your account | apiKey: 'apiKeyValue' |
iframe | CSS selector or DOM element | iframe: '#fisher-widget' or iframe: document.getElementById('fisher-widget') |
activeColor | Color to be applied to all active elements (hex without #) | activeColor: 'aabbcc' |
buttonColor | Color to be applied to buttons (hex without #) | buttonColor: '332211' |
textColor | Color to be applied to text,e.g. labels (hex without #) | textColor: '222222' |
lang | Enforces static language to one of (de,en,fr,it) | lang: 'de' |
gaTrackingId | Google Analytics Tracking ID (track impact of Google campaigns in the Fisher Widget with UTM params) | gaTrackingId: 'UA-000000-2' |
custom | Any value passed in this parameter will be included in the resulting lead email | custom: 'www.example.com' |
resizable | Enables automatic resizing of iframe height and width to fit its container | resizable: false (default - true) |
scrollTopOffset | Scroll top offset value, to be used with sticky navbars | scrollTopOffset: 50 |
Basic Configuration (deprecated)
/* This is important to avoid issue with iOS devices. */
.scroll-wrapper {
-webkit-overflow-scrolling: touch;
overflow-y: scroll;
/* dimensions or positioning here */
}
<div class="scroll-wrapper">
<iframe src="https://fisher.pricehubble.com/?api-key=PRICEHUBBLE&text-color=222222"></iframe>
</div>
<script src="https://fisher.pricehubble.com/widget.js"></script>
This section has been deprecated. Use Basic Configuration section instead.
There are a few parameters you can configure in your widget as querystring parameters. Your new url will look like the one on the right hand, where the different options are:
Parameter | Definition | Example |
---|---|---|
api-key | String that uniquely identifies your account | api-key=PRICEHUBBLE |
active-color | Color to be applied to all active elements (hex without #) | active-color=aabbcc |
button-color | Color to be applied to buttons (hex without #) | button-color=332211 |
text-color | Color to be applied to text,e.g. labels (hex without #) | text-color=222222 |
lang | Enforces static language to one of (de,en,fr,it) | lang=de |
ga-tracking-id | Google Analytics Tracking ID | ga-tracking-id=UA-000000-2 |
ga-client-id | Google Analytics Client ID for cross-domain analytics | See snippet below |
custom | Any value passed in this parameter will be included in the resulting lead email | custom=www.example.com |
Advanced Configuration (deprecated)
<div class="scroll-wrapper">
<iframe src="https://fisher.pricehubble.com/?api-key=PRICEHUBBLE&text-color=222222&ga-tracking-id=UA-000000-2" id="fisher"></iframe>
</div>
<script src="https://fisher.pricehubble.com/widget.js"></script>
<script type="text/javascript" src="YOUR_STATIC_URL/js/iframeResizer.min.js"></script>
<script type="text/javascript">
iFrameResize({},'#fisher');
</script>
This section has been deprecated. Use Basic Configuration section instead.
In order to facilitate embedding Fisher Widget into responsive sites, we have paired it with a library that will do the heavy lifting for you.
What you will have to do is to serve the following iframeResizer.min.js from your site as another static asset and apply the following changes to the code.
Advanced Configuration with cross domain Google Analytics tracking (deprecated)
<div class="scroll-wrapper">
<iframe id="fisher"></iframe>
</div>
<script src="https://fisher.pricehubble.com/widget.js"></script>
<script type="text/javascript">
ga(function(tracker) {
// Gets the client ID of the tracker
let clientId = tracker.get("clientId");
// Gets a reference to the window object of the iframe
let fisherWidgetIframe = document.getElementById("fisher");
// Sets the iframe's complete "src" now that the clientId is known
fisherWidgetIframe.src = "https://fisher.pricehubble.com/?api-key=PRICEHUBBLE&ga-tracking-id=UA-000000-2&ga-client-id=" + clientId;
});
</script>
This section has been deprecated. Use Basic Configuration section instead.
Since <iframe>
elements typically exist on the page prior to Google Analytics Client ID being generated, appending the client ID to the URL in the iframe's source parameter in a static fashion is often not an option.
To solve this problem you can configure the <iframe>
src
parameter after the GA code has been initialized.
CH
Valuation Light
(Deprecated since 2019-03-15; replaced by International Valuation Light)
POST
valuation_light/property_value
Returns a price range estimate for the specified property.
Request
Example Request:
curl -X POST 'https://api.pricehubble.com/api/v1/valuation_light/property_value?access_token=c046eaab3163479cb544f35d17a07fda' \
-H 'content-type: application/json' \
-d '{
"address": {
"city": "Zurich",
"houseNumber": "19",
"postCode": "8001",
"street": "Gerechtigkeitsgasse"
},
"countryCode": "CH",
"buildingYear": 1964,
"conditionDelta": 2,
"livingArea": 100,
"numberOfBathrooms": 1,
"numberOfGarages": 0,
"numberOfRooms": 2,
"propertyType": {
"code": "apartment ",
"subcode": "apartment_normal"
},
"userPayload": [
{
"key": "foo",
"value": "bar"
}
]
}'
Field | Description | Type | Remarks |
---|---|---|---|
address | Valid address in Switzerland; requires error/invalid address handling on client side | object | postCode and city are required parameters |
propertyType | Specification and sub-specification of the property | object | Fields of the object are code with values house , apartment and subcode with values apartment_normal , apartment_attica , apartment_garden , apartment_normal-duplex , apartment_attica-duplex , apartment_garden-duplex , house_detached , house_together , house_row-corner and house_row-middle . Note: only code is required, subcode is optional |
buildingYear | Year when the property was constructed | integer | min: 1850 max: <current year> + 3 |
livingArea | Net living area (SIA standard), in m2 | float | min: 1.0 max: 500.0 |
landArea | Total area of the lot/parcel on which the house is standing, in m2 | float | min: 1.0 max: 4'000.0 |
numberOfRooms | Number of rooms | float | min: 1 max: 12 |
numberOfBathrooms | Number of bathrooms | integer | min: 1 max: 5 |
numberOfGarages | Number of garages | integer | min: 0 max: 5 |
conditionDelta | Condition of the property; considering an average across all relevant factors (bathroom, kitchen, floors, windows, heating, etc.) | integer | 1: new/newly renovated, 2: well maintained, 3: needs renovation |
countryCode | ISO country code | string |
Response
Example Response:
{
"comparison": {
"fractionSmaller": 0.599,
"level": "municipality",
"name": "Zürich"
},
"confidence": 2,
"currencyCode": "CHF",
"geoQuality": "premise",
"userPayload": [
{
"key": "foo",
"value": "bar"
}
],
"valueRange": {
"lower": 1103000,
"upper": 1404000
}
}
Field | Description | Type | Remarks |
---|---|---|---|
valueRange | Estimated lower and upper bound of the property's market value | object | Fields of the object are lower and upper of type float |
geoQuality | Geo quality of the address | string | The “types" field of https://developers.google.com/maps/documentation/geocoding/intro. |
confidence | Confidence of the valuation | integer | 1: poor, 2: medium, 3: good |
Valuation Basic
POST
valuation_basic/property_value
Returns current valuation of an online listing.
Request
Example Request:
curl -X POST 'https://api.pricehubble.com/api/v1/valuation_basic/property_value?access_token=c046eaab3163479cb544f35d17a07fda' \
-H 'content-type: application/json' \
-d '{
"objects": [
property1,
property2
],
"countryCode": "CH",
"userPayload": [
{
"key": "foo_global",
"value": "bar_global"
}
]
}'
Where property1 and property2 are as follows:
{
"address": {
"city": "Zürich",
"houseNumber": "19",
"postCode": "8001",
"street": "Gerechtigkeitsgasse",
"coordinates": {
"latitude": 47.36925,
"longitude": 8.531118
}
},
"buildingYear": 1990,
"livingArea": 100,
"dealCode": "sale",
"propertyType": {
"code": "apartment",
"subcode": "apartment_normal"
},
"userPayload": [
{
"key": "foo0",
"value": "bar0"
}
]
}
Field | Description | Type | Remarks |
---|---|---|---|
objects | Lists of objects to valuate | array of Property | |
countryCode | ISO country code | string | |
userPayload | Optional arguments that can be passed as user-defined payload and returned back in response | array | If set, object must be an array of key-value pairs, as in the example |
Field | Description | Type | Remarks |
---|---|---|---|
address | Valid address in Switzerland; requires error/invalid address handling on client side | object | postCode and city are required parameters. If coordinates are present, the geo-lookup is not performed, and the given values are used for the valuation |
dealCode | Whether the property is for sale or rent | enum | One of: sale , rent |
propertyType | Specification and sub-specification of the property | object | Fields of the object are code with values house , apartment and subcode with values apartment_normal , apartment_attica , apartment_garden , apartment_normal-duplex , apartment_attica-duplex , apartment_garden-duplex , house_detached , house_together , house_row-corner and house_row-middle . Note: only code is required, subcode is optional |
buildingYear | Year when the property was constructed | integer | min: 1850 max: <current year> + 3 |
livingArea | Net living area (SIA standard), in m2 | float | min: 20.0 max: 500.0 |
landArea | Total area of the lot/parcel on which the house is standing, in m2 | float | min: 100.0 max: 3'000.0 Required if propertyType.code is house Do not set if propertyType.code is apartment (or set to null ) |
volume | Volume of the house, in m3 | float | min: 250.0 max: 2'500.0 Do not set if propertyType.code is apartment (or set to null ) |
balconyArea | Area of the balcony/terrace | integer | min: 0 max: 200 |
numberOfRooms | Number of rooms | float | min: 1 max: 12 |
numberOfBathrooms | Number of bathrooms | integer | min: 1 max: 5 |
numberOfGarages | Number of garages | integer | min: 0 max: 5 |
floor | Floor number | integer | min: 0 max: 20 |
renovationYear | Year of renovation | integer | min: 1850 max: <current year> + 3 |
title | Title of the offer | string | |
description | Description of the offer | string | |
url | Url of the offer | string | URL of the offer. Valid schemes are http , https , ftp , and ftps |
images | Images of the offer | array | URLs of property's images. Valid schemes are http , https , ftp , and ftps |
priceRentNet | Net rental offer’s price | integer | min: 0 Do not set if dealCode is sale (or set to null ) |
priceRentGross | Gross rental offer’s price | integer | min: 0 Do not set if dealCode is sale (or set to null ) |
priceSale | Offer’s sale price | integer | min: 0 Do not set if dealCode is rent (or set to null ) |
userPayload | Optional arguments that can be passed as user-defined payload and returned back in response | object | If set, object must be a list of key-value pairs, as in the example |
Response
Example Response:
{
"objects": [
valuation1,
valuation2
],
"userPayload": [
{
"key": "foo_global",
"value": "bar_global"
}
]
}
Where valuation1 and valuation2 are as follows:
{
"confidence": 2,
"currencyCode": "CHF",
"geoQuality": "premise",
"value": 1103000,
"valueRange": {
"lower": "1000000",
"upper": "1200000"
},
"userPayload": [
{
"key": "foo0",
"value": "bar0"
}
]
}
If the valuation fails for an object, the valuation object contains a status object with code 400, a title, and a description giving further information on the cause of the error:
{
"status": {
"code": 400,
"description": {
"livingArea": [
"Must be between 20 and 500."
]
},
"title": "invalid object error"
},
"userPayload": [
{
"key": "foo0",
"value": "bar0"
}
]
}
Field | Description | Type | Remarks |
---|---|---|---|
objects | Lists of valuations | ValuationBasic | |
userPayload | Optional arguments that can be passed as user-defined payload and returned back in response | object | If set, object must be a list of key-value pairs, as in the example |
Field | Description | Type | Remarks |
---|---|---|---|
valueRange | Estimated lower and upper bound of the property's market value | object | Fields of the object are lower and upper of type float |
geoQuality | Geo quality of the address | string | The “types" field of https://developers.google.com/maps/documentation/geocoding/intro. Most common values will be street_address , postal_code or provided_by_user |
status | Status of the valuation | Status | Only present if the valuation was not successful |
userPayload | Optional arguments that can be passed as user-defined payload and returned back in response | object | If set, object must be a list of key-value pairs, as in the example |
Field | Description | Type | Remarks |
---|---|---|---|
code | Status code | integer | 400, if the object is misspecified or an error while executing the valuation has occurred |
title | Title for the status | string | |
description | If an error, dictionary-like object with a field-by-field description of the error | object |
Shared Valuation
(Deprecated since 2018-09-03)
POST
shared/valuation
Returns a shareable link to the property valuation.
Request
Example Request:
curl -X POST 'https://api.pricehubble.com/api/v1/shared/valuation?access_token=c046eaab3163479cb544f35d17a07fda' \
-H 'content-type: application/json' \
-d '{
"countryCode": "CH",
"locale": "en_GB",
"property": {
"address": {
"postCode": "8037",
"city": "Zurich",
"street": "Nordstrasse",
"houseNumber": "391",
"coordinates": {
"latitude": 47.3968601,
"longitude": 8.5153549
}
},
"propertyType": {
"code": "house",
"subcode": "house_detached"
},
"bathroomCondition": 2,
"bathroomStandard": 3,
"buildingYear": 1990,
"conditionOverride": 4.945888803380339,
"flooringCondition": 2,
"flooringStandard": 3,
"kitchenCondition": 2,
"kitchenStandard": 3,
"landArea": 900,
"livingArea": 100,
"microlocationOverride": 2.4199068316056325,
"minergie": false,
"numberOfBathrooms": 1,
"numberOfGarages": 0,
"numberOfRooms": 3,
"qualityOverride": 4.955001175407336,
"roofCondition": 2,
"roofStandard": 3,
"sauna": false,
"volume": 900,
"windowsCondition": 2,
"windowsStandard": 3
}
}'
Field | Description | Type | Remarks |
---|---|---|---|
property | Information about the property | object | Only address and propertyType.code are required. Possible values for propertyType.code : house , apartment . Possible values for propertyType.subcode : apartment_normal , apartment_attica , apartment_garden , apartment_normal-duplex , apartment_attica-duplex , apartment_garden-duplex , house_detached , house_together , house_row-corner and house_row-middle . See sample request. |
countryCode | ISO country code | string | |
locale | Locale in which the shared valuation will be displayed by default. | string | de_CH , en_GB , fr_FR , it_IT or ja_JP |
Response
Example Response:
{
"shareableLink": "https://dash.pricehubble.com/shared/valuation/zyJ0eXAeOiJKV1QiLCJhbGciOiJIUzI1NiJ9.03NzATO4MjNyUTM6ICdhlmIsIiQH9lblJiOiUGbhN2bsJCLzMTM6IyZy9UeCRWZ0FWZyNmIsITO0ojI5JEZlRXYlJ3YiwiIu9Wa0FWdsFmdiojIlBXeUVmchh2ciwiIxYDM4YWZhJDZmZzYtU2NlFWLmJ2Y00iYzMTYtQDMmBTZyMjNiojIklUZyFGazJye.LYL0fjZeZbVqXHxYajF78sb41SmSKDJzv4BqSeLM2CD",
"uuid": "57a7ed57-6f5a-4fd3-bcce-0d6c12eda08f"
}
Field | Description | Type | Remarks |
---|---|---|---|
shareableLink | Link to the shared property valuation | string | |
uuid | unique ID of the shared valuation | string |
Types
Location
Field | Description | Type | Remarks |
---|---|---|---|
coordinates | Coordinates | ||
address | Address |
If used in a request, coordinates
or address
needs to be provided. If both are provided, coordinates
takes precedence.
Coordinates
Field | Description | Type | Remarks |
---|---|---|---|
latitude | Latitude | float | |
longitude | Longitude | float |
Address
Field | Description | Type | Remarks |
---|---|---|---|
postCode | Post code | string | |
city | City | string | |
street | Street | string | |
houseNumber | House number | string |
Score
Type | Description | Remarks |
---|---|---|
float | Score value | min: 0.0 (very bad) max: 1.0 (very good) |
PropertyLight
Field | Description | Type | Remarks |
---|---|---|---|
location | Property location | Location | |
propertyType | Property type | PropertyType | |
buildingYear | The year the property was built | integer | min: 1850, max: <current year> + 3 FR : min: 1700 |
livingArea | Net living area, in m2 | integer | min: 10, max: 800 CH min: 20 |
landArea | Total area of the lot/parcel on which the house is standing, in m2 | integer | Only for houses (required), min: 50, max: 5'000 |
numberOfRooms | Number of rooms | float | min: 1, max: 20 in CH and DE , half rooms are allowed (e.g. 2.5);in JP , use the following rule to map SDK apartment configuration to numberOfRooms: numberOfRooms = Number of bedrooms + 1 (for all SDK combinations, except for 1R/1K where numberOfRooms = 1) |
numberOfBathrooms | Number of bathrooms | integer | min: 1, max: 5 |
condition | Condition of the property; considering an average across all relevant factors (bathroom, kitchen, floors, windows, heating, etc.) | Condition |
Property
Some of the fields have country-specific value ranges (see "Remarks" column below).
Field | Description | Type | Remarks |
---|---|---|---|
location | Property location | Location | |
propertyType | Property type | PropertyType | |
buildingYear | The year the property was built | integer | min: 1850, max: <current year> + 3 FR : min: 1700 |
livingArea | Net living area, in m2 | integer | min: 10, max: 800 CH min: 20 |
landArea | Total area of the lot/parcel on which the house is standing, in m2 | integer | Only for houses (required), min: 50, max: 5'000 |
gardenArea | Garden area, in m2 | integer | Only for apartments, min: 0, max: 200 |
volume | Volume, in m3 | integer | Only for houses, only relevant for CH , min: 250, max: 4'000 |
numberOfRooms | Number of rooms | float | min: 1, max: 20 in CH and DE , half rooms are allowed (e.g. 2.5);in JP , use the following rule to map SDK apartment configuration to numberOfRooms: numberOfRooms = Number of bedrooms + 1 (for all SDK combinations, except for 1R/1K where numberOfRooms = 1) |
numberOfBathrooms | Number of bathrooms | integer | min: 1, max: 5 |
balconyArea | Balcony / Terrace area, in m2 | integer | min: 0, max: 200 |
numberOfIndoorParkingSpaces | Garage spaces | integer | min: 0, max: 2 CH : max: 5 |
numberOfOutdoorParkingSpaces | Parking spaces | integer | min: 0, max: 2 CH : max: 5 |
floorNumber | Floor number | integer | Only for apartments, min: 0, max: 20 FR : max: 50 JP : min: 1, max: 60 |
hasLift | Lift availability | boolean | Only for apartments |
energyLabel | Energy label | enum | Either minergie or do not provide the field, only relevant for CH |
hasSauna | Sauna availability | boolean | Only for houses |
hasPool | Pool availability | boolean | Only for houses |
numberOfFloorsInBuilding | For apartments: Total number of floors of the building in which the apartment is located (Includes ground floor for all countries except FR ). For houses: total number of floors of the house |
integer min: 1, max: 20 FR : max: 50 JP : max: 60 |
|
isFurnished | Whether the property is furnished or not | boolean | Only relevant for FR |
isNew | Whether the property has never been used before ("Bâtiment neuf" in French, "Erstverkauf" / "Erstvermietung" in German) | boolean | Only relevant for FR , DE and AT |
renovationYear | Last renovation year of the property | integer | Only relevant for CH and DE min: 1950, max: <current year> + 3 |
condition.bathrooms | Bathrooms condition | Condition | |
condition.kitchen | Kitchen condition | Condition | |
condition.flooring | Flooring condition | Condition | |
condition.windows | Windows condition | Condition | |
condition.masonry | Masonry condition | Condition | Only for houses |
quality.bathrooms | Bathrooms quality | Quality | |
quality.kitchen | Kitchen quality | Quality | |
quality.flooring | Flooring quality | Quality | |
quality.windows | Windows quality | Quality | |
quality.masonry | Masonry quality | Quality | Only for houses |
PropertyType
Field | Description | Type | Remarks |
---|---|---|---|
code | Property type | enum | apartment or house |
subcode | Property subtype | enum | Not relevant for FR and JP apartment_normal , apartment_maisonette , apartment_attic , apartment_penthouse , apartment_terraced , apartment_studio , house_detached , house_semi_detached , house_row_corner , house_row_middle orhouse_farm |
Condition
renovation_needed
, well_maintained
or new_or_recently_renovated
Quality
simple
, normal
, high_quality
or luxury
Dossier Image
Field | Description | Type | Remarks |
---|---|---|---|
filename | Filename of the uploaded image | string | Get the filename from the Dossier Images endpoint |
caption | Caption of the image | string | Maximum of 60 characters |
Changelog
2020-10-28
divisionsLevel100
request field on Socio-Economics endpoint is no longer supported inDE
2020-10-26
- Added
landArea
filter on Offer search endpoint
2020-08-19
- Added Dossier Logos endpoint
- Added
logo
to Dossier Creation endpoint - Added
logo
to Dossier Update endpoint
2020-07-09
- Added
renovationYear
forCH
to the Property type (used by the Valuation, Dossier Creation and Dossier Update endpoints)
2020-07-06
- Added
offerIds
filter on Offer search endpoint
2020-06-30
Dossier search endpoint updated:
- Removed deprecated
coverImage
response field.
2020-06-04
- Removed deprecated
Location Information
endpoint
2020-05-27
- Added Offer Statistics Light endpoint
2020-05-18
- Added Dossier search endpoint
2020-05-14
- Extended Administrative Divisions endpoint with
AT
support
2020-04-03
- Added Buildings endpoint
2020-03-20
- Added Dossier update endpoint
- Added Dossier deletion endpoint
2020-03-13
- Added Dossier images endpoint
- Added
images
to Dossier Creation endpoint - Added Dossier image type object
2020-03-11
- Added
description
to Dossier Creation endpoint - Added
askingSalePrice
to Dossier Creation endpoint
2019-09-23
- Added
buildingYear
andhasParkingSpaces
filters on Transaction search endpoint
2019-09-20
- Added Transaction Statistics endpoint
2019-09-17
- Added
buildingYear
filter on Offer search endpoint - Added
coordinates
,radius
,numberOfRooms
,livingArea
,salePrice
,rentGross
,isActive
,buildingYear
filters on Offer Statistics endpoint
2019-08-06
Offer search endpoint updated:
- Added
noise
request filter and response field. - Added
slope
request filter and response field. - Added
distanceHospital
request filter and response field. - Added
distanceGroceryStore
request filter and response field. - Added
distancePublicTransport
request filter and response field. - Added
isWheelchairAccessible
request filter and response field.
2019-07-10
- Added Socio-Economics Types endpoint
2019-07-05
- Added Socio-Economics endpoint
2019-07-02
- Added Division Children endpoint
2019-05-20
- Extended Valuation endpoint to return also the net rent value (in
CH
)
2019-05-10
- Added Transaction Search endpoint
2019-04-18
- Added Building Projects endpoint
2019-03-22
- Added Isochrones endpoint
2019-03-15
- Added International Valuation Light endpoint and deprecated CH Valuation Light
2019-03-14
- Extended Location scores endpoint with international support
2019-03-08
- Removed
locale
parameter from endpoints that do not need it
2019-02-15
- Added Points of Interest endpoint
2019-01-14
- Removed deprecated
Property match
endpoint
## 2019-01-07 - Added Offer Statistics endpoint
2018-11-23
- Added Valuation endpoint
2018-11-19
- Updated the Offer search specs with new offset & limit max values
2018-11-16
- Added Dossier Creation endpoint
- Added Dossier Sharing endpoint
- Added Property type object
2018-10-26
- Added Location scores endpoint
- Marked Location Information endpoint as deprecated.
2018-10-05
Offer search endpoint updated:
- Removed
filters.propertyType.subcode
request field optionhouse_row
- Changed
filters.livingArea.min
request field type from float to integer. - Changed
filters.livingArea.max
request field type from float to integer. - Changed
landArea
response field type from float to integer. - Changed
livingArea
response field type from float to integer. - Changed
volume
response field type from float to integer.
2018-09-03
- Marked Shared Valuation endpoint as deprecated.
2018-08-20
- Added Offer search endpoint and marked
Property match
endpoint as deprecated.
2018-06-06
- Added documentation for (German) Appraisals.
2018-05-03
- Valuation Light: Increased max limit of
livingArea
from 400.0 to 500.0.