ThrustLab

Async resources

Simulations and sweeps are async: creating one returns immediately with status: "pending" or "running". To get the result, you can either:

  1. Poll the resource until it reaches a terminal state.
  2. Subscribe to webhook events.

Polling with the SDK

The SDK provides a wait() helper that polls the resource at a configurable interval until terminal:

"""Single-point simulation: auth -> submit -> wait() -> read the canonical result.

Run it:
    export THRUSTLAB_API_KEY=key_...        # never hard-code the key
    python examples/simulations/run_sync.py

The verification combo below (Spektrum Avian 4260 800 kV + 10.5x4.5 + Liperior
4S 5000 mAh @ 70% throttle, static) converges to ~9.78 N / ~8645 rpm. Swap in
your own component IDs, or resolve them by name with client.components.find(...).
"""

from thrustlab import Client

client = Client()  # reads $THRUSTLAB_API_KEY from the environment

project = client.projects.create(name="sdk single-point example")

# Resolve components by name (find() returns the single match or raises
# AmbiguousComponentError / NotFoundError). Or paste explicit IDs instead:
#   motor_id = "comp_motor_xxx"
motor = client.components.find(name="Spektrum Avian 4260 800Kv")
prop = client.components.find(name="10.5x4.5")
battery = client.components.find(name="Liperior 5000mAh 4S 35C")

sim = client.simulations.create(
    project_id=project["id"],
    battery_component_id=battery["id"],
    airspeed_m_s=0.0,
    density_kg_m3=1.225,
    battery_charge_pct=100,
    rotor_groups=[
        {
            "label": "main",
            "count": 4,
            "motor_component_id": motor["id"],
            "propeller_component_id": prop["id"],
            "throttle_pct": 70,
        }
    ],
)
print(f"created {sim['id']}, status={sim['status']}")

# wait() polls until completed / failed / canceled (or a timeout sentinel).
result = client.simulations.wait(sim["id"], timeout=300)
print(f"final status: {result['status']}")

if result["status"] == "completed":
    # Canonical snake_case result (post-D-01): per-rotor group under its label
    # index ("1", "2", ...); aggregate roll-ups under "All".
    per_rotor = result["result"]["1"]
    aggregate = result["result"]["All"]
    print(f"per-rotor thrust: {per_rotor['thrust_n']:.2f} N")
    print(f"per-rotor rpm:    {per_rotor['rpm']:.0f}")
    print(f"total thrust:     {aggregate['total_thrust_n']:.2f} N")

Terminal states are: completed, failed, canceled (one 'l' on the wire). The SDK adds one client-side terminal state, timed_out, set when wait() exceeds its timeout= parameter.

Subscribing via webhooks

For long-running sweeps and production pipelines, subscribe to the simulation.completed, simulation.failed, sweep.completed, and sweep.failed event types via a webhook endpoint. See the webhooks guide and event types.

We use cookies and analytics tools to understand how you use ThrustLab and improve the experience. Privacy Policy

Async resources · ThrustLab API