Composite and Synastry Charts: The Difference, and When to Use Each
Synastry compares how two people affect each other; a composite chart describes the relationship as its own entity. Here is how to build with both.
- Synastry compares two natal charts through directional house overlays and cross-chart aspects, while composite creates one midpoint chart for the relationship itself.
- Both endpoints accept two complete birth-data sets and return each individual chart, but only synastry adds overlays and only composite adds the blended chart.
- Use synastry for a two-sided match detail view, composite for a shareable relationship profile, and filter the raw aspect list before presenting it.
The core difference
Synastry lays one person's chart over the other's. It answers directional questions: your Venus falls in their 5th house, their Mars sits right on your Ascendant. Because it compares two charts, what you see depends on which side you view it from.
A composite chart collapses both people into one. Each composite planet sits at the midpoint of the two natal positions, which gives you a chart that belongs to neither person. It describes the relationship as a third thing with its own Sun, Moon, and aspects.
The composite math is simple enough to check yourself. Here are two planets from a live call, using two sample birth charts:
| Person A | Person B | Composite | |
|---|---|---|---|
| Sun | 84.37° (Gemini) | 239.99° (Scorpio) | 162.18° (Virgo) |
| Moon | 74.75° (Gemini) | 106.29° (Cancer) | 90.52° (Cancer) |
The composite Sun is (84.3744 + 239.9853) / 2 = 162.17985. Nothing hidden is happening. The value of the endpoint is that it does this for every planet, builds the houses and angles, and calculates the aspects within the new chart.
What each endpoint returns
| synastry_horoscope | composite_horoscope | |
|---|---|---|
| Input | Two birth data sets (p_*, s_*) | Same |
| Each person's natal planets | first, second | first, second |
| Relationship data | synastry.house_1, synastry.house_2, synastry.aspects | composite: planets, houses, angles, aspects |
| Aspect shape | first, second, type, orb (person A's body to person B's body) | aspecting_planet, aspected_planet, type, orb, diff (within one chart) |
| Typical aspect count | Well over 100 | A few dozen |
| Directional | Yes | No, one chart for the pair |
| Optional | language | language |
All calls are POST requests to
https://json.astrologyapi.com/v1/ with HTTP Basic auth. Each call
needs both people's day, month,
year, hour, min, lat,
lon, and tzone.
Build the request javascript
const auth = Buffer.from(
process.env.ASTRO_USER_ID + ':' + process.env.ASTRO_API_KEY,
).toString('base64')
const FIELDS = ['day', 'month', 'year', 'hour', 'min', 'lat', 'lon', 'tzone']
function pairBody(primary, secondary) {
const body = {}
for (const f of FIELDS) {
body['p_' + f] = primary[f]
body['s_' + f] = secondary[f]
}
return body
}
async function relationshipChart(endpoint, primary, secondary) {
const res = await fetch('https://json.astrologyapi.com/v1/' + endpoint, {
method: 'POST',
headers: {
Authorization: 'Basic ' + auth,
'Content-Type': 'application/json',
},
body: JSON.stringify(pairBody(primary, secondary)),
})
if (!res.ok) {
throw new Error(endpoint + ' returned ' + res.status)
}
return res.json()
}
// relationshipChart('synastry_horoscope', a, b)
// relationshipChart('composite_horoscope', a, b)
Synastry: two charts, one comparison
The synastry response has two parts worth building on.
House overlays. synastry.house_1 places the
primary person's planets into the secondary person's houses, and
synastry.house_2 does the reverse. Each entry is a planet name
and the synastry_house it lands in:
"house_1": [
{ "name": "Sun", "synastry_house": 1 },
{ "name": "Moon", "synastry_house": 1 },
{ "name": "Venus", "synastry_house": 1 },
{ "name": "Mars", "synastry_house": 12 }
]
This is the natural source for sentences like "Your Venus lands in their 1st house," which is why synastry works well for a two-sided screen where each user sees their own half of the story.
Cross-chart aspects. Every aspect pairs a body from person A
(first) with a body from person B (second):
{ "first": "Sun", "second": "Mars", "type": "Sextile", "orb": 0.6 }
Read this before you render the aspect list
The aspect list is exhaustive, not curated. It includes minor aspects (quincunx, semi-sextile, semi-square, quintile) and orbs running up to about 10°, so a typical response contains well over a hundred entries. Rendering all of them reads as noise. Filter to major aspects with tight orbs between the personal planets and angles, then rank by orb. The tighter the orb, the stronger the contact.
Filter to the highlights
const MAJOR = new Set(['Conjunction', 'Opposition', 'Trine', 'Square', 'Sextile'])
const PERSONAL = new Set(['Sun', 'Moon', 'Mercury', 'Venus', 'Mars', 'Ascendant'])
function topSynastryAspects(synastry, { maxOrb = 3, limit = 5 } = {}) {
return synastry.aspects
.filter((a) => MAJOR.has(a.type) && a.orb <= maxOrb)
.filter((a) => PERSONAL.has(a.first) && PERSONAL.has(a.second))
.sort((x, y) => x.orb - y.orb)
.slice(0, limit)
}
Run against the same sample pair, this reduces the full list to five:
[
{ "first": "Ascendant", "second": "Mars", "type": "Conjunction", "orb": 0.32 },
{ "first": "Sun", "second": "Mars", "type": "Sextile", "orb": 0.6 },
{ "first": "Moon", "second": "Ascendant", "type": "Conjunction", "orb": 0.61 },
{ "first": "Mercury", "second": "Sun", "type": "Opposition", "orb": 1.56 },
{ "first": "Mars", "second": "Sun", "type": "Opposition", "orb": 1.87 }
]
That is a "why you two clicked (and clashed)" card instead of a data
dump. Tune maxOrb and the planet set to your audience. A dating
app might weight Venus and Mars contacts, while a friendship feature might
weight Mercury and Moon.
Composite: one chart for the relationship
The composite_horoscope response contains first and
second (the natal planets, identical to synastry) plus a
composite object with the blended planets, houses, angles, and
the aspects within the new chart.
{
"composite": {
"planets": [
{ "name": "Sun", "full_degree": 162.17985, "norm_degree": 12.1798, "sign": "Virgo" },
{ "name": "Moon", "full_degree": 90.51755, "norm_degree": 0.5175, "sign": "Cancer" }
]
}
}
The most useful output is the simplest: the relationship's Sun sign, Moon sign, and Ascendant as a single shareable card. "Your relationship is a Virgo Sun" is a framing a couple can screenshot, and it needs no explanation of aspects or overlays.
Two things to keep in mind. First, a composite chart is static. It describes the relationship's character, not its current weather, so for "how are we doing this week" you will want to pair it with transit data. Second, it is symmetric where synastry is not. The midpoint of two planets is the same whichever order you pass them, so there is no "your side" and "their side" to design around.
Which one to use
| Feature | Use | Why |
|---|---|---|
| Match detail screen in a dating app | Synastry | Each person sees their own side of the overlay |
| "Why we matched" highlights | Synastry, filtered | Tight-orb contacts make concrete, readable reasons |
| Couples, anniversary, or wedding report | Composite | One chart for the pair, easy to share |
| Friend, co-founder, or business partner profile | Composite | The relationship as an entity, not a ranking |
| Browse feed before anyone has matched | Neither | Too heavy per candidate; use a sign-level check like zodiac_compatibility |
| Full relationship report | Both | Composite as the summary, synastry as the deep dive |
If you ship both, you do not need to call both for natal data. Each response
already includes first and second, so use one of
them for the individual chart views and the other only for what it uniquely
adds.
Caching and call volume
Both endpoints are pure functions of the two sets of birth details, so the same pair always returns the same result. Cache responses indefinitely, with two details worth getting right:
Include the birth details in your cache key, not just the user IDs. If someone corrects their birth time, the old entry should stop matching.
Pick a canonical order for the pair. Composite midpoints do
not care which person is primary, but the response's
first and second blocks do, and for synastry
swapping the order flips the overlay direction. Decide on an order (for
example, by user ID) and map back to "you" and "them" in
your UI.
Compute on demand, not in bulk. In a dating or matchmaking app, call synastry when someone opens a match, not for every candidate in a feed.
Read this before you ship a relationship feature
A pair chart means handling someone else's birth data, and that person may not have signed up. If the second person is a match, a friend, or a partner, collect their details with their knowledge, store pair results against both user IDs, and delete them when a match is removed or an account is closed. Treat a stored birth time and place as personal data, because it is.
Frequently asked questions
What is the difference between a synastry chart and a composite chart?
A synastry chart compares two natal charts side by side, showing how each person's planets fall into the other's houses and which planets aspect each other. A composite chart merges the two into a single chart by taking the midpoint of each planet pair, so the relationship has its own chart.
Which one should I use for a dating app?
Start with synastry for the match detail screen, since it gives each person their own view and concrete reasons for the match. Add composite if you want a single shareable "relationship profile" card. Before a match exists, a lightweight sign-level check is a better fit than either.
Do either of these return a compatibility score?
No. Both return chart data: planets, houses, and aspects. Turning that into a score or a label is your decision, which is why filtering and ranking matter more here than in endpoints that return a ready-made percentage.
Do they need birth times for both people?
For the best results, yes. House overlays and any aspect involving the Ascendant, Descendant, or Midheaven depend on an accurate birth time. Without one, treat those parts of the output as unreliable and lean on planet-to-planet aspects instead.
Are these Western or Vedic calculations?
Western. Both use tropical zodiac positions and include bodies like Chiron,
the outer planets, and the Part of Fortune, and neither takes an ayanamsha
parameter. For Vedic compatibility, match_ashtakoot_points and
match_making_report are the relevant endpoints.