Build a two-chart compatibility UI that returns a 0 to 100 score with strengths and challenges for each match.
Add a compatibility score to each match card in a dating or matchmaking app. The underlying call is POST /astrology/compatibility-score. For the full synastry report with inter-aspects, swap one URL.
What you can build
Match-card compatibility badges (0 to 100 score)
Pro-tier synastry readings with inter-aspect breakdowns
Matrimonial apps using Vedic Gun Milan (36-point Ashtakoota)
Numerology compatibility side-features ("Life Path 5 meets Life Path 7")
AI matchmaker chatbots that read two users and explain the fit
Two birth dates, times, and cities. You convert each city to lat/lng/timezone in Step 1.
Install
bash
npm install @roxyapi/sdk
bash
pip install roxy-sdk
bash
composer require roxyapi/sdk
bash
dotnet add package RoxyApi.Sdk
Step 1: Location lookup (mandatory)
Every chart call needs latitude, longitude, and timezone (IANA string preferred over decimal). Use GET /location/search to convert a free-text city into those three fields. Cache the result per user.
import os
from roxy_sdk import create_roxy
roxy = create_roxy(os.environ['ROXY_API_KEY'])
loc = roxy.location.search_cities(q='New York')
city = loc['cities'][0]
# city['latitude'], city['longitude'], city['timezone']
php
<?php
use function RoxyAPI\Sdk\createRoxy;
$roxy = createRoxy(getenv('ROXY_API_KEY'));
$loc = $roxy->location->searchCities(q: 'New York');
$city = $loc['cities'][0];
csharp
using RoxyApi;
using Microsoft.Kiota.Abstractions; // for the Date and Time types
var roxy = new RoxyClient(Environment.GetEnvironmentVariable("ROXY_API_KEY")!);
var loc = await roxy.Location.Search.GetAsync(c => c.QueryParameters.Q = "New York");
var city = loc!.Cities![0];
// city.Latitude, city.Longitude, city.Timezone ("America/New_York")
IANA timezone strings ("America/New_York") DST-resolve against the birth date automatically. A January 1990 New York chart gets EST, a July chart gets EDT. Decimal offsets (-5) also work but never DST-correct.
Step 2: Call the compatibility endpoint
calculateCompatibility takes person1 and person2, each with date, time, latitude, longitude, and timezone. It returns an overallScore with compatibility breakdowns.
var data = await roxy.Astrology.CompatibilityScore.PostAsync(new()
{
Person1 = new() { Date = new Date(1990, 7, 15), Time = new Time(14, 30, 0), Latitude = 40.7128, Longitude = -74.006, Timezone = new() { String = "America/New_York" } },
Person2 = new() { Date = new Date(1992, 3, 22), Time = new Time(9, 0, 0), Latitude = 34.0522, Longitude = -118.2437, Timezone = new() { String = "America/Los_Angeles" } },
});
Console.WriteLine(data!.OverallScore); // 78
Console.WriteLine(data.Archetype!.Label); // "Kindred Spirits"
Console.WriteLine(data.Summary);
bash
claude mcp add-json --scope user roxy-astrology '{"type":"http","url":"https://roxyapi.com/mcp/astrology","headers":{"X-API-Key":"YOUR_KEY"}}'
claude mcp add-json --scope user roxy-location '{"type":"http","url":"https://roxyapi.com/mcp/location","headers":{"X-API-Key":"YOUR_KEY"}}'
Then in any MCP client: "calculate compatibility between someone born July 15 1990 2:30pm in New York and someone born March 22 1992 9am in Los Angeles." The agent geocodes both cities and calls the score endpoint. Full setup for Cursor, Claude Desktop, Antigravity, and other clients: MCP guide.
<roxy-compatibility-card> from @roxyapi/ui renders the score, category breakdown, archetype, summary, strengths, challenges, and key aspects. Pass the unwrapped SDK response, the card draws itself. No hand-built markup, no .map over aspects, no manual score ring. Works in vanilla HTML, React, Vue, Svelte, WordPress, anything.
Option A: server fetch, client render
Fetch with the secret key on your server, then send the response (never the key) to the card in the browser. The mode="astrology" attribute tells the card it is rendering a compatibility-score response.
Fetch the response on your server, where the secret key lives. Never put a secret API key in page source: anyone who loads the page can read it. For client-side fetching, use a publishable key with an origin allowlist or proxy through a backend (the Next.js guide shows the backend pattern).
Option B: no-build, server-rendered (inline JSON)
When the page is served from a static host or a cache and there is no client JavaScript to set .data, fetch on your server with the secret key and inline the unwrapped response into the card as a child <script type="application/json" class="roxy-data">. The component reads it on load. No key in the browser, same <roxy-compatibility-card> render. This is Pattern 7 from the UI components page.
Your server template writes the JSON in. The inlined JSON is the exact shape calculateCompatibility returns, the same object you would assign to .data. Inline the unwrapped response, never the SDK envelope. Setting the JavaScript .data property later always wins over the inlined JSON, so one card tag covers both server-rendered and dynamic pages with no branching.
React
In React projects use @roxyapi/ui-react. The card types mode as a literal-union prop, so a typo fails the build. Import the response type from the SDK rather than declaring a local interface.
tsx
'use client';
import { RoxyCompatibilityCard } from '@roxyapi/ui-react';
import type { PostAstrologyCompatibilityScoreResponse } from '@roxyapi/sdk';
export function CompatibilityView({ data }: { data: PostAstrologyCompatibilityScoreResponse }) {
return <RoxyCompatibilityCard data={data} mode="astrology" />;
}
Full synastry dual-wheel
For the inter-aspect view, swap the endpoint to POST /astrology/synastry (calculateSynastry) and the component to <roxy-synastry-chart>. The synastry response carries compatibilityScore, an interAspects[] table, and analysis with strengths and challenges. The chart renders the inter-aspects table plus the score from this response directly.
typescript
// Server side
import { createRoxy } from '@roxyapi/sdk';
const roxy = createRoxy(process.env.ROXY_API_KEY!);
const { data, error } = await roxy.astrology.calculateSynastry({
body: {
person1: { date: '1990-07-15', time: '14:30:00', latitude: 40.71427, longitude: -74.00597, timezone: 'America/New_York' },
person2: { date: '1992-03-22', time: '09:00:00', latitude: 34.05223, longitude: -118.24368, timezone: 'America/Los_Angeles' },
},
});
if (error) throw error;
// Send `data` (not the envelope) to the browser, then: synastryChart.data = data;
To draw the full dual-wheel rather than just the inter-aspects table, merge each person planets array from POST /astrology/natal-chart (generateNatalChart) into data.person1.planets and data.person2.planets before assigning. Without planet positions the synastry response has none, so the chart falls back to the inter-aspects table and score. For a single birth wheel on a profile page, render <roxy-natal-chart> with a generateNatalChart response.
Ready-made template
The full mobile build lives at /templates/astrology-starter-app: React Native + Expo + TypeScript, horoscopes, natal charts, synastry, transits, all wired through @roxyapi/sdk. Use a publishable key in the mobile client and keep secret keys in a backend. Clone:
For the conversational variant ("describe two people, get the score"), the astrology-ai-chatbot template is the flagship Next.js + Remote MCP reference.
Upgrade to production
Keep secret keys server-side from the first prototype. Put the fetch behind a Next.js route, Vercel function, or Cloudflare Worker. The Next.js integration guide shows the backend pattern.
Collect cities with <roxy-location-search>. Drop in the geocoding input from @roxyapi/ui instead of asking users to type coordinates. It emits roxy-location-select with latitude, longitude, and timezone, which feed straight into the compatibility call. Behind the scenes it hits /location/search (cities[0]).
Swap to full synastry.POST /astrology/synastry (calculateSynastry) returns inter-aspects, strengths, challenges, and a compatibilityScore. Same inputs, richer output, premium tier.
Do not ship a secret API key in browser code. Use a publishable key with an origin allowlist or proxy through a backend.
Send a local birth time.14:30:00 is the canonical format. 14:30 is also accepted, with seconds defaulting to 00. Out-of-range times return 400.
Both people need full birth data. Each needs date, time, latitude, longitude, and timezone. Missing required fields return 400. If the birth time is unknown, the request still needs a time: use 12:00:00 as an explicit assumption and label the reading accordingly. The API does not recover the unknown birth time.
IANA beats decimal for DST correctness."America/New_York" resolves to EST or EDT automatically. -5 is always EST.
Synastry path is /astrology/synastry, not /synastry. Nested under /astrology. Easy typo.
Positions read directly from the NASA JPL DE440 ephemeris, verified against NASA JPL Horizons. Score breakdowns are deterministic per pair of birth data.
What to build next
The tarot app tutorial adds a second reading type for dating apps with the same fetch pattern.
The AI chatbot tutorial lets users type birth data in natural language and have an LLM call this endpoint for them.
The astrology guide lists every Western endpoint you can swap in.
The vedic guide covers Gun Milan for matrimonial builds.
R
RosieYour AI guide to RoxyAPI
R
Hi, I am Rosie, your guide to the RoxyAPI insight tools.
Ask me to read your birth chart, pull a card, or map your numbers, and I will interpret what it means for you. Unlike most AIs, I never make the numbers up: every reading runs on real, verified calculations. Curious about the API, pricing, or docs instead? Ask me that too.