Skip to main content

pickpoint (Python SDK)

Official Python SDK for Pickpoint — a geolocation platform with four APIs under one key:

API What it does
Geocoding Address ↔ coordinates (forward, reverse, place lookup)
Address search Typeahead / autocomplete for address inputs
Routing Routes, matrices, optimized multi-stop, elevation
Device tracking Register devices over HTTP; stream live GPS over WebSocket / gRPC

Built for maps, delivery, logistics, and anything that needs places, routes, or live location. Data is OpenStreetMap-backed; HTTP responses are plain JSON / GeoJSON. Docs: pickpoint.io/docs.

This package is the idiomatic async Python client for that platform:

Module Import Role
root pickpoint HTTP: geocode, search, routing, devices, client-tokens
tracking pickpoint.tracking Realtime tracks (WebSocket by default, gRPC supported)
tracking.v2 pickpoint.tracking.v2 Generated protobuf (tracking.v2)

Apache-2.0. Go sibling: github.com/pickpoint/go-sdk. Rust sibling: github.com/pickpoint/rust-sdk. JS sibling: @pickpoint/sdk. Wire schema: pickpoint-proto.

pip install pickpoint

Requires Python 3.10+.

python-sdk/
  src/pickpoint/           # HTTP client
  src/pickpoint/tracking/  # tracking session client
  src/pickpoint/tracking/v2/  # protobuf stubs

Public API

One Client, one auth session, whole public HTTP surface:

import asyncio
import os
from pickpoint import Client, Config

async def main() -> None:
    async with Client(Config(api_key=os.environ["PICKPOINT_API_KEY"])) as pp:
        places = await pp.forward({"q": "Berlin", "limit": "5"})
        print(places)

        await pp.reverse({"lat": "52.52", "lon": "13.405"})
        await pp.search({"q": "Alexanderplatz"})
        await pp.route({
            "locations": [
                {"lat": 52.52, "lon": 13.40},
                {"lat": 52.53, "lon": 13.42},
            ],
            "costing": "auto",
        })

        devices = await pp.devices.list()
        print(devices.total)

asyncio.run(main())

API map

Method HTTP Notes
forward / geocoding.forward GET /v2/geocode/forward Nominatim-style; returns list
reverse / geocoding.reverse GET /v2/geocode/reverse dict | None
lookup / geocoding.lookup GET /v2/address/lookup e.g. osm_ids
forward_batch / reverse_batch / lookup_batch same Geocoding only; conveyor ≤20 in flight
search / address.search GET /v2/address/search Photon autocomplete
route / optimized_route / matrix / locate / elevation POST /v2/route… Valhalla JSON body
devices.list / get / create / update / delete /v2/devices Typed dataclasses
devices.command POST …/command Payload bytes (SDK base64-encodes)
mint_client_tokens POST /v2/client-tokens Package helper; needs secret api_key

Query params for geocode/address are plain dict[str, str].

Auth

Provide exactly one of:

Field Header Use
api_key x-api-key Backends, workers, CLIs
client_auth Authorization: Bearer Short-lived pair; auto-refresh
access_token Authorization: Bearer Static token, no refresh

Keep the secret API key on the server. For client apps mint client-tokens and pass client_auth.

from pickpoint import Client, ClientAuth, Config, mint_client_tokens

pair = await mint_client_tokens(
    Config(api_key=os.environ["PICKPOINT_API_KEY"]),
    scopes=["geocoding", "address", "routing", "devices"],
    ttl_sec=600,
)

async with Client(
    Config(
        client_auth=ClientAuth(
            access_token=pair.access_token,
            refresh_token=pair.refresh_token,
            expires_at=pair.expires_at,
        )
    )
) as pp:
    ...

Refresh behavior (same as Go/Rust/JS):

  1. Proactive refresh at ~50% of access TTL (single-flight).
  2. On HTTP 401, one refresh + retry.
  3. If refresh fails → auth error.

Config

Config(
    api_key="…",
    base_url="https://api.pickpoint.io",  # default
    timeout=30.0,
    max_retries=3,
    retry_base=1.0,
    concurrency=20,
)
Constant Value
DEFAULT_BASE_URL https://api.pickpoint.io
DEFAULT_TIMEOUT 30s
DEFAULT_MAX_RETRIES 3
DEFAULT_RETRY_BASE 1s (MIN_RETRY_BASE = 0.2s)
MAX_CONCURRENCY 20

Tracking

Realtime publisher / listener over binary WebSocket (tracking.v2.proto subprotocol). gRPC via Transport.GRPC.

import asyncio
from pickpoint import tracking
from pickpoint.tracking.v2 import LatLng

async def main() -> None:
    client = await tracking.connect(
        tracking.Config(
            endpoint="wss://tracking.pickpoint.io",  # local: "ws://127.0.0.1:3100"
            device=tracking.DeviceAuth(
                client_id=device_uid,
                client_secret=device_secret,
            ),
        )
    )
    try:
        track_uid = await client.start_track(
            LatLng(latitude=55.75, longitude=37.61)
        )
        seq, ok = await client.publish(LatLng(latitude=55.76, longitude=37.62))
        # managed client_seq; ok=False if rate-limited locally
        await client.stop_track()
    finally:
        await client.close()

asyncio.run(main())

Auth modes

Config Role
device=DeviceAuth(…) Publisher (device)
listener=ListenerAuth(…) Dashboard / subscriber JWT

Exactly one of device / listener is required.

Main methods

Method Purpose
start_track Open a track; returns track_uid
publish Point on active track (managed client_seq); capped at 50 Hz
resume Manual resume; auto-reconnect also resumes
stop_track End track
send_event Opaque event ≤4 KiB; capped at 1 Hz
subscribe Listener: subscribe to a device UID
recv Next ServerMsg
recv_command / ack_command Inbound commands
close Tear down session

Limits enforced client-side: MAX_PUBLISH_HZ = 50, MAX_EVENT_BYTES = 4 KiB, MAX_EVENT_HZ = 1.


Develop

python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest -q

Live geocode batch e2e (skipped unless the key is set; 1000 requests each):

PICKPOINT_API_KEY= pytest tests/test_e2e_geocode_batch.py -q --tb=short
# optional: PICKPOINT_BASE_URL=https://api.pickpoint.io  (default: https://beta-api.pickpoint.io)

CI & release

  • PR.github/workflows/ci.yml (pytest on Python 3.10 / 3.12 / 3.13)
  • Push to main (untagged HEAD) → bump patch, tag vX.Y.Z, PyPI publish (OIDC) + GitHub Release in the same job
    (tag push via GITHUB_TOKEN does not start new workflows — publish cannot wait on the tag event)
  • Manual tag v* (pushed by a human) → publish + GitHub Release

Minor/major: bump version in pyproject.toml and __version__ in a PR, merge with [skip release] in the commit message, then:

git tag v2.1.0
git push origin v2.1.0

PyPI Trusted Publishing must match this workflow: repo python-sdk, workflow release.yml, environment pypi.

Protobuf stubs under src/pickpoint/tracking/v2 are generated from pickpoint-proto. Regenerate:

python -m grpc_tools.protoc \
  -I ../pickpoint-proto \
  --python_out=src/pickpoint/tracking/v2 \
  --grpc_python_out=src/pickpoint/tracking/v2 \
  ../pickpoint-proto/tracking/v2/*.proto
# then flatten nested tracking/v2/ paths and fix imports to `from . import …_pb2`

Download files

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

Source Distribution

pickpoint-2.0.2.tar.gz (26.4 kB view details)

Uploaded Source

Built Distribution

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

pickpoint-2.0.2-py3-none-any.whl (35.8 kB view details)

Uploaded Python 3

File details

Details for the file pickpoint-2.0.2.tar.gz.

File metadata

  • Download URL: pickpoint-2.0.2.tar.gz
  • Upload date:
  • Size: 26.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for pickpoint-2.0.2.tar.gz
Algorithm Hash digest
SHA256 809e7117f81ce9c178b69dbac9bbe3c169304f0fe8f77667f770e38894f339d9
MD5 efa8fa8fe59ba460a7ca62c75e5a0f55
BLAKE2b-256 3f9eeaf8565500b3c298275d2d61a19de99ed66ebc7e145f0f885f44cc02d831

See more details on using hashes here.

Provenance

The following attestation bundles were made for pickpoint-2.0.2.tar.gz:

Publisher: release.yml on pickpoint/python-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pickpoint-2.0.2-py3-none-any.whl.

File metadata

  • Download URL: pickpoint-2.0.2-py3-none-any.whl
  • Upload date:
  • Size: 35.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for pickpoint-2.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 9fc1614e0b85cbe9bcd574f5f415211d0ef42a5febcb7583710f487879c68f45
MD5 b24316deaa8d8b9486c42469ce955986
BLAKE2b-256 8edaaf2a3c36d71256af2b972740d819e203ee13ba398e18f5eda98f7dac6adf

See more details on using hashes here.

Provenance

The following attestation bundles were made for pickpoint-2.0.2-py3-none-any.whl:

Publisher: release.yml on pickpoint/python-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

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