API docs
Five endpoints. No key, no signup, no SDK, no parameters, no point. All GET, all JSON. /s
GET /api/news
Returns one random English-language news article about Elon Musk, picked from the latest page of NewsAPI results. No parameters, no headers, no API key.
Response fields
| Field | Type | Description |
|---|---|---|
source | string | Publication name |
title | string | Headline |
description | string | null | Summary from the publisher |
url | string | Link to the full article |
urlImage | string | null | Lead image URL |
publishDate | string | ISO 8601 timestamp |
curl https://elonmu.sh/api/news
{
"source": "Business Insider",
"title": "Wizards, horses, flip phones and AI: Elon Musk's 10 most colorful quotes from Tesla's investor day",
"description": "Musk joked about charging mishaps, hailed the complexity of the human brain, and voiced his fears about the rise of artificial intelligence.",
"url": "https://markets.businessinsider.com/news/stocks/elon-musk-tesla-investor-day-ai-electric-vehicles-self-driving-2023-3",
"urlImage": "https://i.insider.com/64007dd7ce4a630019955630?width=1200&format=jpeg",
"publishDate": "2023-03-02T11:37:41Z"
}
GET /api/jet/flights
Every private-jet flight this year, with the fuel bill. The flights come from the public posts of @elonjet.net by Jack Sweeney on Bluesky.
Response fields
| Field | Type | Description |
|---|---|---|
year | number | The year the flights are from (UTC) |
updatedAt | string | When the flights were read, ISO 8601 |
attribution | object | label and url of the source |
flights | array | This year's flights, newest first |
flights[]. | string | The post the flight was read from |
flights[]. | string | Tail number, or "Unknown" |
flights[]., .to | object | null | Place name, lat and lon |
flights[]., .landedAt | string | null | ISO 8601 timestamps |
flights[]. | number | null | Minutes in the air |
flights[]. | object | null | gallons, usd and co2Tons burned |
flights[]. | string | "landed" or "airborne" |
flights[]. | string | null | Link to the post |
totals | object | The year's flights, gallons, usd, co2Tons and hours |
flightsis newest first. The example is trimmed to one flight.- A field is
nullwhen the posts don't say: a flight still in the air has notoorlandedAt, andfuelwaits for the fuel reply.
curl https://elonmu.sh/api/jet/flights
{
"year": 2026,
"updatedAt": "2026-10-28T09:12:44.000Z",
"attribution": {
"label": "@elonjet.net by Jack Sweeney",
"url": "https://bsky.app/profile/elonjet.net"
},
"flights": [
{
"id": "3mxq2c7tluk2a",
"tail": "N628TS",
"from": {
"name": "Austin, Texas, United States",
"lat": 30.2672,
"lon": -97.7431
},
"to": {
"name": "San Jose, California, United States",
"lat": 37.3362,
"lon": -121.8906
},
"departedAt": "2026-10-27T15:02:11.000Z",
"landedAt": "2026-10-27T18:21:40.000Z",
"durationMin": 199,
"fuel": {
"gallons": 1032,
"usd": 7276,
"co2Tons": 9.86
},
"status": "landed",
"sourceUrl": "https://bsky.app/profile/elonjet.net/post/3mxq2c7tluk2a"
}
],
"totals": {
"flights": 324,
"gallons": 157525,
"usd": 1109406,
"co2Tons": 1657.6,
"hours": 529.1
}
}
GET /api/hype
Daily views of the English Wikipedia article "Elon Musk" for the last year, with the biggest spikes named. The views come from Wikimedia's pageview API (users only, known bots excluded).
Response fields
| Field | Type | Description |
|---|---|---|
article | string | The article, "Elon Musk" |
from | string | First day returned, YYYY-MM-DD |
to | string | Last day returned, YYYY-MM-DD |
updatedAt | string | When the views were read, ISO 8601 |
attribution | object | label and url of the source |
days | array | date and views for each day, oldest first |
stats | object | total, median and the peak day |
spikes | array | The five busiest days, with timesMedian |
daysis oldest first, in chart order. The example is trimmed to one day and one spike.- The window ends yesterday (UTC). Days Wikimedia has no data for are left out, not zero-filled.
stats.medianis the middle day's views, a whole number. With an even number of days it is the mean of the two middle days, rounded.spikesis highest first, each at least 7 days from any busier one.timesMedianis that day's views over the median, to one decimal.
curl https://elonmu.sh/api/hype
{
"article": "Elon Musk",
"from": "2025-10-27",
"to": "2026-10-26",
"updatedAt": "2026-10-27T09:12:44.000Z",
"attribution": {
"label": "Wikimedia pageviews (en.wikipedia, users only)",
"url": "https://pageviews.wmcloud.org/?project=en.wikipedia.org&pages=Elon_Musk"
},
"days": [
{
"date": "2025-10-27",
"views": 19194
}
],
"stats": {
"total": 8678483,
"median": 20803,
"peak": {
"date": "2026-06-12",
"views": 194434
}
},
"spikes": [
{
"date": "2026-06-12",
"views": 194434,
"timesMedian": 9.3
}
]
}
GET /api/doge
Dogecoin's price now against the minute he went on air hosting Saturday Night Live, 8 May 2021. The live price comes from CoinGecko.
Response fields
| Field | Type | Description |
|---|---|---|
coin | string | "Dogecoin" |
snl | object | at, usd and source of the price at showtime |
now | object | at and usd of the live price |
changePercent | number | (now ÷ SNL − 1) × 100, to one decimal |
thousand | number | What $1,000 of DOGE bought at showtime is worth now, to the cent |
attribution | object | label and url of the live price |
snlnever changes. CoinGecko's free history only goes back 365 days, so the SNL price is a constant: the open of Binance's DOGE/USDT 1-minute candle at 11:30 pm EDT on 8 May 2021.snl.source.urlreturns that candle. USDT is taken as USD.now.atis when CoinGecko last updated its price, not when you asked.- Both figures are computed from the unrounded prices.
curl https://elonmu.sh/api/doge
{
"coin": "Dogecoin",
"snl": {
"at": "2021-05-09T03:30:00.000Z",
"usd": 0.67343,
"source": {
"label": "Binance DOGE/USDT, 1-minute open at showtime",
"url": "https://data-api.binance.vision/api/v3/klines?symbol=DOGEUSDT&interval=1m&startTime=1620531000000&limit=1"
}
},
"now": {
"at": "2026-10-28T04:30:56.000Z",
"usd": 0.079484
},
"changePercent": -88.2,
"thousandDollarsNow": 118.03,
"attribution": {
"label": "Data provided by CoinGecko",
"url": "https://www.coingecko.com/en/coins/dogecoin"
}
}
GET /api/starlink
Every Starlink satellite in orbit, as orbital elements you can propagate, and this year's re-entries. Both come from CelesTrak: the Starlink GP group and the satellite catalogue.
Response fields
| Field | Type | Description |
|---|---|---|
updatedAt | string | When the older of the two catalogues was read, ISO 8601 |
inOrbit | number | null | How many satellites are in orbit |
satellites | array | null | One entry per satellite, by NORAD catalogue number |
satellites[]., .name | number, string | NORAD catalogue number and CelesTrak name |
satellites[]. | string | Time the elements are for, ISO 8601 UTC |
satellites[]. | number | Revolutions per day |
satellites[]. | number | Half the rate of change of mean motion, rev/day², as in a TLE |
satellites[]. | number | Orbit eccentricity |
satellites[]., .raan, .argOfPerigee, .meanAnomaly | number | Angles in degrees |
reentries | object | null | This year's count and the 12 most recent |
reentries. | number | The current UTC year |
reentries. | number | Satellites whose re-entry date falls in that year |
reentries. | array | id, name, launched and reentered (YYYY-MM-DD), newest first |
attribution | array | name and url of each source |
- The example is trimmed to one satellite and one re-entry. The full response is about 2.4 MB, 330 KB gzipped.
- Elements are rounded to keep the response small:
meanMotionto 5 decimals,meanMotionDotto 6,eccentricityto 4 and the angles to 2 decimals. Across the whole catalogue that moves a satellite by up to about 2 km, under a pixel on the globe. - The year is the current UTC year, so
reentries.countstarts again from 0 at midnight UTC on 1 January. - If one of the two CelesTrak catalogues has never loaded, its half is
nulland the response is sent withCache-Control: no-store.
curl https://elonmu.sh/api/starlink
{
"updatedAt": "2026-10-30T04:52:13.127Z",
"inOrbit": 11130,
"satellites": [
{
"id": 44714,
"name": "STARLINK-1008",
"epoch": "2026-10-28T20:33:11.108Z",
"meanMotion": 15.68273,
"meanMotionDot": 0.00034,
"eccentricity": 0.0002,
"inclination": 53.14,
"raan": 138.75,
"argOfPerigee": 162.32,
"meanAnomaly": 197.79
}
],
"reentries": {
"year": 2026,
"count": 459,
"recent": [
{
"id": 45414,
"name": "STARLINK-1309",
"launched": "2020-03-18",
"reentered": "2026-10-29"
}
]
},
"attribution": [
{
"name": "CelesTrak",
"url": "https://celestrak.org"
}
]
}
Errors
Errors come back as JSON with a single error message.
When an upstream (NewsAPI, Bluesky, Wikimedia, CoinGecko,
CelesTrak) is down, the status is still 200: we are fine, it is the
world that failed.
Our own mistakes are a 500.
| Status | When |
|---|---|
200 | An upstream returned an error or never answered |
500 | Something broke on our side |
404 | Any other path. The body is plain text: does not compute... |
Caching
Each endpoint keeps its last good answer. When the upstream fails after one good load, you get that answer instead of an error.
| Endpoint | Refreshed every | When the upstream fails |
|---|---|---|
/api/news | 15 min | Picks from the last good articles, asks again after a minute |
/api/jet/ | 5 min | Serves this year's last good flights |
/api/hype | 4 h | Serves the last good year, asks again after a minute |
/api/doge | 5 min | Serves the last good price, asks again after a minute |
/api/starlink | 6 h orbits, 12 h re-entries | Serves the last good orbits and re-entries, asks again after a minute, or after 2 hours if CelesTrak refused |
{
"error": "There was an error with NewsAPI. Please try again later."
}