Skip to main content

thrustlab — official Python SDK for the ThrustLab API

PyPI Python License

The official Python client for ThrustLab — electric-UAV powertrain simulation as an API.

Install

pip install thrustlab

Requires Python 3.10+.

Quickstart

from thrustlab import Client

client = Client()  # reads $THRUSTLAB_API_KEY (never hard-code the key)

# Create a project
project = client.projects.create(name="my project")

# Run a single-point simulation and wait for the result.
# A rotor group carries the motor + propeller + throttle (0–100); the battery
# and flight condition are top-level. Resolve component IDs from the catalog
# (client.components.find(name=...)) or paste them directly.
sim = client.simulations.create(
    project_id=project["id"],
    battery_component_id="comp_batt_xxx",
    airspeed_m_s=0.0,
    density_kg_m3=1.225,
    battery_charge_pct=100,
    rotor_groups=[
        {
            "label": "main",
            "count": 4,
            "motor_component_id": "comp_motor_xxx",
            "propeller_component_id": "comp_prop_xxx",
            "throttle_pct": 70,
        }
    ],
)
result = client.simulations.wait(sim["id"], timeout=300)

# Canonical snake_case result: per-rotor group under "1"/"2"/…, roll-ups
# under "All" (a sibling `display_labels` map carries the human labels).
print(result["result"]["1"]["thrust_n"], result["result"]["All"]["total_thrust_n"])

Runnable end-to-end examples for every simulation type live in examples/: simulations/run_sync.py, sweeps/run_and_poll.py, and dynamic/run_and_poll.py.

Why the SDK (and not urllib / wget)?

The SDK gives you automatic retries with backoff, idempotency keys, cursor pagination, polling helpers, webhook signature verification, and typed errors. It is built on httpx and sends its own thrustlab-python/<version> User-Agent.

If you hand-roll a client anyway, use an HTTP library with a descriptive User-Agent (httpx, requests, or curl). ThrustLab's edge protection screens non-browser User-Agents such as stdlib Python-urllib/* and wget: API paths under /v1/ are exempt from the screening, but every other route blocks these at the edge with an opaque error 1010 page — the request never reaches ThrustLab, so no JSON error envelope is possible there.

Configuration

Setting Constructor arg Env var Default
API key api_key= THRUSTLAB_API_KEY (required)
Base URL base_url= THRUSTLAB_BASE_URL https://thrustlab.com
Timeout timeout= 30 (seconds)
Max retries max_retries= 3

Resources

Every /v1/ route family is exposed as an attribute on the client:

client.users
client.projects
client.simulations
client.sweeps
client.dynamic_simulations
client.components
client.submissions
client.starred_components
client.compute_units
client.webhook_endpoints

Error handling

from thrustlab import Client
from thrustlab.exceptions import (
    AuthenticationError,
    ValidationError,
    RateLimitError,
    NotFoundError,
)

client = Client()
try:
    client.simulations.create(project_id="proj_xxx", rotor_groups=[...], ...)
except ValidationError as exc:
    print(f"bad request: {exc.code} ({exc.param}): {exc.message}")
except RateLimitError as exc:
    print(f"rate limited; retry after {exc.retry_after}s")
except NotFoundError as exc:
    print(f"not found: {exc.message}")
except AuthenticationError as exc:
    print(f"auth failed: {exc.message}")

Every error carries .code, .type, .request_id, .http_status, and .message. ValidationError additionally exposes .param. See thrustlab.com/docs/guides/errors for the full code reference.

Pagination

List endpoints return a CursorPager — a lazy iterator that fetches the next page only when needed:

# Iterate all pages automatically
for project in client.projects.list():
    print(project["id"])

# Materialise the first page only
first_page = list(client.projects.list(limit=20))

Async polling

simulations.wait(), sweeps.wait(), and dynamic_simulations.wait() block until the resource reaches a terminal state (completed, failed, or canceled — one 'l' on the wire) or the timeout fires. On timeout the returned dict carries the SDK-side sentinel status="timed_out" (never a server state):

sweep = client.sweeps.create(...)
result = client.sweeps.wait(sweep["id"], timeout=600, poll_interval=2.0)
if result["status"] == "completed":
    for point in client.sweeps.list_points(sweep["id"]):
        print(point["rotors"]["1"]["thrust_n"])

Webhooks

from thrustlab import Webhook
from thrustlab.exceptions import SignatureVerificationError

WEBHOOK_SECRET = "whsec_..."

@app.post("/webhooks/thrustlab")
async def handle(request):
    payload = await request.body()
    sig    = request.headers["Thrustlab-Signature"]
    try:
        event = Webhook.verify(payload, sig, WEBHOOK_SECRET)
    except SignatureVerificationError:
        return Response(status_code=400)
    if event.type == "simulation.succeeded":
        print(event.data)

Retries

The client automatically retries on 429 (rate limit) and 5xx responses using exponential backoff with jitter. Set max_retries=0 to disable:

client = Client(max_retries=0)

Links

License

Apache-2.0. See LICENSE and NOTICE.

Download files

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

Source Distribution

thrustlab-0.5.0.tar.gz (263.7 kB view details)

Uploaded Source

Built Distribution

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

thrustlab-0.5.0-py3-none-any.whl (306.7 kB view details)

Uploaded Python 3

File details

Details for the file thrustlab-0.5.0.tar.gz.

File metadata

  • Download URL: thrustlab-0.5.0.tar.gz
  • Upload date:
  • Size: 263.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.9

File hashes

Hashes for thrustlab-0.5.0.tar.gz
Algorithm Hash digest
SHA256 533d8714de415c9b4ae04e0af5a2eb3e5c8800f806fb279e95c81b686d6325b7
MD5 52f70504a4b29259c1e78f7c1112f26d
BLAKE2b-256 3c2b690e5fc2cb2d7e4b302f834d6e430ee19f32d001a5e62d77620d624b5026

See more details on using hashes here.

File details

Details for the file thrustlab-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: thrustlab-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 306.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.9

File hashes

Hashes for thrustlab-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a7c951bdc210c1eeddabf1e205b2c528907b0618ac5910f6fdce8d353869afc7
MD5 127495d2aa60b7a1f859617663d41944
BLAKE2b-256 0f80624d2c5877ccea2dda52056b517543762610769487959883e7b008d1e62d

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.5.0 This release

2 files

0.4.0

2 files

0.3.2

2 files

0.3.1

2 files

0.3.0

2 files

0.1.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page