altitude-sdk
altitude-sdk is a lightweight Python client for the Geotab Altitude APIs. It is designed to make getting started quick and easy, handling authentication, async job submission and polling, and result pagination so you can focus on the data rather than the plumbing.
Requires Python 3.10+.
Contents
- Installation
- Quick start
- Two calling patterns
- Working with job ids
- Client modules
- Module reference
- Examples
- Resuming with an id
Installation
pip install altitude-sdk
Quick start
from altitude_sdk import AltitudeClient
# Authenticate with your API key; sent as `Authorization: Bearer <api_key>`.
client = AltitudeClient(api_key="your-api-key")
industries = client.filters.get_industries()
AltitudeClient accepts a few optional settings:
import httpx
from altitude_sdk import AltitudeClient
client = AltitudeClient(
api_key="your-api-key",
timeout=60.0, # seconds, or an httpx.Timeout
)
# Use as a context manager to close the underlying HTTP client automatically.
with AltitudeClient(api_key="your-api-key") as client:
industries = client.filters.get_industries()
Two calling patterns
Every method on the client is one of two kinds:
- Job process — long-running analytics. The call returns a
PagedWorkflowhandle rather than data. Use.all()to submit, poll to completion, paginate, and return all rows in one step, or drive it manually with.run(),.status(),.results(),.pages(), and.cancel(). A few workflows also expose.time_series_results(). - Direct API — synchronous reference/CRUD calls. The method returns the data immediately, no workflow involved.
The Type column in each table below tells you which kind a method is.
Working with job ids
Every job-process method submits a job that the server identifies by an id. Hold on to that id and you can come back to the job later — from a different process, or after your program restarts — without re-running the analysis.
Keep the workflow in a variable instead of chaining .all() onto the call. .all() waits for
the job to finish, and afterwards wf.id holds the id of the job that produced those rows:
wf = client.stop_analytics.rda(params) # keep the handle
rows = wf.all() # submit → poll to completion → paginate
print(wf.id) # "its_123" — save this to resume later
This is the same for every job-process method — every method marked Job in the tables below:
poi = client.poi.analytics(params)
rows = poi.all()
print(poi.id)
speed = client.traffic.speed_summary(params)
rows = speed.all()
print(speed.id)
wf.id is None until the job is submitted. If you want it before the results are ready, use
.run(), which submits without waiting:
wf = client.stop_analytics.rda(params)
wf.run() # submit, non-blocking — sets wf.id right away
print(wf.id) # "its_123"
.status() also carries the id alongside the current state:
wf.status() # {"id": "its_123", "status": "RUNNING", "links": {...}}
Once you have an id, see Resuming with an id.
Client modules
AltitudeClient exposes these module clients as attributes:
| Module | Attribute | Covers |
|---|---|---|
| AADT | client.aadt |
Annual average daily traffic jobs |
| Analyses | client.analyses |
Analysis zones and data-quality dates |
| Database | client.database |
Database information |
| Expansion factors | client.expansion_factors |
Expansion factors by zone |
| Filters | client.filters |
Reference filter options (industries, NAICS, vehicle classes, vocations) |
| Jobs | client.jobs |
Check status of / cancel any submitted job |
| Origin / destination | client.origin_destination |
OD matrices (open, closed, corridor), route and segment analysis |
| POI | client.poi |
Points-of-interest analytics, summaries, and locations |
| Regional travel metrics | client.rtm |
VDT, fuel economy, idle metrics, observed counts |
| Stop analytics | client.stop_analytics |
Regional domicile, fuel point, and stop-event analytics |
| Traffic | client.traffic |
Speed and harsh-event traffic analytics |
| Zones | client.zones |
Zone lookups, custom zones, and sub-types |
Module reference
AADT
client.aadt
| Method | Type | Description |
|---|---|---|
modeled_aadt(params) |
Job | Start modeled annual average daily traffic job |
Analyses
client.analyses
| Method | Type | Description |
|---|---|---|
get_analysis_zones(id) |
Direct | Get zone GeoJSON features for an analysis |
get_last_processed_date() |
Direct | Get the last processed date |
Database
client.database
| Method | Type | Description |
|---|---|---|
get_info() |
Direct | Get database information |
Expansion factors
client.expansion_factors
| Method | Type | Description |
|---|---|---|
by_zones(params, page_token=None, page_size=None) |
Direct | Get expansion factors by zone |
Filters
client.filters
| Method | Type | Description |
|---|---|---|
get_industries() |
Direct | Get grouped industry filter options |
get_naics(...) |
Direct | Get raw NAICS code list |
get_vehicle_classes(...) |
Direct | Get vehicle class filter options |
get_vocations() |
Direct | Get vocation filter options |
Jobs
client.jobs
| Method | Type | Description |
|---|---|---|
get_job_status(id) |
Direct | Get the status of a submitted job |
cancel_job(id) |
Direct | Cancel a running job |
Origin / destination
client.origin_destination
| Method | Type | Description |
|---|---|---|
open_matrix(params) |
Job | Start open OD matrix job (also .time_series_results()) |
closed_matrix(params) |
Job | Start closed OD matrix job (also .time_series_results()) |
corridor_matrix(params) |
Job | Start corridor OD matrix job (also .time_series_results()) |
route(params) |
Job | Start OD route analysis job |
segment(params) |
Job | Start OD segment analysis job |
POI
client.poi
| Method | Type | Description |
|---|---|---|
analytics(params) |
Job | Start POI analytics job (also .time_series_results()) |
summary(params) |
Job | Start POI summary job |
locations(params) |
Job | Start point of interest job |
Regional travel metrics
client.rtm
| Method | Type | Description |
|---|---|---|
fuel_economy(params) |
Job | Start fuel economy job |
idle_metrics(params) |
Job | Start idle metrics job (also .time_series_results()) |
modeled_vdt(params) |
Job | Start modeled vehicle distance traveled job (also .time_series_results()) |
observed_counts(params) |
Job | Start observed counts job (also .time_series_results()) |
vdt(params) |
Job | Start vehicle distance traveled job (also .time_series_results()) |
Stop analytics
client.stop_analytics
| Method | Type | Description |
|---|---|---|
fuel_point_analytics(params) |
Job | Start Fuel Point Analytics job (also .time_series_results()) |
rda(params) |
Job | Start Regional Domicile Analytics job |
stop_events(params) |
Job | Start stop events job |
Traffic
client.traffic
| Method | Type | Description |
|---|---|---|
harsh_events_per_segment(params) |
Job | Start harsh events per segment job |
road_reverse_lookup(params) |
Job | Start road reverse lookup job |
speed_map_metrics(params) |
Job | Start speed map metrics job |
speed_per_segment(params) |
Job | Start speed per segment job |
speed_summary(params) |
Job | Start speed summary job |
speed_trend(params) |
Job | Start speed trend job |
Zones
client.zones
| Method | Type | Description |
|---|---|---|
by_hierarchy(params) |
Job | Start zones by hierarchy job |
by_ids(params) |
Job | Start zone data fetch by IDs |
by_radius(params) |
Job | Start zones by radius job |
by_sub_type(params) |
Job | Start custom zones by sub-type fetch |
contained_zones(params) |
Job | Start contained zones job |
custom_zone_batch(params) |
Job | Start custom zone batch job |
road_segments(params) |
Job | Start road segments job |
batch_update_custom_zones(params) |
Job | Batch update custom zones |
create_custom_zone(params) |
Direct | Create custom zone |
create_sub_type(params) |
Direct | Create custom zone sub-type |
list_sub_types() |
Direct | List custom zone sub-types |
update_sub_type(id, params) |
Direct | Update custom zone sub-type |
Examples
Job process method
Job-process methods return a PagedWorkflow. The simplest path is .all(), which
submits the job, polls until it finishes, paginates, and returns every row:
from altitude_sdk import AltitudeClient
client = AltitudeClient(api_key="your-api-key")
params = {
"zones": [{"code": "32007", "iso_3166_2": "US-NV", "type": "County"}],
"isMetric": False,
"dateFrom": "2025-03-01",
"dateTo": "2025-03-05",
}
# All-in-one: submit → poll to completion → paginate → list of results
rows = client.stop_analytics.rda(params).all()
For more control, drive the workflow step by step:
import time
wf = client.stop_analytics.rda(params)
wf.run() # submit the job (non-blocking); sets wf.id
while wf.status()["status"] != "DONE": # poll until the job finishes
time.sleep(5)
rows = wf.results() # fetch the results once DONE
Direct API method
Direct methods return data immediately — no workflow, no polling:
from altitude_sdk import AltitudeClient
client = AltitudeClient(api_key="your-api-key")
industries = client.filters.get_industries()
naics = client.filters.get_naics(min_naics_level=2, max_naics_level=2)
Resuming with an id
Pass id= to the same method that started the job — it knows where that job's results
live. Every job-process method accepts it:
# Later — different process, same job. Nothing is re-submitted.
handle = client.stop_analytics.rda(id="its_123")
if handle.status()["status"] == "DONE":
rows = handle.results()
Two rules apply to an id handle:
- Pass exactly one of
paramsorid— passing both, or neither, raisesAltitudeWorkflowError. - It retrieves, it does not submit.
.results(),.pages(),.status(), and.time_series_results()work;.all()and.cancel()raiseAltitudeWorkflowError, because there is nothing left to start or stop.
Metadata
Release files for altitude-sdk 2.0.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| altitude_sdk-2.0.5.tar.gz | 98.6 kB | Without provenance | Details for altitude_sdk-2.0.5.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| altitude_sdk-2.0.5-py3-none-any.whl | Python 3 | none | any | Details for altitude_sdk-2.0.5-py3-none-any.whl |
Total release size: 153.1 kB
Release files / altitude_sdk-2.0.5.tar.gz
| Download URL | altitude_sdk-2.0.5.tar.gz |
|---|---|
| Size | 98.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c1cf45fd3184f150534fedbc103084a38ae6a794a37169879ada418aa986d97b
|
|
BLAKE2b-256 checksum How to use checksums |
f0e6d42adda384e008d58904180c47c0306ad09fe4f6a09a2e39b97e32489e23
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / altitude_sdk-2.0.5-py3-none-any.whl
| Download URL | altitude_sdk-2.0.5-py3-none-any.whl |
|---|---|
| Size | 54.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1cef2a6f71154737aefdd865dbbf25991b1e52f1538a6c7c30bb9e2286253ae0
|
|
BLAKE2b-256 checksum How to use checksums |
62a8d5354adc149d104763140bf09a369d067ebe4983f1e7ed34d66940fcf5ef
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for altitude-sdk 2.0.5
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.