Locations API
Last reviewed: 03/08/23
Barbour ABI data is about construction projects:
- All planning applications are captured and processed for their location data.
- Larger projects are researched and tracked by a team of in-house Barbour ABI researchers, who track the projects and the companies and people working on them, from initial design and planning stages through to construction completion.
Two APIs are available for the two data sets above, Locations API and Projects API. The Projects API has additional fields available as a result of the telephone research.
Field | Locations API (free) | Locations API (paid) | Projects API (subscription) |
---|---|---|---|
project_id | Yes | Yes | Yes |
project_first_published | Yes | ||
project_last_published | Yes | Yes | |
project_title | Yes | Yes | Yes |
project_site1 | Yes | Yes | |
project_site2 | Yes | Yes | |
project_site3 | Yes | Yes | Yes |
project_site4 | Yes | Yes | Yes |
project_postcode | Yes | Yes | |
project_site_phone | Yes | ||
project_site_phone_tps | Yes | ||
project_scheme | Yes | Yes | |
project_status | Yes | Yes | |
project_latitude | Yes | Yes | |
project_longitude | Yes | Yes | |
project_enabling_start | Yes | ||
project_start_min | Yes | ||
project_start_max | Yes | ||
project_start_display | Yes | ||
project_finish_min | Yes | ||
project_finish_max | Yes | ||
project_finish_display | Yes | ||
project_duration | Yes | ||
project_timing_projected | Yes | ||
project_tender_close_min | Yes | ||
project_tender_close_max | Yes | ||
project_tender_close_display | Yes | ||
project_value | Yes | ||
project_value_estimated | Yes | ||
project_planning_stage | Yes | Yes | |
project_contract_stage | Yes | ||
project_stages | Yes | Yes | |
project_stopped | Yes | ||
project_geocode | Yes | Yes | |
project_development_types | Yes | Yes | |
project_primary_sector | Yes | Yes | Yes |
project_primary_category | Yes | Yes | |
project_categories | Yes | Yes | |
project_materials | Yes | ||
project_funding | Yes | ||
project_contract_type | Yes | Yes | |
project_last_recall | Yes | ||
project_next_recall | Yes | ||
project_plan_area | Yes | ||
project_site_area | Yes | ||
project_volume | Yes | ||
project_linear | Yes | ||
project_structures | Yes | ||
project_units | Yes | ||
project_storeys_above | Yes | ||
project_storeys_below | Yes | ||
project_parking | Yes | ||
project_one_bed | Yes | ||
project_two_bed | Yes | ||
project_three_bed | Yes | ||
project_four_bed | Yes | ||
project_five_bed | Yes | ||
project_flats | Yes | ||
project_houses | Yes | ||
project_hotel_beds | Yes | ||
project_hospital_beds | Yes | ||
project_student_beds | Yes | ||
project_carehome_beds | Yes | ||
project_sheltered_beds | Yes | ||
project_net_retail_floor | Yes | ||
project_gross_retail_floor | Yes | ||
project_floor_area | Yes | ||
project_planning_reference | Yes | ||
project_plans_submitted | Yes | Yes | Yes |
project_planning_url | Yes | Yes | |
project_breeam_rating | Yes | ||
project_image_url | Yes | ||
project_image_source_url | Yes | ||
project_usage | Yes | ||
project_researcher | Yes | Yes | |
project_researcher_full_name | Yes | Yes | |
project_is_framework | Yes | ||
project_framework | Yes | ||
project_framework_project_id | Yes |
Customers require a Developer license with their subscription to access the Projects API. Customers require a Locations license to access the Locations API.
Common use cases
Customers use Barbour ABI APIs to:
Use | Projects API | Locations API |
---|---|---|
Find sales opportunities: search for relevant projects near me | Yes | |
Competitor analysis: identify projects that a competitor has won | Yes | |
Marketing data sets: extract a set of data for mailing | Yes | |
Analysis: compare project activity in different geographical areas | Yes | Yes |
Local search: Find all planning applications near a location | Yes |
Data updates
The Barbour ABI research team are based in the UK, so the majority of updates occur during UK business hours. We encourage developers to build systems that continually use these APIs to ensure the latest updates are seen to users, rather than build daily batch processes. The APIs and repositories are hosted on a load balanced environment so resilience and uptime are high.
Some updates are done outside UK business hours, so please ensure this is considered in designing a batch processing system.
HTTP status codes
Success
All successful API calls will respond with a standard 2xx status code. These responses will not have a message body, unless a GET request.
Typical responses and examples for PUT/POST requests, using by advanced API consumers are:
Status code | Description |
---|---|
200 OK | Changing the property of an object, for example favouriting a project or marking a project as read. |
201 Created | Creating a new resource, for example creating a team, creating a user and creating a tag |
204 Accepted | An attempt to update or create that results in no change. For example, favouriting a project that is already favourited, or creating a team that already exists. |
Others
API calls resulting in a client or server error will respond with the appropriate status code along with a supporting message. For example:
{
"status_code" : 501,
"message" : "Support to delete teams is not available yet"
}
Rate limiting
In the future v4 will be released that includes throttling to ensure fair use and the wider user experience is not affected. When this is implemented excessive programatic API calls will result in a 429 Too Many Requests status code.
Entry point
The entry point is:
To get started, you will need an API key for your Barbour ABI subscription which will be provided by Barbour ABI. There is a single API key for your company subscription so if you have two developers then both developers should use the same API key. You need to include the API key in an ‘x-api-key’ header of every API call you make:
headers:
x-api-key: {api-key}
As a developer you will also need either a Developer or a Locations license. You will receive your username and will be invited to set your password in a “Welcome” email.
With these two items you can then generate a token to consume the APIs as follows:
GET login
headers:
Authorization: Basic {token}
x-api-key: {api-key}
{token} is base64 encoded username:password where password is a SHA256 hash.
{api-key} is the API key provided by Barbour ABI.
An example, assuming the following:
- Username: api_user
- Password: MB_4810
- SHA256 hash the password MB_4810 which will be 37596daf86f09dbc748480ef693fb4beb1ff5e406b21a8f671eccb06a0fd6f2d
- Append this to the username separated by a colon to produce: api_user:37596daf86f09dbc748480ef693fb4beb1ff5e406b21a8f671eccb06a0fd6f2d
- Base64 encode api_user:37596daf86f09dbc748480ef693fb4beb1ff5e406b21a8f671eccb06a0fd6f2d to produce YXBpX3VzZXI6Mzc1OTZkYWY4NmYwOWRiYzc0ODQ4MGVmNjkzZmI0YmViMWZmNWU0MDZiMjFhOGY2NzFlY2NiMDZhMGZkNmYyZA==
- Call the login API as follows (example in Curl):
curl --location --request GET ' \
--header 'Authorization: Basic YXBpX3VzZXI6Mzc1OTZkYWY4NmYwOWRiYzc0ODQ4MGVmNjkzZmI0YmViMWZmNWU0MDZiMjFhOGY2NzFlY2NiMDZhMGZkNmYyZA==' \
--header 'x-api-key: ABI_KEY_PROVIDED_BY_BARBOUR_ABI'
This will respond with a token in the header, which must be supplied in all other API calls.
The body will contain the unique ID for the user.
{
"user_id": 1234
}
The user_id cannot be changed and should not be confused with the username which can be changed.
If a token is not used for 30 days it will become invalid and a new one must be generated as above. Also, on rare occasions tokens will be invalidated sooner, for example with a major production release.
In your production code you should test for an invalid token and re-authenticate as necessary.
Tokens will automatically become invalid if a Barbour ABI subscription lapses.
A valid token and the API Key must be included in the header of all API calls:
headers:
Authorization: Bearer {authentication token}
x-api-key: {api-key}
Logout
It is not necessary to invalidate a token, but if required it can be explicitly destroyed as follows:
GET /logout
Provide the token in the header, like all the other API calls.
Customers API
To get details about your company:
GET customers
returns:
{
"customer_id": "ABC1245",
"company_name": "ABC Limited",
"company_website": "abclimited.co.uk",
"sector_id": 1
}
Access to the APIs is based on a subscription service with customers having access to the sub-set of Barbour ABI that matches their subscription. To see this profile, in the standard API query syntax:
GET customers/profiles
The response includes the fields where filtering is applied. For example if your subscription covers all project values, then the key project_value will be omitted.
Lookups API
New lookup ids are introduced rarely, and similarly the text associated with an id rarely changes. Therefore developers should cache local copies of the lookups, perhaps updating their cache every 24 hours or if an unrecognised id is found.
Some of the fields are based on lookups. Lookups can be numeric or strings, for example planning stages and materials respectively. To get the list of lookups:
GET lookups
The response is as follows:
{
"lookups": [{
"planning_stage": [{
"id": 2,
"description": "Outline planning"
},
{
"id": 10,
"description": "Outline approval"
}
],
"materials": [{
"id": "EC",
"description": "Envelope",
"children": [{
"id": "EC01",
"description": "Wall Cladding",
"children": [{
"id": "EC0102",
"description": "reinforced concrete"
}, {
"id": "EC0103",
"description": "precast concrete"
}]
},
{
"id": "EC02",
"description": "Wall Features"
}
]
},
{
"id": "BR",
"description": "Bridges
}
]
}]
}
For specific sets of lookups use the lookups parameter as follows:
GET lookups?lookups=planning_stage,material
For specific lookups use the query parameter. An example to get the lookups for 4 categories:
GET lookups?query={
"category":
{"operator": "=",
"value": [807, 1006, 1312, 2301]
}
}
The response will include the parent categories.
Credits
The locations API is based on a credit system.
- Unlimited searching the locations data is included with the Locations license and does not consume credits.
- One credit is consumed when the full details of a project is accessed. Once the details of a project has been accessed, subsequent requests for the same project do not consume a credit.
There is no restrictions on the number of credits that can be consumed, so the developer using the Location APIs must be responsible with their application design.
All projects are accessible via the Locations API. There are no restrictions such as location, sector and planning stage.
In brief, consumers will search for projects with:
GET locations
then get the full detail (consuming a credit) with:
GET locations/{project_id}
Searching for projects
The simplest search which lists all projects is as follows:
GET locations
This will respond with the first set of projects as follows:
{
"aggregation": {
"project_count": 13961013
},
"projects": [
{
"project_id": 59771528,
"project_title": "Window/Single Storey Rear/Wall/Lightwell",
"project_plans_submitted": "2013-10-21T00:00:00Z",
"project_primary_sector": 1500,
"project_site4": "London",
"project_site3": "Deptford",
"project_size": "small"
},
{
etc
}
]
}
The projects key contains a list of projects and the aggregation key contains the total number of projects available in the complete dataset. For example there could be 20 projects returned, but the count may be much higher. See the section Pagination for more information on iteration using offsets.
Query
Typically customers want to see projects within a region, a sector, within a timeframe etc. For this, filters are applied using the query parameter. The syntax is as follows:
"query"={
"field":{
"operator": ,
"value":
},
...
}
The operators are:
Operator | Sign |
---|---|
Range | .. |
Equal | = |
Not equal | != |
Greater than | > |
Less than | < |
Greater than or equal | = |
Less than or equal | <= |
Is empty | 0 |
Is not empty | !0 |
If the range operator is used, then value1 and value2 keys need to be used in place of the single value key.
The use of this query language is explained next, in the form of examples.
Example 1: Projects within 25 miles of Tower Bridge (51.5079, 0.0877):
GET locations?query={
"project_latitude": {
"operator": "=",
"value": 51.5079
},
"project_longitude": {
"operator": "=",
"value": 0.0877
},
"project_distance": {
"operator": "=",
"value": 25
}
}&sort=project_distance
The units for project_distance is miles.
To get the results sorted by distance, use sort=project_distance. When sorting by distance the project_latitude and project_longitude must be included in the query.
Date filters can be applied based on specific dates or relative dates, as shown in the next two examples.
Example 3: Projects which were submitted for planning permission on or after 29th January 2022:
GET locations?query={
"project_plans_submitted":{
"operator": ">=",
"value": "2022-01-29T00:00:00Z"
}
}
Example 4: Projects which were submitted for planning permission within the last 90 days:
GET location?query={
"project_plans_submitted":{
"operator": "..",
"value1": -90,
"value2": 0
}
}
Example 5: A generic project text search for “northgate development”:
Support is provided for fuzzy text searches as follows:
GET locations?query={
"project_text":{
"operator": "=",
"value": "northgate development"
}
}
Searching the project_text will search the following fields for matches:
- project_id
- project_title
- project_scheme*
- project_status*
- project_site1*
* a field not accessible using the fields parameter with a search
It is preferred that you specify a sort order in your code.
However, if no sort order is specified, where possible the results will be ranked by score with exact matches ranking first. An exact match within a project_title will rank higher than an exact match within a project_scheme.
Note: project_text is not a field itself, so cannot be returned using the fields parameter.
Example 6: Projects in various postcodes
GET locations?query={
"project_postcode":{
"operator": "=",
"value": ["CH","LL12","LL13","CW6"]
}
}
For these filters, the postcodes can be specified as a postcode area (e.g. CH), a postcode district (e.g. CH64), a unit postcode (e.g. CH65 9HQ) or any combination of these.
All or any text search
Searching for multiple strings is achieved using the project_search parameter.
To search for projects with contain the both string “college” and “extension”:
GET locations?query={
"project_text":{
"operator": "=",
"value": ["college", "extension"]
}
}&project_search=all
To search for projects which contain either the string “University of Manchester” or “Manchester University”:
GET locations?query={
"project_text":{
"operator": "=",
"value": ["University of Manchester", "Manchester University"]
}
}&project_search=any
Sort
Results can be sorted, for example to get projects with the latest planning application date, followed by the project_id (ascending), use the following:
GET locations?sort=-project_plans_submitted,project_id
The negative (-) sign and plus sign (+) can be used to specify descending and ascending sort order respectively. The plus sign is implied and therefore optional.
When searching on text fields, the default sort order is the best match. To override this default, specify a sort order.
A maximum of three sort orders can be provided.
Pagination
For all search calls, the top n records are returned by default, where n is the limit, so to retrieve a larger or complete dataset a series of API calls must be made, using the limit and offset parameters.
For example, to get the first 30 records, in three batches of 10 at a time:
GET locations?limit=10&offset=0
GET locations?limit=10&offset=10
GET locations?limit=10&offset=20
If not specified, the default values for limit and offset are 50 and 0 respectively. It is good practice for you to set the limit and offset programmatically as the defaults may change from time-to-time.
The use of limit and offset gives access to the first 10,000 records, but not beyond. To get a larger dataset use the query parameter to reduce the total results. For example, query using the project_last_published date to get the the projects in monthly sets, say from July 2018, then iterate through these using limit and offset. Then get the the results for August 2018, and iterate, etc.
For the best user experience, repeated API calls with limit of between 10 and 200 are recommended for performance reasons.
Getting project details
Once a project of interest has been identified using the search above, get the details as follows:
GET locations/{project_id}
There are some legacy and uncommon fields which are not included by default in the above request.
Fields
To specify the project fields returned:
GET locations?fields=project_id,project_title
The full list of available fields are listed in the table in the introduction. The fields parameter is restricted to a limited set of fields for the searches, but the full set of fields are available with project details API calls.
Wherever possible fields are coded (for example project_planning_stage and project_categories) so are returned as ids. Use the lookups API to get the display text associated with each id.
Combining with Projects API
The most significant projects within the Location data repository have been researched by the Barbour ABI research team. These projects can be identified with the project_size key as follows:
"project_size": "large"
If you also have a Developer license you can use the Projects API to get the full researched details of the project with:
GET projects/{project_id}
See the Project API documentation for more information on how to get complete details of these projects, including the associated companies and people.
Any questions?
For support using the Barbour ABI APIs, please sign into the Barbour ABI platform and use the “Chat with us” functionality in the bottom left of the Web platform.