Profections
GET /v1/profections — Annual and monthly profections: the lord of the year and month, at one instant or over a range.
Profections
Annual and monthly profections of a natal chart, the simplest of the Hellenistic time-lord techniques. Each year of life advances the count one sign from the Ascendant: at age n the profected sign is n signs past the rising sign, that count is the profected house, and the sign's domicile ruler is the lord of the year. Each month of that year advances one sign further.
Ask for one instant to get the year and month in force, or for a range to get every year and month overlapping it as flat period records, ready for a timeline.
GET /v1/profections
POST /v1/profectionsCredit cost: 1, or 2 with solar=true
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
datetime | string | One of datetime or jd | — | Natal moment, ISO 8601 UTC |
jd | number | One of datetime or jd | — | Natal moment as a Julian Day (UT1) |
lat, lon | number | Yes | — | Natal location, for the Ascendant |
at | string | One of at or start+end | — | One instant, ISO 8601 UTC: returns the year and month in force then (or at_jd) |
start, end | string | One of at or start+end | — | A range, ISO 8601 UTC: returns every period overlapping it. end after start, at most 120 years later (or start_jd, end_jd) |
from | string | No | ascendant | The point the count starts from: ascendant, midheaven, a body in bodies (moon), or a Hermetic lot (part_of_fortune, part_of_spirit, …). Only its sign matters |
months | boolean | No | true | Include the twelve monthly sub-profections of each year |
year_days | number | No | 365.2422 | Length of a profection year in days, for the mean-year boundaries. The default is the mean tropical year; 365.25 is the Julian year |
solar | boolean | No | false | Anchor each year to the Sun's real return to its natal degree and each month to its arrival 30° further on, searched in the chart's own zodiac. Costs 2 credits |
bodies | string | No | planets | Bodies in the natal chart, so one can be named in from |
sidereal | string | No | — | Ayanamsha for the sidereal zodiac. The signs are then sidereal, and with solar=true the year turns at the sidereal return |
Whole sign, always. Profections are defined on signs: an Ascendant at 29°59′ Virgo profects exactly as one at 0° Virgo, and the house is the whole-sign count from the starting sign whatever house system the natal chart is cast in. from only picks a starting sign.
Where a year begins is the one thing the count cannot decide, so there are two rules. By default (boundaries: "mean") a year is year_days days from birth and each month an equal twelfth. With solar=true (boundaries: "solar") each year begins at the solar return and each month when the Sun reaches 30°, 60°, … past its natal degree. The two agree on every house and lord; the years turn within a day of each other, and the months drift up to about three days apart by mid-year because the Sun moves faster through Capricorn than Cancer.
Nothing is profected before birth. A range that begins earlier is cut to the birth instant, which is a true boundary and is not flagged. An at before birth returns 400.
Response
{
"data": {
"from": "ascendant",
"from_sign": "libra",
"boundaries": "mean",
"year_days": 365.2422,
"months": true,
"start": { "jd": 2461041.5, "datetime": "2026-01-01T00:00:00.000Z" },
"end": { "jd": 2461406.5, "datetime": "2027-01-01T00:00:00.000Z" },
"periods": [
{
"level": 1,
"age": 35,
"house": 12,
"sign": "virgo",
"lord": "mercury",
"start": { "jd": 2461041.5, "datetime": "2026-01-01T00:00:00.000Z" },
"end": { "jd": 2461207.08, "datetime": "2026-06-15T13:55:12.000Z" },
"clamped_start": true,
"clamped_end": false
},
{
"level": 2,
"age": 35,
"month": 7,
"house": 6,
"sign": "pisces",
"lord": "jupiter",
"start": { "jd": 2461024.44, "datetime": "2025-12-14T22:31:00.000Z" },
"end": { "jd": 2461054.88, "datetime": "2026-01-14T09:07:00.000Z" },
"clamped_start": true,
"clamped_end": false
}
]
},
"meta": { "..." }
}| Field | Type | Description |
|---|---|---|
from | string | The starting point, as requested |
from_sign | string | Its sign in the natal chart: the first house of the count |
boundaries | string | mean or solar |
year_days | number | The year length used. Absent for solar |
months | boolean | Whether month records are included |
at | instant | The instant asked about, as { jd, datetime }. Present for an at query |
start, end | instant | The range asked about. Present for a range query |
periods[].level | number | 1 for a year, 2 for a month |
periods[].age | number | Completed years at the start of the year the record belongs to. Age 0 runs from birth to the first birthday |
periods[].month | number | Month of the profected year, 1–12. Absent on a year record |
periods[].house | number | The profected house, 1–12, counted from the starting sign |
periods[].sign | string | The profected sign |
periods[].lord | string | The lord of the year or month: the sign's classical domicile ruler |
periods[].start, end | instant | When the period begins and ends |
periods[].clamped_start | boolean | start is the range's start, not the period's own |
periods[].clamped_end | boolean | end is the range's end, not the period's own |
Records are flat, ordered by start then level, so a renderer draws one track per level and recovers the nesting from time containment. An at query returns the full year and month containing the instant, never clamped.
Examples
The lord of the year right now
curl "https://api.morphemeris.com/v1/profections?datetime=1990-06-15T14:30:00Z&lat=40.7&lon=-74&at=2026-03-01T00:00:00Z" \
-H "Authorization: Bearer morphemeris_live_YOUR_KEY"const res = await fetch(
"https://api.morphemeris.com/v1/profections?datetime=1990-06-15T14:30:00Z&lat=40.7&lon=-74&at=2026-03-01T00:00:00Z",
{ headers: { Authorization: "Bearer morphemeris_live_YOUR_KEY" } }
);
const { data } = await res.json();
const year = data.periods.find((p) => p.level === 1);
console.log(`Age ${year.age}: ${year.house}th house, ${year.sign}, lord ${year.lord}`);import requests
res = requests.get(
"https://api.morphemeris.com/v1/profections",
params={
"datetime": "1990-06-15T14:30:00Z", "lat": 40.7, "lon": -74,
"at": "2026-03-01T00:00:00Z",
},
headers={"Authorization": "Bearer morphemeris_live_YOUR_KEY"},
)
year = next(p for p in res.json()["data"]["periods"] if p["level"] == 1)A decade of years and months, anchored to the solar returns
curl "https://api.morphemeris.com/v1/profections?datetime=1990-06-15T14:30:00Z&lat=40.7&lon=-74&solar=true&start=2020-01-01T00:00:00Z&end=2030-01-01T00:00:00Z" \
-H "Authorization: Bearer morphemeris_live_YOUR_KEY"Profecting from the Lot of Fortune, years only
curl "https://api.morphemeris.com/v1/profections?datetime=1990-06-15T14:30:00Z&lat=40.7&lon=-74&from=part_of_fortune&months=false&start=2026-01-01T00:00:00Z&end=2036-01-01T00:00:00Z" \
-H "Authorization: Bearer morphemeris_live_YOUR_KEY"See Time Lords for the technique and the time-lords guide for building a timeline from the records. Planetary Returns gives the full chart at the solar return a profected year begins on.