Programmatic access to the normalized launch feed and the per-pad weather assessment that powers rocketassessor.com. Included with the Developer plan ($19/mo or $180/yr).
Base URL https://rocket-assessor-engine.zeronoisereport.workers.dev
Send your key as a bearer token:
curl -H "Authorization: Bearer ra_live_xxxxxxxx" \
"https://rocket-assessor-engine.zeronoisereport.workers.dev/api/export?format=csv"
A ?api_key= query parameter also works for tools that can't set headers, though headers are preferred — query strings leak into logs.
Issue a key. Authenticate with your Clerk session token (not an API key) — easiest from the browser while signed in:
const token = await window.Clerk.session.getToken();
const res = await fetch(BASE + "/api/keys", {
method: "POST",
headers: { Authorization: "Bearer " + token, "Content-Type": "application/json" },
body: JSON.stringify({ label: "production" })
});
console.log(await res.json());
The plaintext key is returned once — we store only a SHA-256 hash, so it cannot be shown again. Lose it and you issue a new one.
GET /api/keys lists your keys (metadata only). DELETE /api/keys?id=<id> revokes one.
| Method | Path | Tier | Purpose |
|---|---|---|---|
| GET | /api/launches | public | All tracked launches + assessments |
| GET | /api/launch/:id | public | One launch |
| GET | /api/launches.ics | public | Calendar feed |
| GET | /api/health | public | Cache freshness |
| GET | /api/export | developer | CSV / JSON / NDJSON export |
| GET | /api/webhooks | developer | List webhooks |
| POST | /api/webhooks | developer | Register a webhook |
| DEL | /api/webhooks?id= | developer | Delete a webhook |
| Param | Values | Notes |
|---|---|---|
| format | csv · json · ndjson | defaults to csv |
| verdict | GO · CAUTION · NO-GO · PENDING | filter by verdict |
| provider | e.g. SpaceX | substring, case-insensitive |
| from / to | ISO 8601 | filter on launch time (NET) |
# every NO-GO launch in the window, as CSV
curl -H "Authorization: Bearer $RA_KEY" \
"$BASE/api/export?format=csv&verdict=NO-GO" -o nogo.csv
One row per launch, flattened: identifiers, pad, verdict, score, reasons, and the raw weather sample (wind, gusts, cloud, precipitation probability, CAPE, temperature).
Get pushed an event when a verdict flips, instead of polling.
curl -X POST "$BASE/api/webhooks" \
-H "Authorization: Bearer $RA_KEY" -H "Content-Type: application/json" \
-d '{"url":"https://your.app/hooks/ra","events":["launch.verdict_changed"]}'
| Event | Fires when |
|---|---|
| launch.verdict_changed | GO ⇄ CAUTION ⇄ NO-GO transition |
| launch.scheduled | A launch enters the tracked window |
| launch.net_changed | Launch time (NET) moves |
Every delivery is signed. Recompute the HMAC over ${timestamp}.${rawBody} and compare in constant time:
import crypto from "node:crypto";
app.post("/hooks/ra", express.raw({type:"application/json"}), (req, res) => {
const ts = req.header("X-RA-Timestamp");
const sig = req.header("X-RA-Signature"); // "sha256=<hex>"
const raw = req.body.toString("utf8");
// Reject replays older than 5 minutes.
if (Math.abs(Date.now()/1000 - Number(ts)) > 300) return res.sendStatus(400);
const expected = "sha256=" + crypto
.createHmac("sha256", process.env.RA_WEBHOOK_SECRET)
.update(`${ts}.${raw}`).digest("hex");
const ok = crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
if (!ok) return res.sendStatus(401);
const { event, data } = JSON.parse(raw);
console.log(event, data.launch.mission, data.new_verdict);
res.sendStatus(200); // ack fast; 2xx = delivered
});
Non-2xx responses count as failures. After 10 consecutive failures the endpoint is auto-disabled — re-register it once you've fixed the receiver.
{
"event": "launch.verdict_changed",
"created": "2026-07-19T18:45:02.161Z",
"data": {
"launch": {
"id": "e1079d3a-c0a6-4b42-bc1d-92e48a5a78fc",
"mission": "Starlink Group 17-39",
"vehicle": "Falcon 9 Block 5",
"provider": "SpaceX",
"net": "2026-07-20T14:00:00Z",
"pad": { "site": "Vandenberg SFB, CA, USA", "lat": 34.632, "lon": -120.611 },
"assessment": { "score": 42, "verdict": "NO-GO", "reasons": ["Likely precipitation"] }
},
"previous_verdict": "GO",
"new_verdict": "NO-GO",
"previous_score": 82,
"new_score": 42,
"reasons": ["Likely precipitation"]
}
}
| Tier | Per minute | Per day |
|---|---|---|
| Anonymous | 60 | 5,000 |
| Observer | 120 | 10,000 |
| Mission Control | 300 | 50,000 |
| Developer | 1,200 | 500,000 |
Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. Exceeding a window returns 429 with Retry-After.
| Status | Meaning |
|---|---|
| 401 | Missing, invalid, or revoked credential |
| 403 | Valid credential, but your plan lacks this feature |
| 404 | Unknown launch or webhook id |
| 429 | Rate limited — honour Retry-After |
| 503 | Cache still warming; retry shortly |
The cache rebuilds every 10 minutes from
Launch Library 2 (schedule) and
Open-Meteo (forecast). /api/health reports the
last build. Weather beyond a 16-day horizon returns verdict PENDING.