# SDK (TypeScript / Python / PHP / WordPress)

Official Roxy SDKs for TypeScript, Python, and PHP, plus a WordPress plugin with Gutenberg blocks and shortcodes. Full type safety and IDE autocomplete on every code SDK, drop-in shortcodes on WordPress, all hitting the same 145+ endpoints across 12 domains. Same API shape, same domain names, three languages. Drop a `composer require`, `pip install`, or `npm install` into any Laravel, Symfony, Slim, Django, FastAPI, Next.js, or Express project and ship a natal-chart endpoint in five minutes.

- **TypeScript:** [`@roxyapi/sdk`](https://www.npmjs.com/package/@roxyapi/sdk) on npm
- **Python:** [`roxy-sdk`](https://pypi.org/project/roxy-sdk/) on PyPI
- **PHP:** [`roxyapi/sdk`](https://packagist.org/packages/roxyapi/sdk) on Packagist (PHP 8.2+)
- **WordPress:** [RoxyAPI plugin](https://wordpress.org/plugins/roxyapi/) on the WordPress.org Plugin Directory
- **UI components:** [`@roxyapi/ui`](https://www.npmjs.com/package/@roxyapi/ui) and [`@roxyapi/ui-react`](https://www.npmjs.com/package/@roxyapi/ui-react) on npm. Open-source web components for charts, tables, cards, and forms across every domain. Setup walkthrough at [/docs/ui](/docs/ui) (Next.js, vanilla HTML, shadcn). Catalog and live customizer at [/ui](/ui).

## Install


### npm
```bash
npm install @roxyapi/sdk
```

### bun
```bash
bun add @roxyapi/sdk
```

### pnpm
```bash
pnpm add @roxyapi/sdk
```

### yarn
```bash
yarn add @roxyapi/sdk
```

### pip
```bash
pip install roxy-sdk
```

### uv
```bash
uv add roxy-sdk
```

### poetry
```bash
poetry add roxy-sdk
```

### composer
```bash
composer require roxyapi/sdk
```

### WordPress

<div class="not-prose my-4">
  <a href="https://wordpress.org/plugins/roxyapi/" class="btn btn-primary inline-flex items-center gap-2 hover:gap-3 transition-all" target="_blank" rel="noopener" title="Install RoxyAPI from the WordPress.org Plugin Directory">
    Install from WordPress.org
    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 17 17 7"/><path d="M7 7h10v10"/></svg>
  </a>
</div>

In WordPress admin: Plugins → Add New → search **RoxyAPI** → Install Now → Activate. Settings → RoxyAPI to paste your API key. Full integration guide at [/docs/integrations/wordpress](/docs/integrations/wordpress "RoxyAPI WordPress plugin integration guide"). Prefer the latest unreleased code? Grab [`roxyapi.zip` from GitHub Releases](https://github.com/RoxyAPI/sdk-wordpress/releases/latest/download/roxyapi.zip "Download the latest RoxyAPI WordPress plugin zip from GitHub Releases") and upload via Plugins → Add New → Upload Plugin.

## Quick start

Two lines to instantiate, one line per API call. `createRoxy` / `create_roxy` / `RoxyAPI\Sdk\createRoxy` set the base URL, auth header, and SDK identification header automatically.


### TypeScript
```typescript
import { createRoxy } from '@roxyapi/sdk';

const roxy = createRoxy(process.env.ROXY_API_KEY!);

// Daily horoscope
const { data } = await roxy.astrology.getDailyHoroscope({
  path: { sign: 'aries' },
});

// Numerology life path
const { data: lp } = await roxy.numerology.calculateLifePath({
  body: { year: 1990, month: 1, day: 15 },
});

// Tarot Celtic Cross spread
const { data: reading } = await roxy.tarot.castCelticCross({
  body: { question: 'What should I focus on this month?' },
});
```

### Python
```python
from roxy_sdk import create_roxy

roxy = create_roxy("your-api-key")

# Daily horoscope
horoscope = roxy.astrology.get_daily_horoscope(sign="aries")

# Numerology life path
lp = roxy.numerology.calculate_life_path(year=1990, month=1, day=15)

# Tarot Celtic Cross spread
reading = roxy.tarot.cast_celtic_cross(question="What should I focus on this month?")
```

### PHP
```php
<?php

use function RoxyAPI\Sdk\createRoxy;

$roxy = createRoxy(getenv('ROXY_API_KEY'));

// Daily horoscope
$horoscope = $roxy->astrology->getDailyHoroscope(sign: 'aries');

// Numerology life path
$lp = $roxy->numerology->calculateLifePath(year: 1990, month: 1, day: 15);

// Tarot Celtic Cross spread
$reading = $roxy->tarot->castCelticCross(question: 'What should I focus on this month?');
```

**Warning: Never expose your API key in client-side code. Call Roxy from your server, API routes, serverless functions, or background workers only.**

## Authentication

Pass your API key on initialization. Get your API key at [roxyapi.com/pricing](/pricing), delivered instantly after checkout.


### TypeScript
```typescript
import { createRoxy } from '@roxyapi/sdk';

const roxy = createRoxy(process.env.ROXY_API_KEY!);
```

### Python
```python
import os
from roxy_sdk import create_roxy

roxy = create_roxy(os.environ["ROXY_API_KEY"])
```

### PHP
```php
<?php

use function RoxyAPI\Sdk\createRoxy;

$roxy = createRoxy(getenv('ROXY_API_KEY'));
```

## Domains

Each domain is a namespace on the `roxy` instance. TypeScript returns typed objects via `{ data, error, response }` per call. Python and PHP return the decoded JSON directly as associative arrays / dicts. Python raises `RoxyAPIError` on failure; PHP throws `RoxyApiException` (catch it and switch on `$e->errorCode`).

| Namespace (TS / PHP) | Namespace (Python) | What it covers |
|----------------------|--------------------|----------------|
| `roxy.astrology` / `$roxy->astrology` | `roxy.astrology` | Western astrology: natal charts, horoscopes, synastry, transits, moon phases |
| `roxy.vedicAstrology` / `$roxy->vedicAstrology` | `roxy.vedic_astrology` | Vedic / Jyotish: kundli, panchang, dashas, nakshatras, doshas, KP system |
| `roxy.numerology` / `$roxy->numerology` | `roxy.numerology` | Life path, expression, soul urge, personal year, karmic lessons |
| `roxy.tarot` / `$roxy->tarot` | `roxy.tarot` | Daily card, custom draws, three-card, Celtic Cross, yes / no, love spread |
| `roxy.biorhythm` / `$roxy->biorhythm` | `roxy.biorhythm` | Daily check-in, multi-day forecast, critical days, compatibility |
| `roxy.iching` / `$roxy->iching` | `roxy.iching` | Daily hexagram, three-coin cast, 64 hexagrams, trigrams |
| `roxy.crystals` / `$roxy->crystals` | `roxy.crystals` | Crystal meanings, zodiac / chakra pairings, birthstone, search |
| `roxy.dreams` / `$roxy->dreams` | `roxy.dreams` | Dream symbol dictionary, interpretations |
| `roxy.angelNumbers` / `$roxy->angelNumbers` | `roxy.angel_numbers` | Number meanings, universal digit-root lookup, daily |
| `roxy.location` / `$roxy->location` | `roxy.location` | City search for birth chart coordinates |
| `roxy.usage` / `$roxy->usage` | `roxy.usage` | API usage stats, remaining quota, subscription info |

## Location first

Every chart, horoscope, panchang, dasha, dosha, navamsa, KP, synastry, compatibility, and natal endpoint needs `latitude`, `longitude`, and a `timezone`. Call the location API first, then feed the result into the chart method.

The location response is a pagination envelope. Each city has both an IANA timezone string and a decimal `utcOffset`. Either form works on chart endpoints — pass the **IANA string** for DST-correct historical charts, or the **`utcOffset`** decimal if you prefer numbers.


### TypeScript
```typescript
const { data } = await roxy.location.searchCities({
  query: { q: 'Mumbai, India' },
});

// Response: { total, limit, offset, cities: [...] }
const { latitude, longitude, timezone } = data.cities[0];

const { data: chart } = await roxy.vedicAstrology.generateBirthChart({
  body: {
    date: '1990-01-15',
    time: '14:30:00',
    latitude,
    longitude,
    timezone, // IANA string like "Asia/Kolkata" — server resolves DST for the chart date
  },
});
```

### Python
```python
result = roxy.location.search_cities(q="Mumbai, India")

# Response: { "total", "limit", "offset", "cities": [...] }
city = result["cities"][0]

chart = roxy.vedic_astrology.generate_birth_chart(
    date="1990-01-15", time="14:30:00",
    latitude=city["latitude"], longitude=city["longitude"],
    timezone=city["timezone"],  # IANA string; server resolves DST for the chart date
)
```

### PHP
```php
$result = $roxy->location->searchCities(q: 'Mumbai, India');

// Response carries total, limit, offset, cities
$city = $result['cities'][0];

$chart = $roxy->vedicAstrology->generateBirthChart(
    date: '1990-01-15',
    time: '14:30:00',
    latitude: $city['latitude'],
    longitude: $city['longitude'],
    timezone: $city['timezone'], // IANA string; server resolves DST for the chart date
);
```

::: info
Chart endpoints accept `timezone` as either a decimal number (`5.5` for IST, `-5` for EST, `9` for Tokyo) or an IANA identifier (`"Asia/Kolkata"`, `"America/New_York"`). IANA strings are resolved server-side to the DST-correct offset for the request `date`, so a January 1990 New York birth gets EST (`-5`) even when you geocoded the city in July. The `utcOffset` field on the Location response is a convenience decimal if you prefer numbers. Both forms produce identical charts.

## Examples

### Daily horoscope


### TypeScript
```typescript
const { data, error } = await roxy.astrology.getDailyHoroscope({
  path: { sign: 'scorpio' },
});

if (error) {
  console.error(error);
} else {
  console.log(data.overview); // General daily forecast
  console.log(data.love);     // Love and relationship forecast
  console.log(data.career);   // Career outlook
}
```

### Python
```python
horoscope = roxy.astrology.get_daily_horoscope(sign="scorpio")
print(horoscope["overview"])  # General daily forecast
print(horoscope["love"])      # Love and relationship forecast
print(horoscope["career"])    # Career outlook
```

### PHP
```php
$horoscope = $roxy->astrology->getDailyHoroscope(sign: 'scorpio');
echo $horoscope['overview']; // General daily forecast
echo $horoscope['love'];     // Love and relationship forecast
echo $horoscope['career'];   // Career outlook
```

### Numerology life path


### TypeScript
```typescript
const { data } = await roxy.numerology.calculateLifePath({
  body: { year: 1990, month: 1, day: 15 },
});

console.log(data.number); // e.g. 7
console.log(data.type);   // "single" | "master"
```

### Python
```python
result = roxy.numerology.calculate_life_path(year=1990, month=1, day=15)
print(result["number"])  # e.g. 7
print(result["type"])    # "single" | "master"
```

### PHP
```php
$result = $roxy->numerology->calculateLifePath(year: 1990, month: 1, day: 15);
echo $result['number']; // e.g. 7
echo $result['type'];   // "single" | "master"
```

### Vedic birth chart

The response groups planets by the rashi (sign) they occupy. Each rashi has a `signs[]` array (planets in that rashi, often empty) plus a top-level `meta` dict with every planet keyed by name.


### TypeScript
```typescript
const { data } = await roxy.vedicAstrology.generateBirthChart({
  body: {
    date: '1990-01-15',
    time: '14:30:00',
    latitude: 28.6139,
    longitude: 77.209,
    timezone: 5.5,
  },
});

// Iterate rashis (aries..pisces) for the 12-sign chart
for (const rashi of ['aries', 'taurus', 'gemini'] as const) {
  console.log(rashi, data[rashi].signs); // planets in this rashi
}

// Or look up any planet directly
console.log(data.meta.Sun.rashi);            // "Capricorn"
console.log(data.meta.Moon.nakshatra.name);  // nakshatra name
```

### Python
```python
chart = roxy.vedic_astrology.generate_birth_chart(
    date="1990-01-15", time="14:30:00",
    latitude=28.6139, longitude=77.209, timezone="Asia/Kolkata",
)

# Iterate rashis for the 12-sign chart
for rashi in ["aries", "taurus", "gemini"]:
    print(rashi, chart[rashi]["signs"])

# Or look up any planet directly
print(chart["meta"]["Sun"]["rashi"])             # "Capricorn"
print(chart["meta"]["Moon"]["nakshatra"]["name"])  # nakshatra name
```

### PHP
```php
$chart = $roxy->vedicAstrology->generateBirthChart(
    date: '1990-01-15',
    time: '14:30:00',
    latitude: 28.6139,
    longitude: 77.209,
    timezone: 5.5,
);

// Iterate rashis for the 12-sign chart
foreach (['aries', 'taurus', 'gemini'] as $rashi) {
    echo $rashi, count($chart[$rashi]['signs']); // planets in this rashi
}

// Or look up any planet directly
echo $chart['meta']['Sun']['rashi'];           // "Capricorn"
echo $chart['meta']['Moon']['nakshatra']['name']; // nakshatra name
```

### Western natal chart


### TypeScript
```typescript
const { data } = await roxy.astrology.generateNatalChart({
  body: {
    date: '1990-01-15',
    time: '14:30:00',
    latitude: 28.6139,
    longitude: 77.209,
    timezone: 5.5,
  },
});

console.log(data.planets.length);  // 13 (incl. lunar nodes and Chiron)
console.log(data.houses.length);   // 12
console.log(data.ascendant.sign);  // ascendant zodiac sign
console.log(data.midheaven.sign);  // midheaven zodiac sign
```

### Python
```python
natal = roxy.astrology.generate_natal_chart(
    date="1990-01-15", time="14:30:00",
    latitude=28.6139, longitude=77.209, timezone="Asia/Kolkata",
)

print(len(natal["planets"]))   # 13
print(len(natal["houses"]))    # 12
print(natal["ascendant"]["sign"])  # ascendant zodiac sign
print(natal["midheaven"]["sign"])  # midheaven zodiac sign
```

### PHP
```php
$natal = $roxy->astrology->generateNatalChart(
    date: '1990-01-15',
    time: '14:30:00',
    latitude: 28.6139,
    longitude: 77.209,
    timezone: 5.5,
);

echo count($natal['planets']);  // 13
echo count($natal['houses']);   // 12
echo $natal['ascendant']['sign']; // ascendant zodiac sign
echo $natal['midheaven']['sign']; // midheaven zodiac sign
```

### Tarot daily card


### TypeScript
```typescript
const { data } = await roxy.tarot.getDailyCard({ body: { seed: 'user-123' } });
console.log(data.card.name);    // e.g. "The Star"
console.log(data.dailyMessage); // concise daily guidance
console.log(data.card.meaning); // full card interpretation
```

### Python
```python
card = roxy.tarot.get_daily_card(seed="user-123")
print(card["card"]["name"])      # e.g. "The Star"
print(card["dailyMessage"])      # concise daily guidance
print(card["card"]["meaning"])   # full card interpretation
```

### PHP
```php
$card = $roxy->tarot->getDailyCard(seed: 'user-123');
echo $card['card']['name'];     // e.g. "The Star"
echo $card['dailyMessage'];     // concise daily guidance
echo $card['card']['meaning'];  // full card interpretation
```

### Angel number lookup


### TypeScript
```typescript
const { data } = await roxy.angelNumbers.getAngelNumber({
  path: { number: '1111' },
});
console.log(data.coreMessage);       // Short divine message summary
console.log(data.meaning.spiritual); // Spiritual interpretation
console.log(data.meaning.love);      // Love / relationship meaning
```

### Python
```python
result = roxy.angel_numbers.get_angel_number(number="1111")
print(result["coreMessage"])          # Short divine message summary
print(result["meaning"]["spiritual"]) # Spiritual interpretation
print(result["meaning"]["love"])      # Love / relationship meaning
```

### PHP
```php
$result = $roxy->angelNumbers->getAngelNumber(number: '1111');
echo $result['coreMessage'];          // Short divine message summary
echo $result['meaning']['spiritual']; // Spiritual interpretation
echo $result['meaning']['love'];      // Love / relationship meaning
```

### Check usage


### TypeScript
```typescript
const { data } = await roxy.usage.getUsageStats();
console.log(`${data.usedThisMonth} / ${data.requestsPerMonth} requests used`);
```

### Python
```python
stats = roxy.usage.get_usage_stats()
print(f"{stats['usedThisMonth']} / {stats['requestsPerMonth']} requests used")
```

### PHP
```php
$stats = $roxy->usage->getUsageStats();
echo "{$stats['usedThisMonth']} / {$stats['requestsPerMonth']} requests used";
```

## Multi-language responses

Interpretations are available in eight languages: English (`en`), Turkish (`tr`), German (`de`), Spanish (`es`), French (`fr`), Hindi (`hi`), Portuguese (`pt`), Russian (`ru`).


### TypeScript
```typescript
const { data } = await roxy.tarot.getDailyCard({
  body: { date: '2026-04-22' },
  query: { lang: 'es' },
});
```

### Python
```python
card = roxy.tarot.get_daily_card(date="2026-04-22", lang="es")
```

### PHP
```php
$card = $roxy->tarot->getDailyCard(date: '2026-04-22', lang: 'es');
```

Supported: `astrology`, `vedicAstrology` / `vedic_astrology`, `numerology`, `tarot`, `biorhythm`, `iching`, `crystals`, `angelNumbers` / `angel_numbers`. English-only: `dreams`, `location`, `usage`.

## Async support

TypeScript is async by default (every method returns a Promise). Python ships an `_async` variant for every sync method, for asyncio, FastAPI, or any event loop. PHP is synchronous per call; for concurrent fan-out (e.g. fetching 12 horoscopes in parallel) use the Saloon connector's request pool — see the [PHP SDK README](https://github.com/RoxyAPI/sdk-php) for examples.


### TypeScript
```typescript
// Already async — every method returns a Promise
const { data } = await roxy.astrology.getDailyHoroscope({ path: { sign: 'aries' } });
```

### Python
```python
import asyncio
from roxy_sdk import create_roxy

async def main():
    roxy = create_roxy("your-api-key")
    horoscope = await roxy.astrology.get_daily_horoscope_async(sign="aries")
    card = await roxy.tarot.get_daily_card_async()
    print(horoscope, card)

asyncio.run(main())
```

### PHP
```php
// Each call is synchronous. For concurrent fan-out, use the Saloon pool API
// on the underlying connector (Saloon ships a battle-tested request pool).
$horoscope = $roxy->astrology->getDailyHoroscope(sign: 'aries');
$card = $roxy->tarot->getDailyCard();
```

## Error handling

TypeScript returns `{ data, error, response }` per call. Python raises `RoxyAPIError`. PHP throws `RoxyApiException`. All three expose a stable `code` / `errorCode` field you can branch on.


### TypeScript
```typescript
const { data, error } = await roxy.tarot.castYesNo({
  body: { question: 'Should I take this opportunity?' },
});

if (error) {
  switch (error.code) {
    case 'validation_error':
      console.error('Bad input:', error.error);
      break;
    case 'rate_limit_exceeded':
      console.error('Monthly quota reached');
      break;
    default:
      console.error('API error:', error.code, error.error);
  }
} else {
  console.log(data.answer); // "Yes" | "No" | "Maybe"
}
```

### Python
```python
from roxy_sdk import create_roxy, RoxyAPIError

try:
    result = roxy.tarot.cast_yes_no(question="Should I take this opportunity?")
    print(result["answer"])  # "Yes" | "No" | "Maybe"
except RoxyAPIError as e:
    if e.code == "validation_error":
        print(f"Bad input: {e.error}")
    elif e.code == "rate_limit_exceeded":
        print("Monthly quota reached")
    else:
        print(f"API error: {e.code} {e.error}")
```

### PHP
```php
use RoxyAPI\Sdk\RoxyApiException;

try {
    $result = $roxy->tarot->castYesNo(question: 'Should I take this opportunity?');
    echo $result['answer']; // "Yes" | "No" | "Maybe"
} catch (RoxyApiException $e) {
    match ($e->errorCode) {
        'validation_error'     => fwrite(STDERR, "Bad input: {$e->error}\n"),
        'rate_limit_exceeded'  => fwrite(STDERR, "Monthly quota reached\n"),
        default                => fwrite(STDERR, "API error: {$e->errorCode} {$e->error}\n"),
    };
}
```

### Error codes

| Status | Code | When |
|--------|------|------|
| 400 | `validation_error` | Missing or invalid parameters. Check `issues[]` for per-field failures. |
| 401 | `api_key_required` | No API key provided |
| 401 | `invalid_api_key` | Key format invalid or tampered |
| 401 | `subscription_not_found` | Key references non-existent subscription |
| 401 | `subscription_inactive` | Subscription cancelled, expired, or suspended |
| 404 | `not_found` | Resource does not exist |
| 429 | `rate_limit_exceeded` | Monthly request quota reached |
| 500 | `internal_error` | Server error |

The `code` field is machine-readable and stable, safe to switch on. The `error` field is human-readable and may change wording.

## Type safety

Every SDK is fully typed for its language. TypeScript ships generated `.d.ts` definitions. PHP ships PHPDoc on every Saloon Request class plus a phpstan-level-8-clean public surface. Python ships `py.typed` for mypy and Pyright.

```typescript
// TypeScript knows sign must be one of the 12 zodiac signs
const { data } = await roxy.astrology.getDailyHoroscope({
  path: { sign: 'aries' }, // autocompletes all 12 options
});

// data is typed, no manual casting needed
console.log(data.date);     // string
console.log(data.overview); // string
```

You can also import individual namespace classes or response types:

```typescript
import { Astrology, type GetAstrologyHoroscopeBySignDailyResponse } from '@roxyapi/sdk';
```

PHP uses named arguments (PHP 8.0+) for parameters and PHPDoc-typed Saloon Request classes for response shapes. PhpStorm, VS Code (Intelephense), and phpstan all see the full signature without any extra setup.

## Gotchas


### Parameters are structured
TypeScript always uses `{ path: {...} }`, `{ body: {...} }`, or `{ query: {...} }`. Python uses keyword arguments only (`sign="aries"`), never positional. PHP uses named arguments (`sign: 'aries'`), never positional. Do not mix the patterns.

### Timezone accepts both IANA and decimal
Chart endpoints accept `timezone` as either a decimal (`5.5`, `-5`, `0`) or an IANA identifier (`"Asia/Kolkata"`, `"America/New_York"`). IANA is preferred because it is DST-resolved against the request's `date`, so historical birth charts pick the correct offset even when you geocoded the city today. Both `city.timezone` and `city.utcOffset` from the Location response work.

### Location returns an envelope, not a bare array
`data.cities[0]` in TypeScript and `result["cities"][0]` in Python. The top-level object carries `total`, `limit`, `offset` for pagination. Same envelope pattern applies to `tarot.listCards` (`data.cards`), `iching.listHexagrams` (`data.hexagrams`), `dreams.searchDreamSymbols` (`data.symbols`), and `crystals.searchCrystals` / `getCrystalsByZodiac` / `getCrystalsByChakra` (`data.crystals`).

### Date format is YYYY-MM-DD, time is HH:MM:SS
Both are strings. Time must include seconds, `14:30` will be rejected.

### Do not guess method names
Type `roxy.domain.` and let autocomplete show methods. Names come from `operationId` in the OpenAPI spec, not URL paths. Examples: `getDailyHoroscope` (not `dailyHoroscope`), `calculateLifePath` (not `lifePath`), `castCelticCross` (not `celticCross`).

### Chart endpoints need coordinates
Use the location API to geocode cities before any birth chart, synastry, panchang, KP, or natal method. Never hardcode a user's latitude, longitude, or timezone from memory.

### Do not expose API keys client-side
Call Roxy from server code, API routes, serverless functions, or background workers only. Any key shipped to the browser is a leaked key.

### Do not use raw fetch or requests
The SDK handles auth headers, base URL, SDK identification, and typed responses. Raw HTTP clients re-invent this and miss the type safety.

### Python errors raise RoxyAPIError, PHP throws RoxyApiException
Catch and switch on `e.code` (Python) or `$e->errorCode` (PHP), not the human-readable message text. The codes are stable between releases; the message text may change.

### TypeScript data and error are mutually exclusive
If `error` is set, `data` is undefined. Always check `error` first.

## Render the response in the browser

For projects that need to display the response visually (charts, tables, cards, forms) without writing your own SVG geometry or table layouts, install Roxy UI alongside the SDK.


### npm
```bash
npm install @roxyapi/ui @roxyapi/sdk
```

### bun
```bash
bun add @roxyapi/ui @roxyapi/sdk
```

### CDN
```html
<script src="https://cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn/roxy-ui.js"></script>
```

Components are stateless. Caller fetches via the SDK, passes the response as the `data` prop. Theming via CSS custom properties on `:root` or per element. Works in React, Next.js, Vue, Svelte, Angular, vanilla HTML, and WordPress.


### React / Next.js
```tsx
'use client';

import { createRoxy } from '@roxyapi/sdk';
import { RoxyNatalChart, RoxyLocationSearch } from '@roxyapi/ui-react';
import { useState } from 'react';

const roxy = createRoxy(process.env.NEXT_PUBLIC_ROXY_API_KEY!);

export default function Page() {
  const [chart, setChart] = useState(null);

  const onLocationSelect = async (e: CustomEvent<{ latitude: number; longitude: number; timezone: string }>) => {
    const { data } = await roxy.astrology.generateNatalChart({
      body: { date: '1990-01-15', time: '14:30:00', ...e.detail },
    });
    setChart(data);
  };

  return (
    <>
      <RoxyLocationSearch onroxy-location-select={onLocationSelect} />
      {chart && <RoxyNatalChart data={chart} />}
    </>
  );
}
```

### Vanilla HTML
```html
<script src="https://cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn/roxy-ui.js"></script>
<roxy-natal-chart id="chart"></roxy-natal-chart>
<script type="module">
  import { createRoxy } from 'https://cdn.jsdelivr.net/npm/@roxyapi/sdk@1/dist/factory.js';
  const roxy = createRoxy(import.meta.env?.ROXY_API_KEY);
  const { data } = await roxy.astrology.generateNatalChart({
    body: { date: '1990-01-15', time: '14:30:00', latitude: 28.6139, longitude: 77.2090, timezone: 5.5 },
  });
  document.getElementById('chart').data = data;
</script>
```

### WordPress
```php
add_action('wp_enqueue_scripts', function () {
  wp_enqueue_script(
    'roxy-ui',
    'https://cdn.jsdelivr.net/npm/@roxyapi/ui@latest/dist/cdn/roxy-ui.js',
    [], null, true
  );
});

// In a template or shortcode handler:
echo '<roxy-natal-chart data="' . esc_attr(wp_json_encode($response)) . '"></roxy-natal-chart>';
```

Full setup walkthrough at [/docs/ui](/docs/ui "Roxy UI integration guide for Next.js, vanilla HTML, and shadcn"), catalog and live customizer at [/ui](/ui "Roxy UI: open source web components for the RoxyAPI catalog"). Source on GitHub at [RoxyAPI/ui](https://github.com/RoxyAPI/ui), MIT licensed, published with SLSA provenance via OIDC.

## AI coding agents

All three SDKs ship `AGENTS.md` bundled in the package so AI agents (Claude Code, Cursor, GitHub Copilot, OpenAI Codex, Gemini CLI) read it directly from `node_modules/@roxyapi/sdk/AGENTS.md`, the installed Python package, or `vendor/roxyapi/sdk/AGENTS.md`.

- Quickstart, critical patterns, common tasks reference, gotchas
- Field format table covering timezone decimals, date / time strings, nested person objects, enum values
- MCP tool name mapping for every REST endpoint

For agents in projects WITHOUT any SDK installed (Go, Ruby, Rust, raw curl, Bash), there is also a site-level <a href="/AGENTS.md" target="_blank" rel="noopener" title="AGENTS.md execution playbook for AI coding agents - tight 120-line guide for Cursor, Codex, Windsurf, Aider, Claude Code, Gemini CLI to build apps using raw HTTP">AGENTS.md playbook</a> at `https://roxyapi.com/AGENTS.md` covering the same Rule 0, common tasks, body shapes, error contract, and field gotchas, but language-agnostic.

Also available: a [remote MCP server](/docs/mcp) per domain at `https://roxyapi.com/mcp/{domain}` (Streamable HTTP, no stdio / no self-hosting) for agents that speak the Model Context Protocol.

## Links

- [API Reference](/api-reference) — browse all endpoints and try live calls
- [Quickstart](/docs/quickstart) — your first API call in 60 seconds
- [MCP Setup](/docs/mcp) — connect AI agents to Roxy
- [Starter Apps](/docs/starters) — full app templates to clone
- [Pricing](/pricing) — get your API key
- [Roxy UI setup walkthrough](/docs/ui) — Next.js, vanilla HTML, shadcn, theming, gotchas
- [Roxy UI catalog](/ui) — every component with live preview and customizer
- [TypeScript SDK on GitHub](https://github.com/RoxyAPI/sdk-typescript)
- [Python SDK on GitHub](https://github.com/RoxyAPI/sdk-python)
- [PHP SDK on GitHub](https://github.com/RoxyAPI/sdk-php)
- [WordPress plugin on wordpress.org](https://wordpress.org/plugins/roxyapi/) ([source on GitHub](https://github.com/RoxyAPI/sdk-wordpress))
- [Roxy UI on GitHub](https://github.com/RoxyAPI/ui)
