client.components
The catalog of motors, propellers, and batteries. You reference
component ids in simulation and sweep bodies; create() adds your own
private custom components. Custom components you submit through
submissions appear here once approved.
Methods
| Method | Endpoint | Returns |
|---|---|---|
client.components.list(**filters) | GET /v1/components | CursorPager of components |
client.components.find(**filters) | GET /v1/components | Single component (one-hit-or-raise) |
client.components.create(type=..., name=..., spec_json=...) | POST /v1/components | New private component |
client.components.retrieve(component_id) | GET /v1/components/{id} | Single component |
client.components.brands() | GET /v1/components/brands | List of {name, count} brand summaries |
Filter by type
Every simulation needs at least one motor, one propeller, and one battery.
The type filter is the fastest way to scope the catalog:
from thrustlab import Client
client = Client()
motors = list(client.components.list(type="motor", limit=100))
print(f"{len(motors)} motors in catalog")
Valid type values: motor, propeller, battery. Anything else —
esc included, ThrustLab doesn't catalog ESCs — is rejected with a 422.
Filter by brand
brand is a discrete filter that takes the bracket [in] suffix, with a
comma-separated list of names:
kde_or_tmotor = client.components.list(
type="motor",
**{"brand[in]": "KDE,T-Motor"},
)
for m in kde_or_tmotor:
print(m["id"], m["name"], m["spec_json"].get("brand"))
The full list of brands, with per-brand counts, is available via
client.components.brands():
brands = client.components.brands()
for b in brands["data"]:
print(b["name"], b["count"]) # KDE 42, T-Motor 38, ...
Filter motors by Kv rating
Numeric spec fields take a bracket-suffixed filter — kv[gte] / kv[lte]
(also [gt] / [lt], currently treated the same as the inclusive forms).
Pass them through **extra_filters:
mid_kv = client.components.list(type="motor", **{"kv[gte]": 400, "kv[lte]": 900})
for m in mid_kv:
print(m["id"], m["name"], m["spec_json"]["kv"])
Type-specific filters
Every other numeric spec filter follows the same key[gte] / key[lte]
pattern and maps to a spec_json field server-side:
| Type | Filter key | spec_json field |
|---|---|---|
motor | kv[gte] / kv[lte] | kv |
motor | weight[gte] / weight[lte] | weight |
motor | resistance[gte] / resistance[lte] | R |
motor | current_max[gte] / current_max[lte] | iq_max |
motor | poles[gte] / poles[lte] | n |
propeller | diameter[gte] / diameter[lte] | diameter |
propeller | pitch[gte] / pitch[lte] | pitch |
propeller | weight[gte] / weight[lte] | weight |
propeller | max_rpm[gte] / max_rpm[lte] | maxRPM |
propeller | inertia[gte] / inertia[lte] | inertia |
battery | series_cells[gte] / series_cells[lte] | series_cells |
battery | capacity[gte] / capacity[lte] | total_capacity_mAh |
battery | c_rating[gte] / c_rating[lte] | c_rating |
battery | weight[gte] / weight[lte] | weight_g |
An unrecognized filter key — a typo, or a key that doesn't apply to the
given type — is silently dropped rather than erroring, so a filter that
returns everything usually means the key doesn't match this table.
# 14-16 inch propellers with at least 8 inch pitch
props = client.components.list(
type="propeller",
**{"diameter[gte]": 14, "diameter[lte]": 16, "pitch[gte]": 8},
)
Other list filters
| Filter | Type | Notes |
|---|---|---|
visibility | "public" | "private" | Restrict to the shared catalog or your own private customs. Omit for both. |
search (or q) | str | Case-insensitive substring match on name. If both are supplied, search wins. |
sort_by | str | name, created_at, or (with type set) a type-specific spec key. |
sort_order | "asc" | "desc" | Default asc. |
ids_only | bool | Returns every matching id in one bounded response (for "select all") instead of a cursor-paginated page. |
See the API reference for the full list of per-type sort keys and spec filter keys.
Retrieve one component
motor = client.components.retrieve("comp_2c5tQ...")
print(motor["spec_json"])
The spec_json field carries every type-specific spec that the catalog has
recorded — Kv, internal resistance, mass, etc. for motors; chord and twist
for propellers; cell count and chemistry for batteries.
Create your own
create() persists a private custom component and returns its id:
prop = client.components.create(
type="propeller",
name="My Custom 10.5x4.5",
spec_json={...},
)
The per-type required spec_json fields, units, and validation rules are in
Creating your own components.
Recipe: pick the highest-thrust prop for a given motor
motor_id = "comp_2c5tQ..."
# Find every prop, then pick by trying them and reading thrust.
results = []
for prop in client.components.list(type="propeller", limit=50):
sim = client.simulations.create(
project_id="proj_xxx",
battery_component_id="comp_xxx",
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": 100,
}],
)
final = client.simulations.wait(sim["id"], timeout=120)
if final["status"] == "completed":
results.append((prop["name"], final["result"]["1"]["thrust_n"]))
results.sort(key=lambda r: -r[1])
for name, thrust in results[:5]:
print(f"{name}: {thrust:.1f} N")
For larger searches, use sweeps to run all combinations in one request instead of N round-trips.
See also
- Submissions — submit a custom component for review
- Starred components — per-project favorites