This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Python SDK for Cercalia

Typed Python SDK for Cercalia APIs with Pydantic models, reference docs, and source code access.

    Cercalia SDK for Python

    Python SDK

    A modern, type-safe Python SDK for Cercalia web services. Build powerful location-based applications with geocoding, routing, POI search, and moreβ€”all with full type hints and Pydantic models.

    Reference: https://docs.cercalia.com/docs/sdks/reference/python/

    Source code: https://github.com/Cercalia/cercalia-sdk-python

    from cercalia import GeocodingService, RoutingService, CercaliaConfig
    
    config = CercaliaConfig(api_key="your-api-key")
    geocoding = GeocodingService(config)
    
    candidates = geocoding.geocode(
        street="Gran VΓ­a",
        locality="Madrid"
    )
    

    Table of Contents

    About Cercalia

    Cercalia is a comprehensive geospatial platform that provides mapping, geocoding, routing, and location intelligence services. Originally developed in Spain, Cercalia offers exceptional coverage of European markets with high-quality cartographic data and advanced spatial analysis capabilities.

    This SDK provides a clean, modern interface to Cercalia’s web services, abstracting away the complexity of raw API calls while preserving the full power of the platform.

    Features

    • 🎯 Type-Safe: Built with Pydantic models and full type hints for excellent IDE support
    • 🐍 Pythonic: Clean, idiomatic Python API following PEP 8 conventions
    • πŸ“¦ Modern Architecture: Clean, modular design with clear separation of concerns
    • πŸ”„ Comprehensive Services: 12 geospatial services including:
      • Geocoding - Convert addresses to coordinates
      • Reverse Geocoding - Get addresses from coordinates
      • Routing - Calculate optimal routes with turn-by-turn directions
      • Suggest - Autocomplete and place suggestions
      • POI Search - Find points of interest
      • Isochrones - Calculate reachability areas
      • Proximity - Distance calculations and nearest neighbor search
      • Geofencing - Spatial boundary operations
      • Static Maps - Generate map images
      • Snap to Road - Match GPS traces to road network
      • Geoment - Geographic element queries
      • And more…
    • πŸ›‘οΈ Resilient: Built-in retry logic and error handling
    • πŸ“ Well-Documented: Comprehensive docstrings and examples
    • πŸ§ͺ Tested: Full test coverage with pytest (172 tests)

    Installation

    pip install cercalia-sdk
    

    Or install from source:

    git clone https://github.com/cercalia/cercalia-sdk-python.git
    cd cercalia-sdk-python
    make install
    

    Development

    The project includes a Makefile for common development tasks:

    # Install development dependencies
    make install
    
    # Run tests with coverage
    make test
    
    # Run linting (ruff and mypy)
    make lint
    
    # Format code
    make format
    
    # Build package distribution
    make build
    
    # Clean build artifacts
    make clean
    

    Publishing to PyPI

    To publish a new version to PyPI, ensure you have set the following environment variables:

    export TWINE_USERNAME=__token__
    export TWINE_PASSWORD=pypi-your-token-here
    make publish
    

    Requirements

    • Python 3.12+
    • pydantic >= 2.0
    • requests >= 2.28

    Getting Your API Key

    Before using the SDK, you’ll need a Cercalia API key:

    1. Register for a Cercalia account at https://clients.cercalia.com/register
    2. Obtain your API key from your account dashboard
    3. Configure the SDK with your credentials (see Quick Start below)

    The API key authenticates your requests and tracks usage against your plan’s quota.

    Quick Start

    Here’s a simple example to get you started:

    from cercalia import (
        CercaliaConfig,
        GeocodingService,
        RoutingService,
        Coordinate,
    )
    
    # Configure the SDK
    config = CercaliaConfig(
        api_key="your-api-key-here",
        base_url="https://lb.cercalia.com/services/v2/json"
    )
    
    # Geocode an address
    geocoding = GeocodingService(config)
    results = geocoding.geocode(
        street="Paseo de la Castellana, 1",
        locality="Madrid",
        country_code="ESP"
    )
    
    print(results[0])
    # GeocodingCandidate(
    #     name='Paseo de la Castellana, 1, Madrid',
    #     coord=Coordinate(lat=40.419838, lng=-3.692580),
    #     type='road',
    #     locality='Madrid',
    #     region='Comunidad de Madrid',
    #     ...
    # )
    
    # Calculate a route
    routing = RoutingService(config)
    route = routing.calculate_route(
        origin=Coordinate(lat=40.419838, lng=-3.692580),
        destination=Coordinate(lat=41.387015, lng=2.170047)  # Barcelona
    )
    
    print(f"Distance: {route.distance / 1000:.2f} km")
    print(f"Duration: {route.duration // 60} minutes")
    

    Usage

    Environment Variables

    You can configure the SDK using environment variables:

    # .env file
    export CERCALIA_API_KEY=your-api-key-here
    export CERCALIA_BASE_URL=https://lb.cercalia.com/services/v2/json
    
    import os
    from cercalia import CercaliaConfig, GeocodingService
    
    config = CercaliaConfig(
        api_key=os.environ["CERCALIA_API_KEY"],
        base_url=os.environ.get("CERCALIA_BASE_URL", "https://lb.cercalia.com/services/v2/json")
    )
    
    geocoding = GeocodingService(config)
    results = geocoding.geocode(street="Gran VΓ­a", locality="Madrid")
    

    Per-Service Configuration

    Each service can be configured independently:

    from cercalia import CercaliaConfig, GeocodingService
    
    geocoding = GeocodingService(
        CercaliaConfig(
            api_key="your-api-key-here",
            base_url="https://lb.cercalia.com/services/v2/json"
        )
    )
    

    Core Services

    Geocoding

    Convert addresses and place names into geographic coordinates.

    from cercalia import CercaliaConfig, GeocodingService
    
    config = CercaliaConfig(api_key="your-api-key")
    geocoding = GeocodingService(config)
    
    # Basic address geocoding
    results = geocoding.geocode(
        street="Calle AlcalΓ‘, 42",
        locality="Madrid",
        country_code="ESP"
    )
    
    print(results[0])
    # GeocodingCandidate(
    #     name='Calle AlcalΓ‘, 42, Madrid',
    #     coord=Coordinate(lat=40.419123, lng=-3.697421),
    #     type='road',
    #     locality='Madrid',
    #     locality_code='28079',
    #     region='Comunidad de Madrid',
    #     region_code='28',
    #     country='EspaΓ±a',
    #     country_code='ESP',
    #     postal_code='28014',
    #     geometry_type='rd'
    # )
    
    # Geocode by postal code
    postal_results = geocoding.geocode(
        postal_code="08025",
        country_code="ESP"
    )
    
    # Road milestone geocoding
    road_results = geocoding.geocode_road(
        road="M-45",
        km=12,
        subregion="Madrid",
        country_code="ESP"
    )
    

    Key Features:

    • Address normalization and standardization
    • Multiple result candidates with quality scoring
    • Support for partial addresses
    • Administrative boundary information (city, region, country)
    • Geometry type metadata

    Reverse Geocoding

    Get address information from geographic coordinates.

    from cercalia import CercaliaConfig, ReverseGeocodingService, Coordinate
    
    config = CercaliaConfig(api_key="your-api-key")
    reverse = ReverseGeocodingService(config)
    
    # Get address from coordinates
    result = reverse.reverse_geocode(
        coord=Coordinate(lat=41.387015, lng=2.170047)
    )
    
    print(result)
    # ReverseGeocodingResult(
    #     ge=GeographicElement(
    #         name='PlaΓ§a Catalunya, Barcelona',
    #         locality='Barcelona',
    #         region='CataluΓ±a',
    #         ...
    #     ),
    #     distance=15.2
    # )
    
    # Batch reverse geocoding
    coords = [
        Coordinate(lat=37.777041, lng=-3.785477),
        Coordinate(lat=37.877041, lng=-3.785770)
    ]
    batch_results = reverse.reverse_geocode_batch(coords, level="adr")
    
    # Get timezone information
    timezone_result = reverse.reverse_geocode(
        coord=Coordinate(lat=52.252025, lng=20.995254),
        level="timezone",
        date_time="2026-01-15T14:30:00Z"
    )
    

    Key Features:

    • Precise address resolution from coordinates
    • Configurable search radius
    • Batch processing for multiple coordinates
    • Timezone information retrieval
    • Census section and SIGPAC parcel data (Spain)

    Routing

    Calculate optimal routes between locations with turn-by-turn directions.

    from cercalia import CercaliaConfig, RoutingService, Coordinate
    
    config = CercaliaConfig(api_key="your-api-key")
    routing = RoutingService(config)
    
    # Simple point-to-point route
    route = routing.calculate_route(
        origin=Coordinate(lat=40.416775, lng=-3.703790),  # Madrid
        destination=Coordinate(lat=41.387015, lng=2.170047)  # Barcelona
    )
    
    print(f"Distance: {route.distance / 1000:.2f} km")
    print(f"Duration: {route.duration // 60} minutes")
    print(f"WKT: {route.wkt[:100]}...")
    
    # Route with waypoints
    route_with_waypoints = routing.calculate_route(
        origin=Coordinate(lat=40.416775, lng=-3.703790),
        destination=Coordinate(lat=41.387015, lng=2.170047),
        waypoints=[
            Coordinate(lat=41.648823, lng=-0.887618)  # Zaragoza
        ]
    )
    
    # Route avoiding tolls
    no_toll_route = routing.calculate_route(
        origin=Coordinate(lat=40.416775, lng=-3.703790),
        destination=Coordinate(lat=41.387015, lng=2.170047),
        avoid_tolls=True
    )
    
    # Truck routing with restrictions
    truck_route = routing.calculate_route(
        origin=Coordinate(lat=40.416775, lng=-3.703790),
        destination=Coordinate(lat=41.387015, lng=2.170047),
        vehicle_type="truck",
        truck_weight=40000,  # 40 tons (kg)
        truck_height=450,    # 4.5m (cm)
        truck_width=255,     # 2.55m (cm)
        truck_length=1800    # 18m (cm)
    )
    
    # Get only distance and time (faster, no geometry)
    distance_time = routing.get_distance_time(
        origin=Coordinate(lat=40.416775, lng=-3.703790),
        destination=Coordinate(lat=41.387015, lng=2.170047)
    )
    

    Key Features:

    • Turn-by-turn navigation instructions
    • Multiple route optimization strategies (fastest, shortest, balanced)
    • Support for waypoints and multi-stop routes
    • Vehicle-specific routing (car, truck, bicycle, pedestrian)
    • Avoid tolls, highways, ferries
    • WKT and GeoJSON geometry output

    Other Available Services

    The SDK provides many more specialized services:

    • SuggestService - Autocomplete and place search suggestions

      suggest = SuggestService(config)
      results = suggest.search_streets("Gran Via", "ESP")
      
    • PoiService - Search for points of interest

      poi = PoiService(config)
      restaurants = poi.search_nearest(
          coord=Coordinate(lat=40.416, lng=-3.703),
          categories=["C001"],
          radius=5000
      )
      
    • IsochroneService - Calculate reachability areas

      isochrone = IsochroneService(config)
      area = isochrone.calculate(
          center=Coordinate(lat=40.416, lng=-3.703),
          value=30,
          weight="time"
      )
      
    • ProximityService - Distance calculations and nearest neighbor search

      proximity = ProximityService(config)
      result = proximity.find_nearest(
          origin=Coordinate(lat=40.416, lng=-3.703),
          destinations=[...],
          limit=5
      )
      
    • GeofencingService - Point-in-polygon and spatial boundary operations

      geofencing = GeofencingService(config)
      is_inside = geofencing.is_inside_circle(
          point=Coordinate(lat=40.416, lng=-3.703),
          center=Coordinate(lat=40.420, lng=-3.700),
          radius=1000
      )
      
    • SnapToRoadService - Snap GPS coordinates to road network

      snaptoroad = SnapToRoadService(config)
      result = snaptoroad.match(points=[...])
      
    • StaticMapsService - Generate static map images

      staticmaps = StaticMapsService(config)
      result = staticmaps.generate_city_map("Barcelona", "ESP", width=400, height=300)
      print(result.image_url)
      
    • GeomentService - Geographic element geometry queries

      geoment = GeomentService(config)
      result = geoment.get_municipality_geometry(municipality_code="ESP080193")
      

    See the examples directory for complete, runnable code samples for each service.

    Project Structure

    cercalia-sdk-python/
    β”œβ”€β”€ cercalia/
    β”‚   β”œβ”€β”€ services/           # Service implementations
    β”‚   β”‚   β”œβ”€β”€ cercalia_client.py      # Base HTTP client
    β”‚   β”‚   β”œβ”€β”€ geocoding_service.py    # Geocoding service
    β”‚   β”‚   β”œβ”€β”€ routing_service.py      # Routing service
    β”‚   β”‚   β”œβ”€β”€ suggest_service.py      # Suggest service
    β”‚   β”‚   β”œβ”€β”€ reversegeocoding_service.py
    β”‚   β”‚   β”œβ”€β”€ poi_service.py
    β”‚   β”‚   β”œβ”€β”€ proximity_service.py
    β”‚   β”‚   β”œβ”€β”€ isochrone_service.py
    β”‚   β”‚   β”œβ”€β”€ geofencing_service.py
    β”‚   β”‚   β”œβ”€β”€ geoment_service.py
    β”‚   β”‚   β”œβ”€β”€ snaptoroad_service.py
    β”‚   β”‚   β”œβ”€β”€ staticmaps_service.py
    β”‚   β”‚   └── __init__.py
    β”‚   β”œβ”€β”€ types/              # Pydantic models and types
    β”‚   β”‚   β”œβ”€β”€ common.py               # Shared types (Coordinate, etc.)
    β”‚   β”‚   β”œβ”€β”€ geocoding.py            # Geocoding-specific types
    β”‚   β”‚   β”œβ”€β”€ routing.py              # Routing-specific types
    β”‚   β”‚   β”œβ”€β”€ api_response.py         # API response helpers
    β”‚   β”‚   └── __init__.py
    β”‚   β”œβ”€β”€ utils/              # Utilities
    β”‚   β”‚   β”œβ”€β”€ logger.py               # Debug logging
    β”‚   β”‚   └── retry.py                # Retry logic
    β”‚   β”œβ”€β”€ config.py           # Configuration management
    β”‚   └── __init__.py         # Main entry point
    β”œβ”€β”€ examples/               # Usage examples
    β”‚   β”œβ”€β”€ main.py
    β”‚   β”œβ”€β”€ geocoding.py
    β”‚   β”œβ”€β”€ routing.py
    β”‚   └── ...
    β”œβ”€β”€ tests/                  # Test suites
    β”‚   β”œβ”€β”€ test_geocoding_service.py
    β”‚   β”œβ”€β”€ test_routing_service.py
    β”‚   └── ...
    β”œβ”€β”€ pyproject.toml          # Package configuration
    └── README.md
    

    Key Architectural Decisions

    Pydantic Models: All API responses are parsed into Pydantic models, providing automatic validation, serialization, and excellent IDE support.

    Strict Typing: The SDK uses Python type hints throughout. All API responses are fully typed, even fields that aren’t currently mapped.

    Data Integrity: The SDK follows strict “Golden Rules”:

    • No fallback values for administrative fieldsβ€”if the API returns None, the SDK returns None
    • All administrative entities include both name and ID
    • Coordinates never use default values (no 0,0 fallbacks)
    • Geometry type metadata is always preserved

    See AGENTS.md for detailed architectural guidelines.

    Advanced Configuration

    Debug Logging

    Enable detailed logging to troubleshoot API calls:

    from cercalia import CercaliaConfig, GeocodingService
    from cercalia.utils.logger import logger
    
    # Enable debug logging
    logger.set_debug(True)
    
    config = CercaliaConfig(api_key="your-api-key")
    geocoding = GeocodingService(config)
    
    # Logs will show:
    # - Request URLs and parameters
    # - Response status and timing
    # - Error details
    

    Custom Base URL

    If you’re using a Cercalia private instance or proxy:

    config = CercaliaConfig(
        api_key="your-api-key",
        base_url="https://your-custom-domain.com/cercalia/v2/json"
    )
    

    Error Handling

    All services raise typed errors that you can catch and handle:

    from cercalia import CercaliaConfig, GeocodingService, CercaliaError
    
    config = CercaliaConfig(api_key="your-api-key")
    geocoding = GeocodingService(config)
    
    try:
        results = geocoding.geocode(street="Invalid Address")
    except CercaliaError as e:
        print(f"Cercalia API error [{e.code}]: {e.message}")
    except Exception as e:
        print(f"Unexpected error: {e}")
    

    Response Caching

    For production applications, consider implementing response caching:

    from functools import lru_cache
    from cercalia import CercaliaConfig, GeocodingService
    
    config = CercaliaConfig(api_key="your-api-key")
    geocoding = GeocodingService(config)
    
    @lru_cache(maxsize=1000)
    def cached_geocode(street: str, locality: str) -> tuple:
        results = geocoding.geocode(street=street, locality=locality)
        # Convert to tuple for caching (Pydantic models are not hashable by default)
        return tuple((r.name, r.coord.lat, r.coord.lng) for r in results)
    

    Examples

    The SDK includes comprehensive examples in the examples/ directory:

    Run the examples:

    cd examples
    python main.py
    python geocoding.py
    python routing.py
    # ... etc
    

    Documentation

    Official Cercalia Documentation

    For detailed API reference, advanced features, and service-specific parameters, visit the official Cercalia documentation:

    https://docs.cercalia.com/docs/

    The official docs cover:

    • Complete API reference for all services
    • Advanced parameters and options
    • Response format specifications
    • Rate limits and quotas
    • Best practices and optimization tips
    • Regional coverage details

    SDK Documentation

    • Type Definitions: The SDK is fully typed. Use your IDE’s autocomplete to explore available methods and parameters.
    • Source Code: All services include comprehensive docstrings. Read the source in cercalia/services/ for implementation details.
    • Tests: The test suite in tests/ provides additional usage examples and edge cases.

    Getting Help

    1. Check the examples - Most common use cases are covered
    2. Read the official docs - https://docs.cercalia.com/docs/
    3. Review type hints - Your IDE will show you all available options
    4. Open an issue - For SDK-specific bugs or feature requests

    License

    This SDK is provided for use with Cercalia web services. Please refer to your Cercalia service agreement for terms of use.

    For questions about licensing, contact Cercalia.


    Built with Python | Powered by Cercalia | Documentation | Get API Key