Skip to main content

Python SDK for automapa.pl map services API (geocoding, routing, roads)

Project description

Automapa Map Services Python SDK

European Geocoding, Routing & Address Autocomplete

Python Versions License: MIT

Python SDK for the Automapa Map Services REST API. Simplifies integration with geocoding, routing, and address autocomplete services for Europe.


Getting started with your .env file

You will receive a .env file from us containing your API credentials. Place it in the root directory of this repository:

AUTOMAPA_API_KEY=your-key
AUTOMAPA_API_PASSWORD=your-password

Once the .env file is in place, you can test all endpoints against the live API using Docker — no local Python installation required:

# Run the full test suite (unit + integration) inside Docker
make docker-test

# Run only integration tests (live API calls)
make docker-test-integration

# Run only unit tests (no API calls)
make docker-test-unit

# Run all checks (unit, integration, lint, type checks)
make docker-check

Zero dependencies. The SDK has no runtime dependencies — it uses only Python's built-in urllib. It is compatible with Python 3.11 and above.


1. Overview

The SDK covers:

  • Geocoding — convert an address to coordinates and back
  • Routing — calculate routes, distance matrices, and point-order optimization
  • Address autocomplete — suggestions as the user types
  • Google Geocoding API compatibility — optional google response format

For the full list of endpoints and parameters, see the Automapa REST API documentation.


2. Installation

pip install automapa-map-services

Or with uv:

uv add automapa-map-services

Requirements: Python 3.11+, no external runtime dependencies.


3. Client configuration

from automapa_map_services import ApiClient, Config

client = ApiClient(Config(
    key="YOUR_API_KEY",
    password="YOUR_PASSWORD",
))

4. Session handling

A session is opened automatically (lazy) on the first call that requires authorisation. To open it manually:

client.session().generate_session(key="YOUR_API_KEY", pass_="YOUR_PASSWORD")

5. Available services

Class Methods
Geocoder geocode(), geocodemulti(), revgeocode(), revgeocodemulti()
Autocomplete search(), search_address()
Road get_segment_info(), speed_check(), speed_check_multi()
RoadPermit add(), overwrite(), remove(), list()
Routes matrix(), optimize(), optimize_queue(), optimize_queue_result(), route()
Speed speed_report(), speed_report_result()

All methods also accept camelCase aliases (searchAddress(), getSegmentInfo(), etc.) for consistency with the PHP SDK.

Geocoder

# Address → coordinates
response = client.geocoder().geocode({
    "address":    {"city": "Warsaw", "street": "Domaniewska", "house": "37"},
    "maxResults": 1,
})
results = response.data()  # list of results, each with x, y, city, street, ...

# Reverse geocoding — coordinates → address
response = client.geocoder().revgeocode({
    "point":  [21.0073642, 52.18288],
    "params": {},
})
address = response.data()  # city, street, house, pcode, ...

Autocomplete

Address and POI autocomplete — returns suggestions as the user types.

search() — search by phrase

response = client.autocomplete().search({
    "query": "Warsaw Domaniewska 37",
    # "types": ["place"],  # optional: "place", "poi", or both
})

items = response.data()["items"]

for item in items:
    print(item["name"])          # "Domaniewska 37, 02-672 Warsaw"
    print(item["type"])          # "place"
    print(item["subtype"])       # "building"
    print(item["coords"]["x"])   # longitude (lng)
    print(item["coords"]["y"])   # latitude (lat)

Each items entry contains: type, subtype, name, province, district, community, place, quarter, street, number, postal_code, coords.{x,y}.

search_address() — step-by-step address search

Useful for multi-field address forms (city → street → number → postcode).

response = client.autocomplete().search_address({
    "query": {
        "city":    "Warsaw",
        "street":  "Dom",     # partial street name
        "number":  "",
        "zipcode": "02-672",
    },
    "source":   "street",              # field being searched: "place", "street", "number", "zipcode"
    "selected": ["city", "zipcode"],   # fields already confirmed by the user
    # "limit": 10,                     # optional: max results (default 10)
})

items = response.data()["items"]
# [{"city": "Warsaw", "street": "Domaniewska", "zipcode": "02-672", "count": 1}]

Each entry may contain: city, street, number, zipcode, count, and optionally coords.{x,y}.

Note on Autocomplete coordinates: Unlike Geocoder, coordinates are nested: coords.x = longitude, coords.y = latitude.

Routes

Route calculation, distance matrix, and point-order optimisation.

route() — calculate a route

response = client.routes().route({
    "points": [
        {"x": 21.0073642, "y": 52.2297},  # Warsaw (x=lng, y=lat)
        {"x": 18.6282,    "y": 54.3520},  # Gdańsk
    ],
    "route": {
        "type":    "short",  # "quick" | "short" | "optimal"
        "traffic": True,     # True = take live traffic into account
    },
    "object": {"type": "car"},
})

data = response.data()
print(round(data["length"] / 1000, 1), "km")
import time; print(time.strftime("%H:%M:%S", time.gmtime(data["eta"])))  # estimated travel time
print(data["mapurl"])   # link to map
# data["desc"]  — turn-by-turn manoeuvre list
# data["tolls"] — toll charges

matrix() — distance / time matrix

response = client.routes().matrix({
    "points": [
        {"x": 21.0073642, "y": 52.2297},
        {"x": 18.6282,    "y": 54.3520},
        {"x": 16.9252,    "y": 52.4064},
    ],
    "type": 1,  # 1 = time (duration in minutes), 2 = distance (length in metres)
})

for row in response.data():
    print(f"Segment {row['points']}: {round(row['length'] / 1000)} km, {row['duration']} min")

optimize() — synchronous optimisation (max 10 points)

response = client.routes().optimize({
    "points":   [{"x": 21.0, "y": 52.2}, {"x": 18.6, "y": 54.4}],
    "type":     1,      # 1 = time, 2 = distance
    "fixedEnd": False,  # True = last point is the destination; False = return to start
    "object":   {"type": "car"},
})

data = response.data()
data["order"]    # optimal index sequence, e.g. "0,3,2,1"
data["sections"] # segment details: x, y, eta, dist

optimize_queue() + optimize_queue_result() — asynchronous optimisation (max 50 points)

import time

# Step 1: submit — each point requires an "id" field
response   = client.routes().optimize_queue({
    "points":     [{"id": "Warsaw", "x": 21.0, "y": 52.2}],
    "optimizeBy": "time",  # "time" or "distance"
    "object":     {"type": "car"},
})
request_id = response.data()["requestId"]

# Step 2: poll for the result
while True:
    time.sleep(2)
    result = client.routes().optimize_queue_result({"requestId": request_id})
    data   = result.data()
    if data["resultReady"] is True:
        break

data["optimizedSequence"]  # list of point IDs in the optimal order

6. Examples

# Copy configuration
cp .env.example .env
# Fill in AUTOMAPA_API_KEY and AUTOMAPA_API_PASSWORD in .env

# Routes
python examples/routes_route.py                # point-to-point route
python examples/routes_matrix.py               # distance/time matrix
python examples/routes_optimize.py             # sync optimisation (max 10 points)
python examples/routes_optimize_async.py       # async optimisation (max 50 points)

# Geocoder
python examples/geocoder_geocode.py            # single address → coordinates
python examples/geocoder_geocodemulti.py       # batch address geocoding
python examples/geocoder_revgeocode.py         # coordinates → single address
python examples/geocoder_revgeocodemulti.py    # coordinates → multiple addresses

# Autocomplete
python examples/autocomplete_search.py         # search places and POI by phrase
python examples/autocomplete_search_address.py # search address objects

# Road
python examples/road_segment_info.py           # road segment metadata
python examples/road_speed_check.py            # speed limit for a single point
python examples/road_speed_check_multi.py      # speed limits for multiple points

# Road permits
python examples/road_permit_list.py            # list permits
python examples/road_permit_add.py             # create a new permit
python examples/road_permit_overwrite.py <id>  # replace an existing permit
python examples/road_permit_remove.py <id>     # delete a permit

# Speed reports
python examples/speed_report.py                # submit async speed report
python examples/speed_report_result.py <id>    # poll for report results

Or simply run make examples to run all examples.


7. Passing additional parameters

The SDK does not restrict unknown parameters — all fields are forwarded to the API as-is:

client.geocoder().geocode({
    "address":       {"city": "Warsaw"},
    "myCustomParam": "value",  # passed through without modification
})

8. Low-level call() and request()

# Via service + method name (preferred)
client.call("Geocoder", "newMethod", {"param": "value"})

# Or via full URL path (fallback)
client.request("POST", "/v3/Geocoder/newMethod", {"param": "value"})

9. Response formats: native vs google

# Native format (default)
response = client.geocoder().geocode({"address": {"city": "Kraków"}})
data = response.data()   # API data
raw  = response.raw()    # full raw response (always available)

# Google format
response = client.geocoder().geocode({
    "address": {"city": "Kraków"},
    "format":  "google",
})

10. Google format field limitations

Google field Value
geometry.viewport always null (not provided by the API)
place_id always null (not provided by the API)

Note: The Automapa API uses x = longitude and y = latitude — the opposite of Google's convention.


11. Error handling

Situation Exception class
Invalid API key / password AuthenticationException
Expired session SessionException
Parameter validation failure ValidationException
Resource not found NotFoundException
Rate limit exceeded RateLimitException
Network / urllib error NetworkException
Server error (5xx) ServerException
Unexpected response UnknownResponseException
from automapa_map_services.exceptions import AuthenticationException, AutomapaException

try:
    response = client.geocoder().geocode({"address": {"city": "Warsaw"}})
except AuthenticationException as e:
    print("Authentication error:", e)
except AutomapaException as e:
    print("API error:", e)

License

MIT © 2026 Automapa sp. z o.o.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

automapa_map_services-0.1.0.tar.gz (22.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

automapa_map_services-0.1.0-py3-none-any.whl (27.0 kB view details)

Uploaded Python 3

File details

Details for the file automapa_map_services-0.1.0.tar.gz.

File metadata

  • Download URL: automapa_map_services-0.1.0.tar.gz
  • Upload date:
  • Size: 22.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Pop!_OS","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for automapa_map_services-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ac382fd7dab497fb2ec0a3862842bb40e0d7c39aec191c0b87bd45cb5690bdd4
MD5 f12e427205eefcd2934f182aa4f8fe0a
BLAKE2b-256 c8c7eef8439bbf43d8f3ff1f1fe98a666423b4542df8a7c2ceab92ec5ec2d501

See more details on using hashes here.

File details

Details for the file automapa_map_services-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: automapa_map_services-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 27.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Pop!_OS","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for automapa_map_services-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7df1f373ead71f8e2e064f125bb2457d9f1475d011e26e92d2e6af7d1c239d6d
MD5 32463afd7f784e1e083cdb88a716426e
BLAKE2b-256 e93b39bf26fb88e792da9e859eef8d62dced454458837a6107435c8644f30e31

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page