Differences from other providers
If you are migrating from another astrology API and the numbers don’t match, the cause is rarely the math — modern providers share the same Swiss Ephemeris lineage. It is almost always a default or convention that differs. This page is the lookup that turns a “your API is wrong” ticket into a one-line setting change. Every divergence below is inspectable in meta.settings_resolved — and, for composites and returns, in data.method — echoed on every response.
Where defaults diverge
Section titled “Where defaults diverge”| Setting | Astral default | Common elsewhere | Size of the difference |
|---|---|---|---|
| Lunar node | node_type: "true" |
Mean node | Up to about 1°45′ |
| Zodiac | tropical on all /western/* |
Sidereal (usually Lahiri) on Vedic-focused APIs | About 24° on every longitude |
| Ayanamsa | None — explicit and required with sidereal | Implied Lahiri | Arcminutes to over a degree, by ayanamsa pair |
| Retrograde | Sign of speed at the queried instant |
Whole-day differencing | Only within hours of a station |
| House system | placidus |
Placidus or Whole Sign; polar behavior varies | Reassigns house placements |
| Cusps at the poles | 422 when the system is undefined there |
Silent substitution or garbage cusps | Documented error instead of a chart |
| Aspect orbs (natal) | Ptolemaic set at 8/8/7/7/5 | Per-provider orb table | Aspects appear or vanish near boundaries |
| Aspect orbs (transits) | Flat 3.0° on /transits, 1.0° on /transits/events |
Natal orb table reused for transits | Transit hits appear or vanish; event windows widen or narrow |
| Part of Fortune | lots_formula: "sect_aware" |
Day formula on every chart | Different point entirely for night births |
| Composite construction | Shorter-arc body midpoints; houses from the midpoint MC at the mean latitude | Midpointed cusps; near-opposition midpoints on the far side | Composite houses and near-opposition bodies land differently |
| Return chart location | return.location, else subject.location (relocation) |
Natal location | Return houses and angles differ; positions unchanged |
Reproducing a specific setting
Section titled “Reproducing a specific setting”Each row above is a one-line override, confirmed in the echo. The settings below are the ones that most often surprise people.
Lunar node: true by default
Section titled “Lunar node: true by default”The default is the true node; set node_type: "mean" to match a mean-node provider. The two oscillate up to about 1°45′ apart, so a node off by that much while every planet matches exactly is this, not an error.
curl -s https://astral-external-api-iksoi6t3nq-ue.a.run.app/v1/western/positions \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "subject": { "datetime": "1990-05-15T14:30:00-04:00" }, "settings": { "node_type": "mean" } }' | jq .meta.settings_resolvednode_type also selects which node appears in the default bodies list, so the body name changes with it (true_node or mean_node).
Zodiac and ayanamsa
Section titled “Zodiac and ayanamsa”All /western/* endpoints default to the tropical zodiac; positions off by about 24° on every longitude mean you are comparing zodiacs. Requesting sidereal requires an explicit ayanamsa — lahiri, raman, or krishnamurti — never implied. A sidereal request with no ayanamsa is a 422 (settings.ayanamsa.required), not a silent Lahiri.
Aspect orbs
Section titled “Aspect orbs”The default is the ptolemaic set — conjunction, opposition, trine, square, sextile — at orbs of 8°, 8°, 7°, 7°, and 5°. Pass per-type overrides in settings.aspects.orbs, and the fully resolved map comes back in meta.settings_resolved.aspects.orbs: copy another provider’s orb table in, confirm the echo, and the diff closes. set: "ptolemaic_plus_minor" adds the minor aspects. The transit endpoints resolve a different default orb (see the table); a per-type override still wins there.
House systems at extreme latitudes
Section titled “House systems at extreme latitudes”The default is Placidus, with 22 systems available via settings.house_system. Above the polar circles, Placidus and Koch are mathematically undefined — rather than substitute silently, we return a 422 (settings.house_system.undefined_at_latitude) carrying the failing latitude and an available_systems array of the nine systems defined at every latitude. Retry with any of them and the same subject succeeds.
curl -s https://astral-external-api-iksoi6t3nq-ue.a.run.app/v1/western/houses \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "subject": { "datetime": "1990-06-21T12:00:00+02:00", "location": { "latitude": 78.22, "longitude": 15.65 } } }' | jq .Part of Fortune: sect-aware by default
Section titled “Part of Fortune: sect-aware by default”The Part of Fortune has two formulas, one for day births and one for night births, selected by sect (whether the Sun was above or below the horizon). The default sect_aware picks the matching formula; lots_formula: "day_formula_always" reproduces a provider that applies the day formula to every chart. The part_of_fortune angle carries both sect (what the chart is) and formula (what computed the value), so a diverging value names its own cause.
curl -s https://astral-external-api-iksoi6t3nq-ue.a.run.app/v1/western/houses \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "subject": { "datetime": "1990-05-15T23:30:00-04:00", "location": { "latitude": 40.7128, "longitude": -74.0060 } }, "settings": { "lots_formula": "day_formula_always" } }' | jq .data.angles.part_of_fortuneHere sect is night and formula is day — the mismatch is visible in the output, not something you reconstruct from documentation.
Composite and return conventions
Section titled “Composite and return conventions”Composite charts and return charts have no single agreed construction, so data.method names the one that ran.
Composite body positions are shorter-arc midpoints of the two natal longitudes; houses derive from the midpoint of the two MCs at the mean of the two latitudes. Other services midpoint the cusps directly, or place a near-opposition midpoint on the far side of the zodiac, so composite charts legitimately differ between vendors. data.method reports exactly which math produced yours (positions and houses):
curl -s https://astral-external-api-iksoi6t3nq-ue.a.run.app/v1/western/composite \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "subject_a": { "datetime": "1990-05-15T14:30:00-04:00", "location": { "latitude": 40.7128, "longitude": -74.0060 } }, "subject_b": { "datetime": "1992-11-22T08:45:00+05:30", "location": { "latitude": 28.6139, "longitude": 77.209 } } }' | jq .data.methodReturn charts are cast for return.location — where the person will be, the traditional convention — falling back to subject.location, then to a positions-only chart. A provider that casts at the natal location shows the same planetary positions but different house cusps and angles. The default is the next return; occurrence: "previous" returns the one before.
Comparing outputs the reliable way
Section titled “Comparing outputs the reliable way”A few practices make cross-provider diffs quick to close out:
- Pin the settings; don’t trust defaults on either side. Send
zodiac,node_type,house_system,aspects.orbs,lots_formula, and (if sidereal)ayanamsaexplicitly, mirroring the other provider’s documented configuration, and confirmmeta.settings_resolvedmatches what you sent. - Compare decimal longitudes, not re-derived degree/minute/second strings. We return both representations precisely so nobody writes conversion code — that is where comparison artifacts breed.
- Expect determinism from us. Identical inputs with the same
meta.calc_versionproduce byte-identical outputs, so a cross-provider diff is stable: measure it once and it stays explained. See Determinism & calc_version.
If a discrepancy survives after you align settings, we want to know — it is either a documentation gap or a bug, and both get fixed. Include the full response meta; it carries calc_version, settings_resolved, subject_resolved, and the request_id.
API spec v0.1.0 · docs 1123b41