Skip to main content

Module motor_finder

Module motor_finder 

Source
Expand description

Motor stock and prices from motor.fusionspace.co’s public API.

The motor finder lists every AeroTech, Cesaroni and Loki motor that a dozen U.S. vendors carry, with each vendor’s stock and price. Its API is a handful of static JSON files, rebuilt about hourly, with no key, no rate limit and no query parameters: a client fetches a whole file and filters it itself. The files are Endpoint::Meta (when the data was built, and counts), Endpoint::Motors (every motor some vendor lists, D class and up), Endpoint::InStock (the same, only those in stock at one vendor or more), Endpoint::Vendors, and one motor’s page (Endpoint::motor). Prices are whole cents; a listing’s unit price is its sticker price over its pack size. The motor data itself (classes, impulses, delays) comes from ThrustCurve.org, and designations are spelled as ThrustCurve spells them.

parse_meta, parse_motors, parse_in_stock, parse_vendors and parse_motor read an answer, refusing one of another schema version, one whose count disagrees with its list, and a motor or listing that breaks the API’s own rules (a pack of no motors, a unit price over the sticker price, a cheapest offer on a motor out of stock). The fetch_ functions ask a Client for the file, so the answer comes from the cache when it can, and offline from the cache only; an answer that doesn’t parse is never cached. Stock moves by the hour, so a copy stays fresh for TTL_S, an hour. Show ATTRIBUTION (it is on every Fetched) wherever a price or stock is shown: the API’s data license, CC BY 4.0, asks for the credit “Motor stock data from motor.fusionspace.co”, and its terms say to check stock and price on the vendor’s own page before relying on them.

How far to trust it: a value is the answer’s, unchanged, bar a listing status the API adds later (tests/motor_finder.rs reads every field of every recorded answer back). Whether a vendor really has a motor, at that price, is the vendor’s to say: the finder reads their public listings, up to about an hour old when it builds its files, and a fresh cached copy may be an hour older again. One value that breaks a rule refuses the whole file, so the last good copy is kept; a cheapest offer with no price, which the API allows, and a listing status it adds later (read as ListingStatus::Unknown) are read.

use hpr_net::motor_finder;

// The in-stock list as recorded on 2026-10-01 at 07:07 UTC.
let body = include_bytes!("../tests/fixtures/replay/motor-finder-in-stock.json");
let list = motor_finder::parse_in_stock(body)?;
let l_class: Vec<_> = list.motors.iter().filter(|m| m.impulse_class == "L").collect();
assert_eq!((list.motors.len(), l_class.len()), (282, 20));

Structs§

Counts
Meta’s counts.
Listing
One vendor’s listing of a motor.
Meta
meta.json: when the data was built, and how much there is.
Motor
A motor, with every vendor’s listing of it.
MotorList
motors.json or in-stock.json.
MotorName
A motor’s manufacturer and designation, checked by Endpoint::motor so its page’s URL stays in the API’s motors/ folder. Its fields are private, so it can’t be changed past the checks.
MotorPage
One motor’s page, motors/{manufacturer}/{designation}.json.
Offer
The cheapest in-stock offer of a motor: the in-stock listing with the lowest unit price. The API’s schema lets its prices be null; no recorded offer has them so.
Vendor
A vendor the finder reads.
VendorList
vendors.json.

Enums§

Endpoint
One of the API’s files.
Hazmat
Whether a motor ships as hazardous material (U.S. DOT), as the site labels it from the propellant’s weight. Its API describes the labels as “required (>62.5g or H+), varies (F/G near the limit — vendor-dependent), none (<=62.5g, A-E)”. On the 2026-10-01 recording, every D and E motor is NotRequired and every H and up Required; F and G motors are Varies (75) or Required (29).
ListingStatus
A listing’s stock. A status the API adds later reads as ListingStatus::Unknown, so one new word doesn’t refuse the whole list.
MotorFinderError
Why a motor finder request or answer was refused.
MotorType
How a motor is built.

Constants§

ATTRIBUTION
The credit the API’s data license asks for, in its words (“Motor stock data from motor.fusionspace.co”), with the license, CC BY 4.0, and the API’s caution about stock and price.
BASE_URL
The API’s base URL, version 1.
MANUFACTURERS
The manufacturers the API lists: each one’s name as the API writes it, and the slug its motors’ pages sit under.
SCHEMA_VERSION
The schema version this module reads. A breaking change ships under a new path (/api/v2/), so an answer of another version is refused.
TTL_S
How long a cached answer counts as fresh, s: an hour, as often as the site rebuilds the files.

Functions§

fetch_in_stock
Fetches in-stock.json through client, as fetch_meta does.
fetch_meta
Fetches meta.json through client.
fetch_motor
Fetches one motor’s page through client, as fetch_meta does: the motor, and when its page was built. A page for another motor than the one asked for is refused, and never cached.
fetch_motors
Fetches motors.json through client, as fetch_meta does.
fetch_vendors
Fetches vendors.json through client, as fetch_meta does.
parse_in_stock
Reads in-stock.json: as parse_motors, and every motor must be in stock.
parse_meta
Reads meta.json.
parse_motor
Reads one motor’s page.
parse_motors
Reads motors.json.
parse_vendors
Reads vendors.json.
unix_s
Seconds since the Unix epoch of an ISO 8601 UTC time as the API writes it, YYYY-MM-DDTHH:MM:SS followed by Z or +00:00, with optional fractional seconds dropped; None for anything else.