Code Examples

packages = ["requests", "pyodide-http"]

Introduction

Search

11 Recipes for Success with the BTAA Geoportal API

Download the full runnable Python script containing all these examples, or run them directly in your browser below!

Download Python Script

Use the navigation buttons below or arrow keys to move between examples.

Simple Search

Search

Goal: Find all resources related to "water".

Request: GET /api/v1/search?q=water

import requests
import json

BASE_URL = "https://lib-btaageoapi-dev-app-01.oit.umn.edu/api/v1"

# Step 1: Text search for 'water'
params = {
    'q': 'water',
    'page': 1,
    'per_page': 10
}

response = requests.get(f"{BASE_URL}/search", params=params)
data = response.json()

print(f"Total number of resources found: {data.get('meta', {}).get('totalCount')}")

print("\nList of titles:")
for item in data.get('data', []):
    print(f"  - {item['attributes'].get('dct_title_s', 'N/A')}")
Click "Run" to see the API response...
Click "Run" to see the output...

Obtain a Resource

Resource

Goal: Fetch metadata for a specific resource ID.

Request: GET /api/v1/resources/ark28722-s7vs38

import requests
import json

BASE_URL = "https://lib-btaageoapi-dev-app-01.oit.umn.edu/api/v1"

# Step 2: Fetch a specific resource
resource_id = "ark28722-s7vs38"
response = requests.get(f"{BASE_URL}/resources/{resource_id}")
data = response.json()

attrs = data['data']['attributes']
print(f"Title: {attrs.get('dct_title_s', 'N/A')}")
print(f"Description: {attrs.get('dct_description_sm', ['N/A'])[0]}")

# Show references
if 'dct_references_s' in attrs:
    refs = json.loads(attrs['dct_references_s'])
    for key, value in refs.items():
        print(f"{key}: {value}")
Click "Run" to see the API response...
Click "Run" to see the output...

Boolean Search

Advanced Search

Goal: Search for "(water AND ice) NOT Forest".

Request: GET /api/v1/search?q=(water AND ice) NOT Forest

import requests
import json

BASE_URL = "https://lib-btaageoapi-dev-app-01.oit.umn.edu/api/v1"

# Step 3: Boolean search
params = {
    'q': '(water AND ice) NOT Forest',
    'page': 1,
    'per_page': 10
}

response = requests.get(f"{BASE_URL}/search", params=params)
data = response.json()

print(f"Total number of resources found: {data.get('meta', {}).get('totalCount')}")

print("\nList of titles:")
for item in data.get('data', []):
    print(f"  - {item['attributes'].get('dct_title_s', 'N/A')}")
Click "Run" to see the API response...
Click "Run" to see the output...

Field-Directed Search

Advanced Search

Goal: Search for "Transportation" specifically in the Subject field.

Request: GET /api/v1/search?q=Transportation&search_field=dct_subject_sm

import requests
import json

BASE_URL = "https://lib-btaageoapi-dev-app-01.oit.umn.edu/api/v1"

# Step 4: Field-directed search
params = {
    'q': 'Transportation',
    'search_field': 'dct_subject_sm',
    'page': 1,
    'per_page': 10
}

response = requests.get(f"{BASE_URL}/search", params=params)
data = response.json()

print(f"Total number of resources found: {data.get('meta', {}).get('totalCount')}")

print("\nList of titles:")
for item in data.get('data', []):
    print(f"  - {item['attributes'].get('dct_title_s', 'N/A')}")
Click "Run" to see the API response...
Click "Run" to see the output...

Faceted Search

Facets

Goal: Search for "seattle" and filter for "Maps".

Request: GET /api/v1/search?q=seattle&include_filters[gbl_resourceClass_sm][]=Maps

import requests
import json

BASE_URL = "https://lib-btaageoapi-dev-app-01.oit.umn.edu/api/v1"

# Step 5: Faceted search (Maps only)
params = {
    'q': 'seattle',
    'include_filters[gbl_resourceClass_sm][]': 'Maps',
    'page': 1,
    'per_page': 10
}

response = requests.get(f"{BASE_URL}/search", params=params)
data = response.json()

print(f"Total Maps Found: {data.get('meta', {}).get('totalCount')}")

print("\nList of titles:")
for item in data.get('data', []):
    print(f"  - {item['attributes'].get('dct_title_s', 'N/A')}")
Click "Run" to see the API response...
Click "Run" to see the output...

Faceted Search (Includes)

Facets

Goal: Search for "seattle", filter for "Maps" AND "Washington".

Request: GET /api/v1/search?q=seattle&include_filters...

import requests
import json

BASE_URL = "https://lib-btaageoapi-dev-app-01.oit.umn.edu/api/v1"

# Step 6: Faceted search (Maps + Washington)
params = {
    'q': 'seattle',
    'include_filters[gbl_resourceClass_sm][]': 'Maps',
    'include_filters[dct_spatial_sm][]': 'Washington',
    'page': 1,
    'per_page': 10
}

response = requests.get(f"{BASE_URL}/search", params=params)
data = response.json()

print(f"Total Found: {data.get('meta', {}).get('totalCount')}")

print("\nList of titles:")
for item in data.get('data', []):
    print(f"  - {item['attributes'].get('dct_title_s', 'N/A')}")
Click "Run" to see the API response...
Click "Run" to see the output...

Faceted Search (Excludes)

Facets

Goal: Search for "seattle", filter for "Maps", "Washington", but EXCLUDE "Pennsylvania State University".

Request: GET /api/v1/search?q=seattle&exclude_filters...

import requests
import json

BASE_URL = "https://lib-btaageoapi-dev-app-01.oit.umn.edu/api/v1"

# Step 7: Faceted search (Maps + Washington - PSU)
params = {
    'q': 'seattle',
    'include_filters[gbl_resourceClass_sm][]': 'Maps',
    'include_filters[dct_spatial_sm][]': 'Washington',
    'exclude_filters[schema_provider_s][]': 'Pennsylvania State University',
    'page': 1,
    'per_page': 10
}

response = requests.get(f"{BASE_URL}/search", params=params)
data = response.json()

print(f"Total Found: {data.get('meta', {}).get('totalCount')}")

print("\nList of titles:")
for item in data.get('data', []):
    print(f"  - {item['attributes'].get('dct_title_s', 'N/A')}")
Click "Run" to see the API response...
Click "Run" to see the output...

Spatial Search (BBox)

Spatial

Goal: Compare BBox search with within and overlap spatial modes.

Request: GET /api/v1/search?q=maps&include_filters[geo][type]=bbox&include_filters[geo][relation]=within|overlap...

import requests
import json

BASE_URL = "https://lib-btaageoapi-dev-app-01.oit.umn.edu/api/v1"

# Step 8a: Bounding Box Search (Minnesota) - within
within_params = {
    'q': 'maps',
    'include_filters[geo][type]': 'bbox',
    'include_filters[geo][field]': 'dcat_bbox',
    'include_filters[geo][relation]': 'within',
    'include_filters[geo][top_left][lat]': '49.0',
    'include_filters[geo][top_left][lon]': '-97.2',
    'include_filters[geo][bottom_right][lat]': '43.5',
    'include_filters[geo][bottom_right][lon]': '-89.5',
    'page': 1,
    'per_page': 10
}
within_response = requests.get(f"{BASE_URL}/search", params=within_params)
within_data = within_response.json()

# Step 8b: Bounding Box Search (Minnesota) - overlap
overlap_params = dict(within_params)
overlap_params['include_filters[geo][relation]'] = 'overlap'
overlap_response = requests.get(f"{BASE_URL}/search", params=overlap_params)
overlap_data = overlap_response.json()

print(f"within total: {within_data.get('meta', {}).get('totalCount')}")
print(f"overlap total: {overlap_data.get('meta', {}).get('totalCount')}")
Click "Run" to see the API response...
Click "Run" to see the output...

Spatial Search (Distance)

Spatial

Goal: Find "parks" resources within 50km of Minneapolis.

Request: GET /api/v1/search?q=parks&include_filters[geo][type]=distance...

import requests
import json

BASE_URL = "https://lib-btaageoapi-dev-app-01.oit.umn.edu/api/v1"

# Step 9: Distance Search (50km from Minneapolis)
params = {
    'q': 'parks',
    'include_filters[geo][type]': 'distance',
    'include_filters[geo][field]': 'dcat_centroid',
    'include_filters[geo][center][lat]': '44.9778',
    'include_filters[geo][center][lon]': '-93.2650',
    'include_filters[geo][distance]': '50km',
    'page': 1,
    'per_page': 10
}

response = requests.get(f"{BASE_URL}/search", params=params)
data = response.json()

print(f"Total Found: {data.get('meta', {}).get('totalCount')}")

print("\nList of titles:")
for item in data.get('data', []):
    print(f"  - {item['attributes'].get('dct_title_s', 'N/A')}")
Click "Run" to see the API response...
Click "Run" to see the output...

Spatial Search (Polygon)

Spatial

Goal: Find "water" resources intersecting with Colorado state boundaries.

Request: GET /api/v1/search?q=water&include_filters[geo][type]=polygon...

import requests
import json

BASE_URL = "https://lib-btaageoapi-dev-app-01.oit.umn.edu/api/v1"

# Step 10: Polygon Search (Colorado)
params = {
    'q': 'water',
    'include_filters[geo][type]': 'polygon',
    'include_filters[geo][field]': 'locn_geometry',
    'include_filters[geo][relation]': 'intersects',
    'include_filters[geo][points][0][lat]': '41.0',
    'include_filters[geo][points][0][lon]': '-109.0',
    'include_filters[geo][points][1][lat]': '41.0',
    'include_filters[geo][points][1][lon]': '-102.0',
    'include_filters[geo][points][2][lat]': '37.0',
    'include_filters[geo][points][2][lon]': '-102.0',
    'include_filters[geo][points][3][lat]': '37.0',
    'include_filters[geo][points][3][lon]': '-109.0',
    'page': 1,
    'per_page': 10
}

response = requests.get(f"{BASE_URL}/search", params=params)
data = response.json()

print(f"Total Found: {data.get('meta', {}).get('totalCount')}")

print("\nList of titles:")
for item in data.get('data', []):
    print(f"  - {item['attributes'].get('dct_title_s', 'N/A')}")
Click "Run" to see the API response...
Click "Run" to see the output...

Advanced Search (adv_q)

Advanced

Goal: Find "Maps" having "Island" in title but NOT "Antarctica".

Request: GET /api/v1/search?q=&adv_q=...

import requests
import json

BASE_URL = "https://lib-btaageoapi-dev-app-01.oit.umn.edu/api/v1"

# Step 11: Advanced Search with adv_q
# Logic: (ResourceClass=Maps AND Title=Island) NOT Title=Antarctica
adv_query = [
    {"op": "AND", "f": "gbl_resourceClass_sm", "q": "Maps"},
    {"op": "AND", "f": "dct_title_s", "q": "Island"},
    {"op": "NOT", "f": "dct_title_s", "q": "antarctica"}
]

params = {
    'q': '',
    'adv_q': json.dumps(adv_query),
    'page': 1,
    'per_page': 10
}

response = requests.get(f"{BASE_URL}/search", params=params)
data = response.json()

print(f"Total Found: {data.get('meta', {}).get('totalCount')}")

print("\nList of titles:")
for item in data.get('data', []):
    print(f"  - {item['attributes'].get('dct_title_s', 'N/A')}")
Click "Run" to see the API response...
Click "Run" to see the output...