Track Planetary Transits
Monitor planetary positions over time to detect sign changes, retrogrades, and aspects.
Track Planetary Transits
Transits are the current (or future) positions of planets relative to a natal chart or fixed zodiacal points.
Scan a date range for aspect windows
/v1/transits does the whole job in one call: give it the natal moment and a range, and it returns every window in which a moving body is within orb of an aspect to a natal point, with the enter, exact, and leave instants of each.
curl "https://api.morphemeris.com/v1/transits?\
datetime=1990-06-15T14:30:00Z&lat=40.7&lon=-74\
&start=2026-01-01T00:00:00Z&end=2026-03-01T00:00:00Z" \
-H "Authorization: Bearer morphemeris_live_YOUR_KEY"{
"moving": "saturn",
"aspect": "square",
"target": "sun",
"enter": { "jd": 2461058.9, "datetime": "2026-01-18T09:36:00.000Z" },
"exacts": [{ "jd": 2461085.6, "datetime": "2026-02-14T02:24:00.000Z" }],
"leave": { "jd": 2461112.3, "datetime": "2026-03-12T19:12:00.000Z" }
}One request covers up to a year and costs 5 credits. The rest of this guide covers the older approach of polling positions, which is still the right tool for watching a single body's motion day by day.
Daily positions
Use the /v1/positions endpoint to fetch positions at any moment in time.
Daily transit snapshot
curl "https://api.morphemeris.com/v1/positions?\
datetime=2024-06-20T12:00:00Z\
&bodies=sun,moon,mercury,venus,mars,jupiter,saturn" \
-H "Authorization: Bearer morphemeris_live_YOUR_KEY"Tracking movement over time
To watch a planet's movement (e.g., for retrograde detection or sign ingress), fetch positions at regular intervals:
const dates = [];
const start = new Date("2024-06-01T00:00:00Z");
for (let i = 0; i < 30; i++) {
const d = new Date(start);
d.setDate(d.getDate() + i);
dates.push(d.toISOString());
}
const positions = await Promise.all(
dates.map(async (dt) => {
const res = await fetch(
`https://api.morphemeris.com/v1/positions?datetime=${dt}&bodies=mercury`,
{ headers: { Authorization: `Bearer ${apiKey}` } }
);
const { data } = await res.json();
return { date: dt, ...data[0] };
})
);
// Detect retrograde periods
for (const pos of positions) {
if (pos.retrograde) {
console.log(`Mercury retrograde on ${pos.date}: ${pos.sign} ${pos.sign_degree.toFixed(2)}°`);
}
}
// Detect sign changes
for (let i = 1; i < positions.length; i++) {
if (positions[i].sign !== positions[i - 1].sign) {
console.log(`Mercury entered ${positions[i].sign} on ${positions[i].date}`);
}
}Computing aspects to natal positions by hand
/v1/transits finds these windows for you, with the exact moments. If you are polling positions anyway, compare the current longitude to the natal longitude:
function getAspect(transitLon, natalLon, orb = 1.0) {
const aspects = [
{ name: "conjunction", angle: 0 },
{ name: "sextile", angle: 60 },
{ name: "square", angle: 90 },
{ name: "trine", angle: 120 },
{ name: "opposition", angle: 180 },
];
const diff = Math.abs(transitLon - natalLon) % 360;
const normalized = diff > 180 ? 360 - diff : diff;
for (const aspect of aspects) {
if (Math.abs(normalized - aspect.angle) <= orb) {
return aspect.name;
}
}
return null;
}Tips
- Each position request costs 1 credit. A month of daily transits for 7 planets = 30 credits.
- Use the
speedfield to detect stations (when speed approaches 0) — these indicate retrograde turning points. - The
retrogradeboolean is derived from the speed: negative speed = retrograde.