"""Pydantic models for Apple Maps Server API responses.
Model names and field names match Apple's official API documentation exactly.
Docstrings explain what each field represents in familiar terms.
See: https://developer.apple.com/documentation/applemapsserverapi
"""
from enum import StrEnum
from pydantic import BaseModel
[docs]
class AddressCategory(StrEnum):
[docs]
AdministrativeArea = "AdministrativeArea"
[docs]
SubAdministrativeArea = "SubAdministrativeArea"
[docs]
SubLocality = "SubLocality"
[docs]
PostalCode = "PostalCode"
[docs]
class PoiCategory(StrEnum):
[docs]
AirportGate = "AirportGate"
[docs]
AirportTerminal = "AirportTerminal"
[docs]
AmusementPark = "AmusementPark"
[docs]
AnimalService = "AnimalService"
[docs]
AutomotiveRepair = "AutomotiveRepair"
[docs]
Basketball = "Basketball"
[docs]
Campground = "Campground"
[docs]
CarRental = "CarRental"
[docs]
ConventionCenter = "ConventionCenter"
[docs]
Distillery = "Distillery"
[docs]
EVCharger = "EVCharger"
[docs]
Fairground = "Fairground"
[docs]
FireStation = "FireStation"
[docs]
FitnessCenter = "FitnessCenter"
[docs]
FoodMarket = "FoodMarket"
[docs]
GasStation = "GasStation"
[docs]
MovieTheater = "MovieTheater"
[docs]
MusicVenue = "MusicVenue"
[docs]
NationalMonument = "NationalMonument"
[docs]
NationalPark = "NationalPark"
[docs]
Nightlife = "Nightlife"
[docs]
Planetarium = "Planetarium"
[docs]
Playground = "Playground"
[docs]
PostOffice = "PostOffice"
[docs]
PublicTransport = "PublicTransport"
[docs]
ReligiousSite = "ReligiousSite"
[docs]
Restaurant = "Restaurant"
[docs]
RockClimbing = "RockClimbing"
[docs]
SkatePark = "SkatePark"
[docs]
University = "University"
[docs]
Volleyball = "Volleyball"
[docs]
class SearchResultType(StrEnum):
"""Result type filter for /v1/search."""
[docs]
physicalFeature = "physicalFeature"
[docs]
pointOfInterest = "pointOfInterest"
[docs]
class SearchACResultType(StrEnum):
"""Result type filter for /v1/searchAutocomplete."""
[docs]
physicalFeature = "physicalFeature"
[docs]
pointOfInterest = "pointOfInterest"
[docs]
class SearchRegionPriority(StrEnum):
"""Importance of searchRegion for /v1/search and /v1/searchAutocomplete.
Apple possible values: default, required.
"""
[docs]
class Location(BaseModel):
"""A coordinate pair from Apple Maps API.
latitude: north-south position (e.g. 37.334)
longitude: east-west position (e.g. -122.009)
"""
[docs]
class StructuredAddress(BaseModel):
"""Detailed address components of a place.
Apple uses different terminology than most geocoding APIs:
- locality = city
- administrativeArea = state/province name
- administrativeAreaCode = state/province short code (e.g. "NY")
- subAdministrativeArea = county name
- postCode = postal/ZIP code
- fullThoroughfare = full street address (number + street, e.g. "841 Broadway")
- thoroughfare = street name (e.g. "Broadway")
- subThoroughfare = street/house number (e.g. "841")
- subLocality = neighborhood or area within the city
- areasOfInterest = common names for the surrounding area
- dependentLocalities = neighborhood names
"""
[docs]
administrativeArea: str | None = None
[docs]
administrativeAreaCode: str | None = None
[docs]
subAdministrativeArea: str | None = None
[docs]
areasOfInterest: list[str] | None = None
[docs]
dependentLocalities: list[str] | None = None
[docs]
fullThoroughfare: str | None = None
[docs]
locality: str | None = None
[docs]
postCode: str | None = None
[docs]
subLocality: str | None = None
[docs]
subThoroughfare: str | None = None
[docs]
thoroughfare: str | None = None
[docs]
class MapRegion(BaseModel):
"""A rectangular bounding box on a map.
Expressed as south-west and north-east corners.
"""
[docs]
class Place(BaseModel):
"""A place returned by geocode, reverseGeocode, or place lookup endpoints.
coordinate: lat/lng of the place
formattedAddressLines: human-readable address lines (e.g. ["841 Broadway", "New York, NY 10003"])
structuredAddress: parsed address components
displayMapRegion: suggested map viewport for displaying this place
"""
[docs]
name: str | None = None
[docs]
coordinate: Location | None = None
[docs]
structuredAddress: StructuredAddress | None = None
[docs]
country: str | None = None
[docs]
countryCode: str | None = None
[docs]
displayMapRegion: MapRegion | None = None
[docs]
alternateIds: list[str] | None = None
[docs]
class SearchPlace(Place):
"""Extended Place returned by /v1/search with POI category info.
poiCategory: point-of-interest category (e.g. Restaurant, MovieTheater).
Unknown values from Apple fail validation so we notice and add support.
"""
[docs]
poiCategory: PoiCategory | None = None
[docs]
class PlaceResults(BaseModel):
"""Response from /v1/geocode and /v1/reverseGeocode.
results: list of Place objects matching the query
"""
[docs]
class SearchResponse(BaseModel):
"""Response from /v1/search.
results: list of SearchPlace objects with optional POI category
displayMapRegion: suggested map viewport encompassing all results
paginationInfo: present when the request set enablePagination
"""
[docs]
results: list[SearchPlace]
[docs]
displayMapRegion: MapRegion | None = None
[docs]
class AutocompleteResult(BaseModel):
"""A single autocomplete suggestion from /v1/searchAutocomplete.
completionUrl: relative URL to /v1/search to fetch full details for this suggestion
displayLines: raw text lines Apple returns — use completionTitle / completionSubtitle instead
location: approximate coordinate of the suggestion
structuredAddress: parsed address components if available
"""
[docs]
completionUrl: str | None = None
[docs]
displayLines: list[str] | None = None
[docs]
location: Location | None = None
[docs]
structuredAddress: StructuredAddress | None = None
@property
[docs]
def completionTitle(self) -> str | None:
"""Primary display text (e.g. place name or street address)."""
return self.displayLines[0] if self.displayLines else None
@property
[docs]
def completionSubtitle(self) -> str | None:
"""Secondary display text (e.g. city, state)."""
return (
self.displayLines[1]
if self.displayLines and len(self.displayLines) > 1
else None
)
[docs]
class SearchAutocompleteResponse(BaseModel):
"""Response from /v1/searchAutocomplete.
results: list of autocomplete suggestions
"""
[docs]
results: list[AutocompleteResult]
[docs]
class TokenResponse(BaseModel):
"""Response from /v1/token.
accessToken: short-lived Bearer token for API requests
expiresInSeconds: token lifetime (typically 1800 = 30 minutes)
"""
[docs]
class GeocodeResult(BaseModel):
"""Provider-agnostic geocode result.
Identical to radar-mapping-api's GeocodeResult for drop-in replacement.
This abstraction allows swapping Apple Maps for Radar without changing consuming code.
"""
[docs]
address1: str | None = None
[docs]
address2: str | None = None
[docs]
postal_code: str | None
[docs]
country_code: str | None = None