Try Astrologer API

Subscribe to support and grow the project.

Synastry API: Build Relationship Compatibility Features #

Relationship compatibility is one of the most popular features in any astrology application. Whether users want to check romantic compatibility, understand family dynamics, or evaluate business partnerships, synastry analysis gives them a structured framework grounded in centuries of astrological tradition. The Astrologer API provides a complete suite of endpoints for building these features, from raw aspect data to numerical compatibility scores and visual chart generation.

This tutorial walks through the three core relationship endpoints, shows how to interpret the response data, and provides working code to build a compatibility feature from scratch.

Understanding the Three Relationship Endpoints #

The Astrologer API offers three distinct approaches to relationship analysis, each suited to different use cases:

Synastry Chart Data (/api/v5/chart-data/synastry) returns the raw astrological data comparing two birth charts. You get each person’s planetary positions, the inter-aspects between their charts, house overlays, and an optional compatibility score. This is the endpoint to use when you need full control over how the data is presented. See the synastry chart data endpoint docs for the full schema.

Compatibility Score (/api/v5/compatibility-score) focuses specifically on generating a numerical score using Ciro Discepolo’s method. It evaluates inter-aspects, checks for “Destiny Signs” connections, and returns a detailed breakdown of how the score was calculated. This is ideal for apps that need a simple, user-facing compatibility percentage or rating. See the compatibility score endpoint docs.

Composite Chart (/api/v5/chart/composite) takes a different approach entirely. Instead of comparing two charts, it calculates the mathematical midpoints of both charts’ planetary positions to create a single chart representing the relationship itself as an entity. The composite chart endpoint docs cover all available rendering options.

Getting Started: Your First Synastry Request #

Every relationship analysis starts with birth data for two people. You need each person’s date, time, and place of birth. Before you begin, get your API key on RapidAPI.

Here is how to fetch synastry chart data for two people:

Python #

import requests

url = "https://astrologer.p.rapidapi.com/api/v5/chart-data/synastry"

headers = {
    "Content-Type": "application/json",
    "X-RapidAPI-Key": "YOUR_API_KEY",
    "X-RapidAPI-Host": "astrologer.p.rapidapi.com"
}

payload = {
    "first_subject": {
        "name": "Alice",
        "year": 1990,
        "month": 3,
        "day": 15,
        "hour": 14,
        "minute": 30,
        "city": "London",
        "nation": "GB",
        "longitude": -0.1278,
        "latitude": 51.5074,
        "timezone": "Europe/London"
    },
    "second_subject": {
        "name": "Bob",
        "year": 1988,
        "month": 7,
        "day": 22,
        "hour": 9,
        "minute": 15,
        "city": "New York",
        "nation": "US",
        "longitude": -74.006,
        "latitude": 40.7128,
        "timezone": "America/New_York"
    },
    "include_relationship_score": True,
    "include_house_comparison": True
}

response = requests.post(url, json=payload, headers=headers)
data = response.json()

# Access the synastry aspects
for aspect in data["chart_data"]["aspects"]:
    print(f"{aspect['p1_name']} {aspect['aspect']} {aspect['p2_name']} "
          f"(orb: {aspect['orbit']:.1f}°, {aspect['aspect_movement']})")

JavaScript #

const url = "https://astrologer.p.rapidapi.com/api/v5/chart-data/synastry";

const payload = {
  first_subject: {
    name: "Alice",
    year: 1990,
    month: 3,
    day: 15,
    hour: 14,
    minute: 30,
    city: "London",
    nation: "GB",
    longitude: -0.1278,
    latitude: 51.5074,
    timezone: "Europe/London",
  },
  second_subject: {
    name: "Bob",
    year: 1988,
    month: 7,
    day: 22,
    hour: 9,
    minute: 15,
    city: "New York",
    nation: "US",
    longitude: -74.006,
    latitude: 40.7128,
    timezone: "America/New_York",
  },
  include_relationship_score: true,
  include_house_comparison: true,
};

const response = await fetch(url, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-RapidAPI-Key": "YOUR_API_KEY",
    "X-RapidAPI-Host": "astrologer.p.rapidapi.com",
  },
  body: JSON.stringify(payload),
});

const data = await response.json();

// Access the synastry aspects
for (const aspect of data.chart_data.aspects) {
  console.log(
    `${aspect.p1_name} ${aspect.aspect} ${aspect.p2_name} ` +
      `(orb: ${aspect.orbit.toFixed(1)}°, ${aspect.aspect_movement})`
  );
}

The response includes a rich chart_data object with both subjects’ full natal data, an aspects array of inter-aspects, and (when requested) a relationship_score object and house_comparison data.

Interpreting Synastry Aspects #

The aspects array is the heart of synastry analysis. Each aspect object describes a geometric relationship between a planet in one chart and a planet in the other:

{
  "p1_name": "Sun",
  "p2_name": "Moon",
  "aspect": "trine",
  "orbit": 2.3,
  "aspect_degrees": 120,
  "aspect_movement": "Applying"
}

Key aspects to watch for in relationship analysis:

  • Sun-Moon aspects indicate fundamental compatibility of identity and emotions. Conjunctions, trines, and sextiles suggest natural ease; squares and oppositions suggest tension that can be growth-producing.
  • Venus-Mars aspects speak to physical attraction and romantic chemistry. A conjunction or trine between these two planets across charts is a classic indicator of mutual attraction.
  • Moon-Moon aspects reveal emotional compatibility. Harmonious Moon connections mean the two people feel “at home” with each other.
  • Saturn aspects to personal planets indicate longevity and commitment, but also potential restriction. Saturn conjunct Venus across charts often appears in long-lasting relationships.

The orbit field tells you how exact the aspect is. Tighter orbs (lower numbers) indicate stronger influences. An aspect with a 0.5-degree orb is far more significant than one with a 7-degree orb. The aspect_movement field ("Applying" or "Separating") adds another layer: applying aspects are gaining strength, while separating aspects are waning.

Calculating Compatibility Scores #

For a user-facing compatibility feature, the dedicated compatibility score endpoint provides a ready-made numerical rating:

Python #

import requests

url = "https://astrologer.p.rapidapi.com/api/v5/compatibility-score"

headers = {
    "Content-Type": "application/json",
    "X-RapidAPI-Key": "YOUR_API_KEY",
    "X-RapidAPI-Host": "astrologer.p.rapidapi.com"
}

payload = {
    "first_subject": {
        "name": "Alice",
        "year": 1990,
        "month": 3,
        "day": 15,
        "hour": 14,
        "minute": 30,
        "city": "London",
        "nation": "GB",
        "longitude": -0.1278,
        "latitude": 51.5074,
        "timezone": "Europe/London"
    },
    "second_subject": {
        "name": "Bob",
        "year": 1988,
        "month": 7,
        "day": 22,
        "hour": 9,
        "minute": 15,
        "city": "New York",
        "nation": "US",
        "longitude": -74.006,
        "latitude": 40.7128,
        "timezone": "America/New_York"
    }
}

response = requests.post(url, json=payload, headers=headers)
result = response.json()

print(f"Score: {result['score']}")
print(f"Description: {result['score_description']}")
print(f"Destiny Sign: {result['is_destiny_sign']}")

# Show the scoring breakdown
for rule in result["score_breakdown"]:
    print(f"  {rule['description']}: +{rule['points']} pts")

JavaScript #

const url = "https://astrologer.p.rapidapi.com/api/v5/compatibility-score";

const payload = {
  first_subject: {
    name: "Alice",
    year: 1990,
    month: 3,
    day: 15,
    hour: 14,
    minute: 30,
    city: "London",
    nation: "GB",
    longitude: -0.1278,
    latitude: 51.5074,
    timezone: "Europe/London",
  },
  second_subject: {
    name: "Bob",
    year: 1988,
    month: 7,
    day: 22,
    hour: 9,
    minute: 15,
    city: "New York",
    nation: "US",
    longitude: -74.006,
    latitude: 40.7128,
    timezone: "America/New_York",
  },
};

const response = await fetch(url, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-RapidAPI-Key": "YOUR_API_KEY",
    "X-RapidAPI-Host": "astrologer.p.rapidapi.com",
  },
  body: JSON.stringify(payload),
});

const result = await response.json();

console.log(`Score: ${result.score}`);
console.log(`Description: ${result.score_description}`);
console.log(`Destiny Sign: ${result.is_destiny_sign}`);

result.score_breakdown.forEach((rule) => {
  console.log(`  ${rule.description}: +${rule.points} pts`);
});

A typical response looks like this:

{
  "status": "OK",
  "score": 15,
  "score_description": "Very Important",
  "is_destiny_sign": false,
  "aspects": [
    { "p1_name": "Sun", "p2_name": "Moon", "aspect": "trine", "orbit": 2.3 },
    { "p1_name": "Venus", "p2_name": "Mars", "aspect": "conjunction", "orbit": 1.1 }
  ],
  "score_breakdown": [
    {
      "rule": "sun_moon_major",
      "description": "Sun-Moon Trine (standard)",
      "points": 5,
      "details": "Sun-Moon Trine (orbit: 2.3°)"
    },
    {
      "rule": "venus_mars_major",
      "description": "Venus-Mars Conjunction (standard)",
      "points": 10,
      "details": "Venus-Mars Conjunction (orbit: 1.1°)"
    }
  ],
  "chart_data": { ... }
}

The score_description maps to these levels: "Minimal", "Medium", "Important", "Very Important", "Exceptional", "Rare Exceptional". The score_breakdown array makes it transparent exactly which astrological factors contributed to the score, which is valuable for building detailed compatibility reports.

Generating Composite Charts #

While synastry compares two separate charts, a composite chart merges them into one. This is useful for understanding the relationship as its own entity, separate from either individual.

Python #

import requests

url = "https://astrologer.p.rapidapi.com/api/v5/chart/composite"

headers = {
    "Content-Type": "application/json",
    "X-RapidAPI-Key": "YOUR_API_KEY",
    "X-RapidAPI-Host": "astrologer.p.rapidapi.com"
}

payload = {
    "first_subject": {
        "name": "Alice",
        "year": 1990,
        "month": 3,
        "day": 15,
        "hour": 14,
        "minute": 30,
        "city": "London",
        "nation": "GB",
        "longitude": -0.1278,
        "latitude": 51.5074,
        "timezone": "Europe/London"
    },
    "second_subject": {
        "name": "Bob",
        "year": 1988,
        "month": 7,
        "day": 22,
        "hour": 9,
        "minute": 15,
        "city": "New York",
        "nation": "US",
        "longitude": -74.006,
        "latitude": 40.7128,
        "timezone": "America/New_York"
    },
    "theme": "classic",
    "style": "modern"
}

response = requests.post(url, json=payload, headers=headers)
result = response.json()

# Save the SVG chart to a file
with open("composite_chart.svg", "w") as f:
    f.write(result["chart"])

# Access the composite chart data
composite_data = result["chart_data"]
print(f"Composite Sun sign: {composite_data['subject']['sun']['sign']}")
print(f"Composite Moon sign: {composite_data['subject']['moon']['sign']}")

The composite chart uses midpoint calculations. For example, if Alice’s Sun is at 25 degrees Pisces and Bob’s Sun is at 29 degrees Cancer, the composite Sun falls at the midpoint of those two positions. The resulting chart reveals the relationship’s core themes, strengths, and challenges.

Building a Complete Compatibility Feature #

Here is a practical example that combines multiple endpoints to create a comprehensive compatibility report:

Python #

import requests

BASE_URL = "https://astrologer.p.rapidapi.com/api/v5"
HEADERS = {
    "Content-Type": "application/json",
    "X-RapidAPI-Key": "YOUR_API_KEY",
    "X-RapidAPI-Host": "astrologer.p.rapidapi.com"
}

def get_compatibility_report(person_a, person_b):
    """Generate a full compatibility report from two birth data dicts."""

    # Step 1: Get the compatibility score
    score_resp = requests.post(
        f"{BASE_URL}/compatibility-score",
        json={"first_subject": person_a, "second_subject": person_b},
        headers=HEADERS
    ).json()

    # Step 2: Get the synastry chart data with house comparison
    synastry_resp = requests.post(
        f"{BASE_URL}/chart-data/synastry",
        json={
            "first_subject": person_a,
            "second_subject": person_b,
            "include_house_comparison": True,
            "include_relationship_score": True
        },
        headers=HEADERS
    ).json()

    # Step 3: Build the report
    report = {
        "score": score_resp["score"],
        "score_description": score_resp["score_description"],
        "is_destiny_sign": score_resp["is_destiny_sign"],
        "key_aspects": [],
        "element_balance": synastry_resp["chart_data"].get("elements_distribution"),
    }

    # Identify the strongest aspects (tightest orbs)
    aspects = synastry_resp["chart_data"]["aspects"]
    sorted_aspects = sorted(aspects, key=lambda a: a["orbit"])

    for aspect in sorted_aspects[:5]:
        report["key_aspects"].append({
            "connection": f"{aspect['p1_name']}-{aspect['p2_name']}",
            "type": aspect["aspect"],
            "strength": round(aspect["orbit"], 2),
            "movement": aspect["aspect_movement"]
        })

    return report

# Example usage
alice = {
    "name": "Alice", "year": 1990, "month": 3, "day": 15,
    "hour": 14, "minute": 30, "city": "London", "nation": "GB",
    "longitude": -0.1278, "latitude": 51.5074, "timezone": "Europe/London"
}

bob = {
    "name": "Bob", "year": 1988, "month": 7, "day": 22,
    "hour": 9, "minute": 15, "city": "New York", "nation": "US",
    "longitude": -74.006, "latitude": 40.7128, "timezone": "America/New_York"
}

report = get_compatibility_report(alice, bob)
print(f"Compatibility: {report['score']} ({report['score_description']})")
print(f"Destiny Sign Connection: {report['is_destiny_sign']}")
print(f"\nTop 5 Strongest Connections:")
for a in report["key_aspects"]:
    print(f"  {a['connection']} ({a['type']}, orb: {a['strength']}°)")

AI-Powered Compatibility Interpretations #

For apps that want to generate natural-language compatibility readings, the synastry context endpoint returns AI-optimized XML data that you can feed directly to an LLM:

context_resp = requests.post(
    f"{BASE_URL}/context/synastry",
    json={"first_subject": person_a, "second_subject": person_b},
    headers=HEADERS
).json()

# The context field contains structured XML ready for LLM consumption
synastry_context = context_resp["context"]
# Pass this to GPT, Claude, or any LLM to generate a reading

This pairs well with the data-driven approach described in the astrology API for AI guide.

Tips for Production Compatibility Features #

Cache wisely. Compatibility between two people does not change. Once you calculate a score for a pair, store it. The API results are deterministic for the same inputs.

Explain the score. The score_breakdown array gives you everything you need to show users why they received a particular score. Transparency builds trust with your users.

Combine synastry and composite. Synastry tells you how two people interact. The composite chart tells you what the relationship itself is about. Offering both gives users a more complete picture.

Handle missing birth times. If a user does not know their exact birth time, you can still calculate Sun-sign-level compatibility, but house-related data and the Moon position (which moves quickly) will be less accurate. Consider defaulting to noon (12:00) and noting the limitation.

Consider aspect weighting. Not all aspects carry equal weight in compatibility. The API’s scoring method already accounts for this, but if you are building custom interpretations, prioritize Sun-Moon, Venus-Mars, and Ascendant-Descendant connections.

For the full list of endpoints and configuration options, visit the Astrologer API landing page. Get your API key on RapidAPI to start building.

Build With Astrology Data

Natal charts, synastry, transits & AI interpretations — all via REST API.

Try Astrologer API