LightBox Parcels with Multiple Owners
This sample demonstrates how to identify properties with multiple owners using the LightBox API. It includes a Jupyter Notebook walkthrough and a runnable Python script.
Jupyter Notebook
View RawLightBox API - Multi-dwelling Assessment Logic
Use an address to acquire its location coordinates, then use those coordinates to find an associated property parcel, then use that parcel to find associated tax assessment data.
For multi-dwelling properties, a given address will have a one-to-many relationship with the assessment data. The assessment data may contain assessements for multiple addresses within the same dwelling.
Using Addresses to Find Tax Assessment Data
This notebook demonstrates basic features of the LightBox Geocoding API by walking through the following steps:
- Import Python packages
- Enter your API Key for authorization
- Create request objects and display the results both in the JSON form.
Additional Materials: LightBox Developer Portal
#1. Import the required python packages
1import requests
2import json
3from typing import Dict
4import pandas as pd
5
#2. Import function definitions
1# ----------------------------
2# Function Definitions
3# ----------------------------
4
5# Function to geocode a single address using the LightBox API.
6def geocode_address(lightbox_api_key: str, address: str) -> Dict:
7 """
8 Geocodes the provided address using the LightBox API.
9
10 Args:
11 lightbox_api_key (str): The API key for accessing the LightBox API.
12 address (str): The address string for matching.
13
14 Returns:
15 dict: The geocoded address information in JSON format.
16 """
17 # API endpoint configuration
18 BASE_URL = "https://api.lightboxre.com/v1"
19 ENDPOINT = "/addresses/search"
20 URL = BASE_URL + ENDPOINT
21
22 # Setting up request parameters and headers
23 params = {"text": address}
24 headers = {"x-api-key": lightbox_api_key}
25
26 # Sending request to the LightBox API
27 geocoder_data = requests.get(URL, params=params, headers=headers)
28
29 # Returning the geocoded address information
30 return geocoder_data
31
32
33# Test for the get_parcel_from_lbx_address_id() function
34def get_parcel_data_from_address_coordinates(lightbox_api_key: str, country_code: str, address_wkt_coordinates: str) -> Dict:
35 """
36 Returns a dictionary containing the parcel data for the specified address.
37
38 Args:
39 lightbox_api_key (str): The API key for accessing the LightBox API.
40 country_code (str): The country code for the address.
41 address_wkt_coordinates (str): The address coordinates for the address.
42 """
43
44 # API endpoint configuration
45 BASE_URL = "https://api.lightboxre.com/v1"
46 ENDPOINT = f"/parcels/{country_code}/geometry"
47 URL = BASE_URL + ENDPOINT
48
49 # Setting up request parameters and headers
50 params = {"wkt": address_wkt_coordinates}
51 headers = {"x-api-key": lightbox_api_key}
52
53 # Make the request
54 parcel_data = requests.get(URL, params=params, headers=headers)
55
56 # Return the parcel data
57 return parcel_data
58
59
60def get_assessment_data_from_lbx_parcel_id(lightbox_api_key: str, parcel_id: str) -> Dict:
61 """
62 Returns a dictionary containing the assessment data for the specified parcel.
63
64 Args:
65 lightbox_api_key (str): The LightBox API key.
66 parcel_id (str): The parcel ID.
67 """
68
69 # API endpoint configuration
70 BASE_URL = "https://api.lightboxre.com/v1"
71 ENDPOINT = f"/assessments/_on/parcel/us/{parcel_id}"
72 URL = BASE_URL + ENDPOINT
73
74 # Setting up request parameters and headers
75 headers = {"x-api-key": lightbox_api_key}
76
77 # Make the request
78 assessment_data = requests.get(URL, headers=headers)
79
80 # Return the assessment data
81 return assessment_data
82
#3. Create variables that will be used to authenticate your calls. Get your key from the LightBox Developer Portal.
1lightbox_api_key = '<YOUR_API_KEY>'
#4. LightBox API Details This notbook will create various requests and display the output in JSON.
- Geocoding - https://api.lightboxre.com/v1/addresses/search
- Parcels - https://api.lightboxre.com/v1/parcels/{country_code}/geometry
- Assessments - https://api.lightboxre.com/v1/assessments/_on/parcel/us/{lbx_parcel_id}
For additional details regarding each endpoint's request parameters or response models, visit the API Catalog on the LightBox Developer Portal page.
Create variables containing necessary inputs for subsequent calls.
- Notice how the API returns any addresses within the buffer distance of the provided geometry, as well as any metadata associated with that address
1# ----------------------------
2# API Usage
3# ----------------------------
4
5# Specify the address to geocode
6address = "24299 Paseo De Valencia, Laguna Woods, CA 92637"
7country_code = "us" # 'us' for the United States
8
9# Geocode the specified address
10address_search_data = geocode_address(lightbox_api_key, address)
11
12# Get the parcel data from the geocoded address
13parcel_data = get_parcel_data_from_address_coordinates(lightbox_api_key, country_code, address_search_data.json()["addresses"][0]["location"]["representativePoint"]["geometry"]["wkt"])
14
15# Get the assessment data from the parcel ID
16assessment_data = get_assessment_data_from_lbx_parcel_id(lightbox_api_key, parcel_data.json()["parcels"][0]["id"])
17
1# Visualize address data in a pandas dataframe format
2pd.json_normalize(address_search_data.json()["addresses"])
1 $ref id \
20 https://api.lightboxre.com/v1/addresses/search... 06000B911R4H3YWETLFGHQ
3
4 uuaid uaid label type \
50 None None 24299 PASEO DE VALENCIA, LAGUNA WOODS, CA 9263... None
6
7 addressConfidenceScore postalCodeDerived corroborationIndex \
80 None None None
9
10 parcels ... location.locality \
110 [{'$ref': 'https://api.lightboxre.com/v1/parce... ... LAGUNA WOODS
12
13 location.regionCode location.unit location.county location.countryCode \
140 CA None ORANGE COUNTY US
15
16 location.postalCode location.postalCodeExt \
170 92637 3100
18
19 location.representativePoint.latitude \
200 33.609982
21
22 location.representativePoint.longitude \
230 -117.713722
24
25 location.representativePoint.geometry.wkt
260 POINT(-117.713722 33.609982)
27
28[1 rows x 37 columns]
1# Visualize parcel data in a pandas dataframe format
2pd.json_normalize(parcel_data.json()["parcels"])
1 $ref id \
20 https://api.lightboxre.com/v1/parcels/us/0202P... 0202P9GBKVNO0LIUTDCJ47
3
4 fips parcelApn county legalDescription neighborhood \
50 06059 621-191-16 ORANGE [N TR 16835 BLK LOT 1 UN HOLD] None
6
7 opportunityZone subdivision topography ... \
80 False None None ...
9
10 transaction.lastMarketSale.tdDocumentNumber \
110 None
12
13 transaction.lastMarketSale.deedTransactionType \
140 None
15
16 transaction.lastMarketSale.lenderType \
170 None
18
19 transaction.priorMarketSale.transferDate transaction.priorMarketSale.lender \
200 None
21
22 transaction.multipleApnFlag usplss.township usplss.range usplss.section \
230 None None None None
24
25 usplss.quarter
260 None
27
28[1 rows x 113 columns]
1# Visualize assessment data in a pandas dataframe format
2pd.json_normalize(assessment_data.json()["assessments"])
3
1 $ref apn fips \
20 https://api.lightboxre.com/v1/assessments/us/0... 621-191-16 06059
31 https://api.lightboxre.com/v1/assessments/us/0... 932-810-75 06059
42 https://api.lightboxre.com/v1/assessments/us/0... 932-810-76 06059
53 https://api.lightboxre.com/v1/assessments/us/0... 932-810-77 06059
64 https://api.lightboxre.com/v1/assessments/us/0... 932-810-78 06059
7.. ... ... ...
8130 https://api.lightboxre.com/v1/assessments/us/0... 932-812-04 06059
9131 https://api.lightboxre.com/v1/assessments/us/0... 932-812-05 06059
10132 https://api.lightboxre.com/v1/assessments/us/0... 932-812-06 06059
11133 https://api.lightboxre.com/v1/assessments/us/0... 932-812-07 06059
12134 https://api.lightboxre.com/v1/assessments/us/0... 932-812-08 06059
13
14 id $metadata alternateApn avm \
150 03046JQUZ4Y7Q7TATH24S3 None None NaN
161 03018O7YHXQ8WN8ENIA2R1 None None 615166.0
172 030759YM7ZE8HWFQCF0TTH None None 459833.0
183 0303YGY9HW6C14HQCMJFC7 None None 599500.0
194 0304XNNLW2WT4VF74Q75N4 None None 599500.0
20.. ... ... ... ...
21130 03002OKN1NJDVLT53YPMRJ None None 566500.0
22131 0306DPN3Y95BZLE3G29MIC None None 566500.0
23132 03060SKL4MQ53HIX3X1AJT None None 373833.0
24133 0306OVUEJWYCVIZ6WC8HLA None None 615166.0
25134 0300H75ZIL46PZE2QU4MFA None None 615166.0
26
27 improvementPercent assessedLotSize poolIndicator ... tax.amount \
280 NaN 12353.31191 None ... NaN
291 49.90 NaN None ... 6139.0
302 58.04 NaN None ... 4099.0
313 51.57 NaN None ... 5385.0
324 51.57 NaN None ... 5385.0
33.. ... ... ... ... ...
34130 52.95 NaN None ... 5408.0
35131 52.95 NaN None ... 5408.0
36132 66.49 NaN None ... 3117.0
37133 49.90 NaN None ... 6139.0
38134 49.90 NaN None ... 6139.0
39
40 tax.rateAreaCode tax.exemption valuationModel.value \
410 32-010 None NaN
421 32-010 None 692000.0
432 32-010 None 555000.0
443 32-010 None 588000.0
454 32-010 None 588000.0
46.. ... ... ...
47130 32-010 None 590000.0
48131 32-010 None 590000.0
49132 32-010 None 391000.0
50133 32-010 None 692000.0
51134 32-010 None 692000.0
52
53 valuationModel.valueHigh valuationModel.valueLow valuationModel.date \
540 NaN NaN None
551 816560.0 567440.0 None
562 627150.0 482850.0 None
573 699720.0 476280.0 None
584 699720.0 476280.0 None
59.. ... ... ...
60130 708000.0 472000.0 None
61131 708000.0 472000.0 None
62132 469200.0 312800.0 None
63133 816560.0 567440.0 None
64134 816560.0 567440.0 None
65
66 valuationModel.propensityScore valuationModel.score \
670 None NaN
681 None 82.0
692 None 87.0
703 None 81.0
714 None 81.0
72.. ... ...
73130 None 80.0
74131 None 80.0
75132 None 80.0
76133 None 82.0
77134 None 82.0
78
79 valuationModel.label
800 None
811 $692 K
822 $555 K
833 $588 K
844 $588 K
85.. ...
86130 $590 K
87131 $590 K
88132 $391 K
89133 $692 K
90134 $692 K
91
92[135 rows x 142 columns]
1# --------------------
2# Print collected data
3# --------------------
4
5# Print the geocoded address data in a readable JSON format
6print(json.dumps(address_search_data.json(), indent=4))
7# Print the parcel data in a readable JSON format
8print(json.dumps(parcel_data.json(), indent=4))
9# Print the assessment data in a readable JSON format
10print(json.dumps(assessment_data.json(), indent=4))
11
12
Commonly Seen Errors
See LightBox Geocoder API for a list of common error responses.
Python Script
View Raw1import requests
2import json
3from typing import Dict
4
5
6# ----------------------------
7# Function Definitions
8# ----------------------------
9
10# Function to geocode a single address using the LightBox API.
11def geocode_address(lightbox_api_key: str, address: str) -> Dict:
12 """
13 Geocodes the provided address using the LightBox API.
14
15 Args:
16 lightbox_api_key (str): The API key for accessing the LightBox API.
17 address (str): The address string for matching.
18
19 Returns:
20 dict: The geocoded address information in JSON format.
21 """
22 # API endpoint configuration
23 BASE_URL = "https://api.lightboxre.com/v1"
24 ENDPOINT = "/addresses/search"
25 URL = BASE_URL + ENDPOINT
26
27 # Setting up request parameters and headers
28 params = {"text": address}
29 headers = {"x-api-key": lightbox_api_key}
30
31 # Sending request to the LightBox API
32 geocoder_data = requests.get(URL, params=params, headers=headers)
33
34 # Returning the geocoded address information
35 return geocoder_data
36
37
38# Test for the get_parcel_from_lbx_address_id() function
39def get_parcel_data_from_address_coordinates(lightbox_api_key: str, country_code: str, address_wkt_coordinates: str) -> Dict:
40 """
41 Returns a dictionary containing the parcel data for the specified address.
42
43 Args:
44 lightbox_api_key (str): The API key for accessing the LightBox API.
45 country_code (str): The country code for the address.
46 address_wkt_coordinates (str): The address coordinates for the address.
47 """
48
49 # API endpoint configuration
50 BASE_URL = "https://api.lightboxre.com/v1"
51 ENDPOINT = f"/parcels/{country_code}/geometry"
52 URL = BASE_URL + ENDPOINT
53
54 # Setting up request parameters and headers
55 params = {"wkt": address_wkt_coordinates}
56 headers = {"x-api-key": lightbox_api_key}
57
58 # Make the request
59 parcel_data = requests.get(URL, params=params, headers=headers)
60
61 # Return the parcel data
62 return parcel_data
63
64
65def get_assessment_data_from_lbx_parcel_id(lightbox_api_key: str, parcel_id: str) -> Dict:
66 """
67 Returns a dictionary containing the assessment data for the specified parcel.
68
69 Args:
70 lightbox_api_key (str): The LightBox API key.
71 parcel_id (str): The parcel ID.
72 """
73
74 # API endpoint configuration
75 BASE_URL = "https://api.lightboxre.com/v1"
76 ENDPOINT = f"/assessments/_on/parcel/us/{parcel_id}"
77 URL = BASE_URL + ENDPOINT
78
79 # Setting up request parameters and headers
80 headers = {"x-api-key": lightbox_api_key}
81
82 # Make the request
83 assessment_data = requests.get(URL, headers=headers)
84
85 # Return the assessment data
86 return assessment_data
87
88
89# Function to test the response status of the geocode_address function.
90def test_geocode_address_response_status(lightbox_api_key: str) -> None:
91 """
92 Tests the response status for various scenarios using the geocode_address function.
93
94 Args:
95 lightbox_api_key (str): The API key for accessing the LightBox API.
96 """
97
98 # Test for a successful request (HTTP status code 200)
99 address = "25482 Buckwood Land Forest, Ca, 92630"
100 address_search_data = geocode_address(lightbox_api_key, address)
101 assert address_search_data.status_code == 200, f"Expected status code 200, but got {address_search_data.status_code}"
102
103 # Test for an unsuccessful request due to an empty address (HTTP status code 400)
104 address = "" # No address specified
105 address_search_data = geocode_address(lightbox_api_key, address)
106 assert address_search_data.status_code == 400, f"Expected status code 400, but got {address_search_data.status_code}"
107
108 # Test for an unsuccessful request due to an invalid API key (HTTP status code 401)
109 address = "25482 Buckwood Land Forest, Ca, 92630"
110 address_search_data = geocode_address("My-LightBox-Key", address) # Invalid API key
111 assert address_search_data.status_code == 401, f"Expected status code 401, but got {address_search_data.status_code}"
112
113 # Test for an unsuccessful request due to an incomplete address (HTTP status code 404)
114 address = "25482 Buckwood Land Forest" # Incomplete address
115 address_search_data = geocode_address(lightbox_api_key, address)
116 assert address_search_data.status_code == 404, f"Expected status code 404, but got {address_search_data.status_code}"
117
118
119# Test the get_parcel_data_from_address_coordinates function
120def test_get_parcel_data_from_address_coordinates(lightbox_api_key):
121 """
122 Test the get_parcel_data_from_address_coordinates function
123
124 Args:
125 lightbox_api_key (str): The LightBox API key
126 """
127
128 # Test for a successful request (HTTP status code 200)
129 address = "25482 Buckwood Land Forest, Ca, 92630"
130 country_code = "us"
131 address_search_data = geocode_address(lightbox_api_key, address)
132 address_coordinates = address_search_data.json()["addresses"][0]["location"]["representativePoint"]["geometry"]["wkt"]
133 parcel_data = get_parcel_data_from_address_coordinates(lightbox_api_key, country_code, address_coordinates)
134 assert parcel_data.status_code == 200, f"Expected status code 200, but got {parcel_data.status_code}"
135
136 # Test for an unsuccessful request due to an invalid address ID (HTTP status code 400)
137 address_coordinates = "foobar"
138 parcel_data = get_parcel_data_from_address_coordinates(lightbox_api_key, country_code, address_coordinates)
139 assert parcel_data.status_code == 400, f"Expected status code 400, but got {parcel_data.status_code}"
140
141 # Test for an unsuccessful request due to an invalid API key (HTTP status code 401)
142 parcel_data = get_parcel_data_from_address_coordinates(lightbox_api_key+"foobar", country_code, address_coordinates)
143 assert parcel_data.status_code == 401, f"Expected status code 401, but got {parcel_data.status_code}"
144
145
146# Test the get_parcel_data_from_lbx_parcel_id function
147def test_get_assessment_data_from_lbx_parcel_id(lightbox_api_key):
148 """
149 Test the get_assessment_data_from_lbx_parcel_id function
150
151 Args:
152 lightbox_api_key (str): The LightBox API key
153 """
154
155 # Test for a successful request (HTTP status code 200)
156 address = "25482 Buckwood Land Forest, Ca, 92630"
157 country_code = "us"
158 address_search_data = geocode_address(lightbox_api_key, address)
159 address_coordinates = address_search_data.json()["addresses"][0]["location"]["representativePoint"]["geometry"]["wkt"]
160 parcel_data = get_parcel_data_from_address_coordinates(lightbox_api_key, country_code, address_coordinates)
161 parcel_id = parcel_data.json()["parcels"][0]["id"]
162 assessment_data = get_assessment_data_from_lbx_parcel_id(lightbox_api_key, parcel_id)
163 assert assessment_data.status_code == 200, f"Expected status code 200, but got {assessment_data.status_code}"
164
165 # Test for an unsuccessful request due to an invalid parcel ID (HTTP status code 400)
166 parcel_id = "1234567890"
167 assessment_data = get_assessment_data_from_lbx_parcel_id(lightbox_api_key, parcel_id)
168 assert assessment_data.status_code == 400, f"Expected status code 400, but got {assessment_data.status_code}"
169
170 # Test for an unsuccessful request (HTTP status code 401)
171 assessment_data = get_assessment_data_from_lbx_parcel_id(lightbox_api_key+"foobar", parcel_id)
172 assert assessment_data.status_code == 401, f"Expected status code 401, but got {assessment_data.status_code}"
173
174
175# ----------------------------
176# API Usage
177# ----------------------------
178
179# Assign your LightBox API key
180lightbox_api_key = ""
181
182# Specify the address to geocode
183address = "24299 Paseo De Valencia, Laguna Woods, CA 92637"
184country_code = "us" # 'us' for the United States
185
186# Geocode the specified address
187address_search_data = geocode_address(lightbox_api_key, address)
188
189# Get the parcel data from the geocoded address
190parcel_data = get_parcel_data_from_address_coordinates(lightbox_api_key, country_code, address_search_data.json()["addresses"][0]["location"]["representativePoint"]["geometry"]["wkt"])
191
192# Get the assessment data from the parcel ID
193assessment_data = get_assessment_data_from_lbx_parcel_id(lightbox_api_key, parcel_data.json()["parcels"][0]["id"])
194
195
196# --------------------
197# Print collected data
198# --------------------
199
200# Print the geocoded address data in a readable JSON format
201print(json.dumps(address_search_data.json(), indent=4))
202# Print the parcel data in a readable JSON format
203print(json.dumps(parcel_data.json(), indent=4))
204# Print the assessment data in a readable JSON format
205print(json.dumps(assessment_data.json(), indent=4))
206
207
208# ----------------------------
209# API Testing
210# ----------------------------
211
212# Perform tests to verify the response status of the geocode_address function
213test_geocode_address_response_status(lightbox_api_key)
214test_get_parcel_data_from_address_coordinates(lightbox_api_key)
215test_get_assessment_data_from_lbx_parcel_id(lightbox_api_key)
216
217