Base URL
Every endpoint lives under a single host. All requests are HTTPS, and all responses are JSON.
https://caldera-api-4owgwzlpaa-ey.a.run.appAuthentication
Pass your key in an X-API-Key header on every request. Requests without a valid key are rejected with 401.
X-API-Key: YOUR_API_KEYQuickstart
A complete natal chart in one request.
curl "https://caldera-api-4owgwzlpaa-ey.a.run.app/v1/natal\
?date=1990-05-15&time=14:30&timezone=Europe/Istanbul\
&lat=41.0082&lon=28.9784&house_system=whole_sign" \
-H "X-API-Key: YOUR_API_KEY"const params = new URLSearchParams({
date: '1990-05-15',
time: '14:30',
timezone: 'Europe/Istanbul',
lat: '41.0082',
lon: '28.9784',
house_system: 'whole_sign'
});
const res = await fetch(
`https://caldera-api-4owgwzlpaa-ey.a.run.app/v1/natal?${params}`,
{ headers: { 'X-API-Key': process.env.CALDERA_KEY } }
);
const chart = await res.json();
console.log(chart.sun_sign, chart.moon_sign, chart.rising_sign);import os, requests
r = requests.get(
"https://caldera-api-4owgwzlpaa-ey.a.run.app/v1/natal",
params={
"date": "1990-05-15",
"time": "14:30",
"timezone": "Europe/Istanbul",
"lat": 41.0082,
"lon": 28.9784,
"house_system": "whole_sign",
},
headers={"X-API-Key": os.environ["CALDERA_KEY"]},
timeout=30,
)
r.raise_for_status()
chart = r.json()
print(chart["sun_sign"], chart["moon_sign"], chart["rising_sign"])Natal chart
/v1/natalThe full birth chart: planets, points, houses, aspects and the deeper layers — dignities, declinations, antiscia, midpoints and chart patterns.
Parameters
| Name | Type | Description |
|---|---|---|
| date | string required | Birth date as YYYY-MM-DD. |
| time | string optional | Local birth time as HH:MM. Defaults to 12:00; the response flags this with has_time. |
| timezone | string required | IANA timezone of the birth place, e.g. Europe/Istanbul. Historical offsets and DST are resolved for you. |
| lat | number required | Latitude in decimal degrees, −90 to 90. |
| lon | number required | Longitude in decimal degrees, −180 to 180. |
| house_system | string optional | whole_sign (default), equal or placidus. |
Response
{
"sun_sign": "Taurus",
"moon_sign": "Capricorn",
"rising_sign": "Virgo",
"has_time": true,
"birth_datetime": "1990-05-15T11:30:00+00:00",
"planets": [ /* 10 planet objects */ ],
"points": [ /* Nodes, Lilith, Ceres, Pallas, Juno, Vesta, Chiron */ ],
"chart_points": [ /* Part of Fortune, Vertex */ ],
"houses": { "system", "ascendant", "midheaven", "cusps" },
"aspects": [ /* major aspects with orb */ ],
"extra_aspects": [ /* minor aspects */ ],
// the layers most APIs leave out
"declination_aspects": [ /* parallels, contra-parallels */ ],
"out_of_bounds": [ "Uranus" ],
"antiscia_contacts": [ /* mirror-point contacts */ ],
"midpoints": [ /* full midpoint tree */ ],
"midpoint_activations": [ ... ],
"patterns": [ { "type": "t_square", "bodies": [...], "apex": "Venus" } ],
"royal_stars": [ ... ],
"moon_phase": "Waning Gibbous",
"moon_illumination": 78.4
}Transits
/v1/transitsCurrent or dated transits against a natal chart, plus a detailed live Moon object. This is the endpoint behind a “what's happening today” feed or a daily push notification.
Parameters
| Name | Type | Description |
|---|---|---|
| birth_date | string required | Natal date, YYYY-MM-DD. |
| birth_time | string optional | Natal local time, HH:MM. |
| timezone | string required | IANA timezone of the birth place. |
| lat | number required | Natal latitude. |
| lon | number required | Natal longitude. |
| transit_date | string optional | Date to compute transits for. Defaults to now. |
Response
Alongside transiting_planets, natal_planets and every transit-to-natal aspects entry, the moon object carries the electional detail most APIs charge extra for:
"moon": {
"phase_name": "Waning Crescent",
"illumination": 22.41,
"lunar_mansion": 9,
"lunar_mansion_name": "Al-Tarf",
"is_void_of_course": false,
"void_of_course_until": null,
"moon_sign_ingress": "2026-09-07T16:49:24Z",
"next_major_aspect": {
"planet": "Mercury",
"aspect": "Sextile",
"hours_until": 10.76,
"datetime": "2026-09-07T07:01:09Z"
},
"is_solar_eclipse": false,
"is_lunar_eclipse": false
}is_void_of_course, void_of_course_until and moon_sign_ingress mean you can build electional features — “don't start anything now” banners, timing widgets — without computing lunar aspects yourself.Synastry
/v1/synastryCompatibility between two charts. Returns both complete charts plus every inter-chart aspect — the backbone of a matching, dating or relationship feature.
Parameters
Each person takes the same five fields, prefixed a_ and b_.
| Name | Type | Description |
|---|---|---|
| a_date, b_date | string required | Birth dates, YYYY-MM-DD. |
| a_time, b_time | string optional | Local birth times, HH:MM. |
| a_timezone, b_timezone | string required | IANA timezones. |
| a_lat, b_lat | number required | Latitudes. |
| a_lon, b_lon | number required | Longitudes. |
Response
{
"person_a": { /* full natal chart */ },
"person_b": { /* full natal chart */ },
"aspect_count": 175,
"aspects": [
{
"person_a": "Venus",
"person_b": "Mars",
"type": "Trine",
"angle": 120,
"orb": 1.42,
"nature": "harmonious",
"is_exact": false,
"is_tight": true,
"is_major": true
}
]
}Response objects
Planet
{
"planet": "Sun",
"symbol": "☉",
"sign": "Taurus",
"sign_glyph": "♉",
"degree": 24.376,
"degree_string": "24°22′",
"longitude": 54.376,
"house": 9,
"is_retrograde": false,
"speed": 0.97,
"dignity": { "name": "Peregrine", "strength": 0 },
"declination": 18.8658,
"out_of_bounds": false,
"antiscia": { "longitude", "sign", "degree_string" },
"contra_antiscia": { "longitude", "sign", "degree_string" }
}Aspect
{
"planet1": "Moon",
"planet2": "Neptune",
"type": "Square",
"angle": 90,
"orb": 2.14,
"nature": "challenging",
"is_applying": true,
"is_exact": false,
"is_tight": false,
"is_major": true
}Errors
Errors return a JSON body and a conventional status code.
| Status | Meaning | What to do |
|---|---|---|
| 401 | Missing or invalid API key | Check the X-API-Key header. |
| 422 | Validation error | A required parameter is missing or malformed. The body names the field. |
| 404 | Unknown endpoint | Check the path — only /v1/natal, /v1/transits and /v1/synastry exist. |
| 5xx | Server error | Retry with backoff; if it persists, email us. |
{
"detail": [
{
"type": "missing",
"loc": ["query", "birth_date"],
"msg": "Field required"
}
]
}Limits & caching
Rate limits are set per plan and exist to keep response times even, not to push you upward. If you need a large one-off backfill, tell us and we will lift the limit for that window.
Cache your natal charts
A natal chart is deterministic: the same birth data always returns the same chart. Store it against your user record on first calculation and you will rarely need to call /v1/natal again for that person. Transits are the opposite — they change constantly, so cache those only for minutes, not days.
- Natal — cache indefinitely, keyed on date, time, lat, lon, timezone and house system.
- Transits — cache briefly, or per calendar day if you only show daily granularity.
- Synastry — deterministic like natal; cache on the pair.
Ready for a key?
Free tier is 1,000 requests a month, no card. Tell us what you're building and we'll send one.