---
title: "List Sweep Points V1"
method: GET
path: "/v1/sweeps/{public_id}/points"
tags: ["v1", "sweeps"]
---

# List Sweep Points V1

`GET /v1/sweeps/{public_id}/points`

## Request

- Base URL: `https://thrustlab.com`
- URL: `https://thrustlab.com/v1/sweeps/{public_id}/points`
- Auth: HTTP bearer

Return sweep_point rows for a /v1/ sweep with cursor pagination.

## Path parameters

- `public_id` string, required

## Query parameters

- `cursor` string, nullable
- `limit` integer

## Response `200`

Successful Response

- SweepPointListResponse
  - `data` SweepPointResource[], required
    - `failed` boolean, required
    - `index` integer, required
    - `inputs` SweepPointInputs, required: ESC-13 item 4 — the operating condition this grid point was solved at. Previously typed ``dict[str, Any]``, which is the wire equivalent of saying nothing: an SDK user got an untyped bag and had to learn the key set by running a sweep and reading one. ESC-13 already made the RUNTIME blob self-describing (it is built from the point rather than from a hardcoded five-key literal, so a new axis appears the day it lands); this makes the CONTRACT say so too. ``extra="allow"`` is load-bearing, not laziness. Two families of key are generated per-sweep and cannot be enumerated in a static model: * ``tilt_<group_index>`` — group-targeted tilt is one grid dimension per MASKED rotor group, so the key set depends on the mask. * ``component_<axis>_<slots>`` — a component axis contributes its selected index under a name encoding the slots it spans (``component_motor_0``, or ``component_motor_0-2`` when synced). The propeller-label axes (2026-09-20) are declared below rather than left to ``extra``: there is one key per axis whatever the mask targets, because a label axis is ONE global grid dimension — the masked groups all run the same size at a point. Declaring those away would be worse than leaving the model untyped, because a strict model would DROP them at serialization — the same failure mode as the 2026-06-02 aggregate-drop that ``rotors`` is deliberately non-coercing to avoid. Every declared field is optional and permissively typed for the same reason: this model documents the shape, it does not police it.
      - `airspeed` number, nullable: Forward airspeed at this point, m/s.
      - `battery_charge_pct` number, nullable: Pack state of charge at this point, %.
      - `component` SweepPointComponentSelection[]: Components selected at this point, one entry per swept slot. Empty when no component axis is active.
        - `axis` string, required: Which component was swapped: "motor", "propeller" or "battery".
        - `id` string, nullable: Public component id of the selected component.
        - `name` string, nullable: Display name of the selected component.
        - `slot` integer, required: Rotor-group index the swap applied to (0 for a battery axis).
      - `density` number, nullable: Air density at this point, kg/m^3.
      - `esc_pwm_frequency_khz` number, nullable: ESC switching frequency at this point, kHz. Present only when an ESC PWM axis is swept.
      - `esc_timing` string, nullable: Six-step commutation timing preset at this point ("low", "medium", "high", "auto"). Present only when an ESC timing axis is swept — absent means each rotor group used its own persisted setting.
      - `grid_index` integer[], nullable: Multi-dimensional coordinate of this point in the sweep grid, one entry per axis in the order the axes were declared. The flat `index` on the point itself is the pagination counter, not this.
      - `prop_diameter_m` number, nullable: Propeller diameter at this point, metres. Present only when a `prop_diameter_m` axis is swept; it applies to every rotor group `sweep.label_sweep_mask` targets, and to no other.
      - `prop_num_blades` integer, nullable: Blade count at this point. Present only when a `prop_num_blades` axis is swept; it applies to every rotor group `sweep.label_sweep_mask` targets, and to no other.
      - `prop_pitch_m` number, nullable: Geometric propeller pitch at this point, metres. Present only when a `prop_pitch_m` axis is swept; it applies to every rotor group `sweep.label_sweep_mask` targets, and to no other.
      - `throttle` number, nullable: Commanded throttle % at this point. Always present. NOTE: this is the value of the throttle AXIS when one is swept; with no throttle axis it echoes rotor group 0's persisted throttle and applies to no other group (DM-6) — read the per-rotor results for what each group actually ran at.
      - `vertical_speed` number, nullable: Signed vertical speed at this point, m/s (positive = climb).
    - `is_starred` boolean, required
    - `object` 'sweep_point', required
    - `rotors` object, nullable, required: Per-point rotor results, keyed per-rotor ("1", "2", ...) plus the "All"/"Battery" aggregates. Each per-rotor entry follows the canonical snake_case SimulationResultV1 shape; NON-coercing at runtime so aggregate-only fields are never dropped.
  - `display_labels` object, nullable
  - `has_more` boolean, required
  - `next_cursor` string, nullable, required
  - `object` 'list', required

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/thrustlab/apis/thrustlab-api.md) · [All operations](https://skmtc.dev/thrustlab/apis/thrustlab-api/llms.txt) · [OpenAPI document](https://skmtc.dev/thrustlab/apis/thrustlab-api/revisions/c19717e52529?raw)
