Astrocartography
GET/POST /v1/astrocartography — Where on Earth each body is on an angle or a house cusp, as line geometry.
Astrocartography
For a fixed moment, the loci on Earth where a body is on a chart angle — the classic MC / IC / Ascendant / Descendant map — and, the generalization, where a body sits on any house-cusp value in any house system: "Jupiter on the 2nd cusp", "Venus halfway through the 5th". The API returns line geometry; rendering is yours.
GET /v1/astrocartography # flat form: bodies × angles
POST /v1/astrocartography # full form: per-body targets with cusp valuesCredit cost: 5
No location is needed — the answer is global — and no sidereal mode applies, because the geometry is frame-independent.
Parameters
Flat form (GET)
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
datetime | string | One of datetime or jd | — | ISO 8601 UTC datetime |
jd | number | One of datetime or jd | — | Julian Day in UT1 |
bodies | string | No | "planets" | Comma-separated body names |
angles | string | No | all four | Comma-separated subset of ascendant, descendant, midheaven, imum_coeli (or asc, dsc, mc, ic) |
system | string | No | "placidus" | House system for cusp lines; angle lines are identical in every system |
mode | string | No | "zodiacal" | "zodiacal" or "mundane" (see below) |
latitude_step | number | No | 1 | Sampling step in degrees of latitude (0.5–10) |
max_latitude | number | No | 89 | Highest |latitude| sampled (1–89) |
Full form (POST)
The same parameters, plus targets in place of bodies/angles:
{
"datetime": "2024-01-25T18:00:00Z",
"system": "placidus",
"targets": [
{ "body": "jupiter", "angles": ["midheaven", "ascendant"], "cusps": [2, 5.5] },
{ "body": "venus", "cusps": [7] }
]
}| Field | Description |
|---|---|
body | Body name |
angles[] | Angle lines for this body (default none) |
cusps[] | House-position values in [1, 13): 2 is the 2nd cusp, 5.5 is halfway through the 5th (default none) |
targets can also be passed in a GET request as URL-encoded JSON text.
Limits
| Limit | Value |
|---|---|
| Targets per request | 20 |
| Cusp values per target | 12 |
| Lines per request (angles + cusps over all targets) | 80 |
latitude_step | 0.5–10 |
Each cusp line is a per-latitude root-find, so the line count — not the target count — is what the limit protects. Every house system works.
Response
{
"data": {
"sky": { "gast": 130.42, "obliquity": 23.4361, "sun_declination": -18.95 },
"lines": [
{
"body": "jupiter",
"line": { "kind": "angle", "value": "midheaven" },
"mode": "zodiacal",
"house_system": "placidus",
"segments": [
{
"points": [
{ "latitude": -89.0, "longitude": -87.31 },
{ "latitude": -88.0, "longitude": -87.31 }
],
"end": "latitude_limit"
}
]
},
{
"body": "jupiter",
"line": { "kind": "cusp", "value": 2 },
"mode": "zodiacal",
"house_system": "placidus",
"segments": [
{ "points": [ { "latitude": -66.0, "longitude": 12.7 } ], "end": "house_system_undefined" }
]
}
]
},
"meta": { "credits_used": 5, "...": "..." }
}| Field | Description |
|---|---|
sky | Greenwich apparent sidereal time, true obliquity, and the Sun's declination for the moment |
lines[] | One per (body, angle-or-cusp), in target order |
line | { "kind": "angle", "value": "midheaven" } or { "kind": "cusp", "value": 5.5 } |
segments[].points[] | { latitude, longitude }, south to north; longitude in (−180, 180] |
segments[].end | Why the segment stopped — see below |
Segment terminations
A renderer has to read end; it is the difference between "the line stops here" and "we ran out of data".
end | Meaning |
|---|---|
latitude_limit | The line reached ±max_latitude and continues, unsampled |
circumpolar | Beyond this latitude the body never rises or sets — a genuine end of an Ascendant/Descendant line |
house_system_undefined | The house system has no cusps here (Placidus and Koch inside the polar circles) |
no_solution | The cusp never reaches the body on this row of latitude |
antimeridian | The line crossed ±180° and continues in the next segment |
discontinuity | A longitude jump of more than 90° between rows; the line continues in the next segment |
No segment ever contains a jump wider than 180°, so each can be drawn as a plain polyline.
Zodiacal vs. mundane
Zodiacal (the default) flattens each body onto the ecliptic before finding where it is angular, so the lines match what a relocated chart shows. Mundane keeps the body's true ecliptic latitude, so the lines mark where the body is physically on the horizon, meridian, or cusp surface — and it is the convention Astrodienst's maps use. The engine's mundane output is validated against a published Astrodienst map ("Method: true latitude"): MC meridians agree within 0.2° and Moon/Pluto rising and setting lines within 0.5°, while a zodiacal control confirmed the flattened convention does not match (Pluto's MC meridian lands 6.8° away). Treat future divergence from Astrodienst as a regression. The two modes differ noticeably only for bodies well off the ecliptic: the Moon, Pluto, the asteroids.
One caveat when comparing node lines against Astrodienst: their maps draw the mean node — true-node meridians differ by more than a degree — so use mean_node (already part of the default planets group) to match their maps.
Examples
The classic map for a birth
curl "https://api.morphemeris.com/v1/astrocartography?datetime=1990-06-15T18:30:00Z" \
-H "Authorization: Bearer morphemeris_live_YOUR_KEY"const res = await fetch(
"https://api.morphemeris.com/v1/astrocartography?datetime=1990-06-15T18:30:00Z",
{ headers: { Authorization: "Bearer morphemeris_live_YOUR_KEY" } },
);
const { data } = await res.json();
for (const line of data.lines) {
const label = line.line.kind === "angle" ? line.line.value : `cusp ${line.line.value}`;
for (const seg of line.segments) {
drawPolyline(seg.points, { body: line.body, label, closed: seg.end !== "latitude_limit" });
}
}Jupiter on the 2nd cusp, Venus on the 7th, in Koch
curl -X POST "https://api.morphemeris.com/v1/astrocartography" \
-H "Authorization: Bearer morphemeris_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"datetime": "1990-06-15T18:30:00Z",
"system": "koch",
"targets": [
{ "body": "jupiter", "cusps": [2] },
{ "body": "venus", "cusps": [7] }
]
}'Errors
| Code | Cause |
|---|---|
invalid_parameter | A limit exceeded, a cusp value outside [1, 13), an unknown angles/mode value, sidereal/topocentric/heliocentric given, a house system without cusp-line support, or malformed targets |
body_not_found | An unknown body in bodies or targets |