# Use RoxyAPI with WordPress

> Add a daily horoscope shortcode, a natal chart block, a Life Path calculator, or a dream symbol lookup to any WordPress site in under 20 minutes.

WordPress powers about 40 percent of the web. Roxy plugs into it two ways: the official plugin gives you Gutenberg blocks and ready-made shortcodes, and the manual path uses standard PHP (`wp_remote_post`, transients, custom REST routes) for builders who want full control over each call.

## Use the plugin (recommended)

<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>

1. In WordPress admin go to Plugins → Add New.
2. Search for **RoxyAPI**.
3. Click Install Now, then Activate.
4. Settings → RoxyAPI to paste your API key.

The plugin ships Gutenberg blocks and shortcodes covering astrology, tarot, numerology, horoscope, I Ching, and biorhythm. Source repo: [github.com/RoxyAPI/sdk-wordpress](https://github.com/RoxyAPI/sdk-wordpress "RoxyAPI WordPress plugin GitHub repository").

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.

Prefer to write each shortcode yourself? Skip the plugin and follow the manual path below.

## What you can build on WordPress

- Daily horoscope shortcode you drop into any post or page
- Natal chart shortcode that takes attributes and renders the chart
- Client-side horoscope picker backed by a custom REST route
- Life Path calculator on a Contact Form 7 or WPForms submit
- Vedic kundli generator with PDF export via FPDF or DOMPDF
- Dream symbol lookup widget in the sidebar
- WooCommerce reading product that emails the chart after checkout

## What you need, 30 seconds

1. A Roxy API key. Get one on the [pricing page](/pricing).
2. A WordPress site where you can edit `wp-config.php` or install a plugin. Self-hosted WordPress works everywhere. WordPress.com Personal plan or higher also works (the free plan does not allow plugins or custom code).
3. Ten minutes.

**Tip: Not comfortable editing PHP? Install the free [Code Snippets](https://wordpress.org/plugins/code-snippets/) or [WPCode](https://wordpress.org/plugins/insert-headers-and-footers/) plugin. Both let you paste PHP snippets in a UI without touching theme files. Every snippet on this page works inside Code Snippets unchanged.**

## Step 1, connect your first endpoint

Two places to store the key. Pick whichever matches your setup.


### wp-config.php constant

Most secure. The constant lives outside the database.

1. Connect via SFTP, the host file manager, or the hosting control panel.
2. Open `wp-config.php` in the WordPress root.
3. Above the line that reads `That is all, stop editing` (near the bottom of the file) add:
   ```php
   define( 'ROXY_API_KEY', 'your_roxyapi_key_here' );
   ```
4. Save. The constant is now available in every PHP file. WordPress reads `wp-config.php` on every request, no restart needed.

### Code Snippets plugin

Easiest. No SFTP, no file editing.

1. Install the **Code Snippets** plugin.
2. Create a new PHP snippet.
3. At the top, above any functions you add:
   ```php
   <?php
   define( 'ROXY_API_KEY', 'your_roxyapi_key_here' );
   ```
4. Save and activate. The key runs server-side like a plugin.

Trade-off: Code Snippets lives in the database (`wp_snippets` table). Database exports include it. For production sites that take regular database backups, the `wp-config.php` path is cleaner.


**Warning: Whichever path you pick, never put the key in a theme file that loads on the frontend, a `wp_options` row, a post meta field, a custom field value, or any JavaScript file. Those either ship to the browser or end up in a database export.**

Now add a shortcode. Paste into Code Snippets as a new PHP snippet or into a child theme `functions.php`.

```php
<?php
add_shortcode( 'roxy_horoscope', 'roxy_horoscope_shortcode' );

function roxy_horoscope_shortcode( $atts ) {
    $atts = shortcode_atts( array( 'sign' => 'aries' ), $atts, 'roxy_horoscope' );
    $sign = sanitize_key( $atts['sign'] );
    $valid = array( 'aries', 'taurus', 'gemini', 'cancer', 'leo', 'virgo', 'libra', 'scorpio', 'sagittarius', 'capricorn', 'aquarius', 'pisces' );
    if ( ! in_array( $sign, $valid, true ) ) {
        return '<p>Invalid zodiac sign.</p>';
    }
    if ( ! defined( 'ROXY_API_KEY' ) ) {
        return '<p>RoxyAPI key not configured.</p>';
    }
    $cache_key = 'roxy_horoscope_' . $sign;
    $cached    = get_transient( $cache_key );
    if ( false !== $cached ) {
        return $cached;
    }
    $response = wp_remote_get(
        'https://roxyapi.com/api/v2/astrology/horoscope/' . $sign . '/daily',
        array(
            'headers' => array( 'X-API-Key' => ROXY_API_KEY ),
            'timeout' => 10,
        )
    );
    if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
        return '<p>Could not load today horoscope.</p>';
    }
    $data = json_decode( wp_remote_retrieve_body( $response ), true );
    if ( empty( $data['overview'] ) ) {
        return '<p>Horoscope unavailable.</p>';
    }
    $html  = '<div class="roxy-horoscope">';
    $html .= '<h3>' . esc_html( $data['sign'] ) . ' daily horoscope</h3>';
    $html .= '<p>' . esc_html( $data['overview'] ) . '</p>';
    $html .= '<p><strong>Love:</strong> ' . esc_html( $data['love'] ) . '</p>';
    $html .= '<p><strong>Career:</strong> ' . esc_html( $data['career'] ) . '</p>';
    $html .= '<p>Lucky number ' . intval( $data['luckyNumber'] ) . ', lucky color ' . esc_html( $data['luckyColor'] ) . '.</p>';
    $html .= '</div>';
    set_transient( $cache_key, $html, HOUR_IN_SECONDS );
    return $html;
}
```

Drop `[roxy_horoscope sign="leo"]` into any post or page in the block editor (Shortcode block). You should see the rendered horoscope with daily overview, love, career, lucky number, and lucky color.

## Step 2, ship a useful feature

Here is the full flow for a natal chart shortcode that takes birth details and renders the chart.


### Shortcode with POST body

```php
<?php
add_shortcode( 'roxy_natal_chart', 'roxy_natal_chart_shortcode' );

function roxy_natal_chart_shortcode( $atts ) {
    $atts = shortcode_atts(
        array(
            'date'      => '',
            'time'      => '',
            'latitude'  => '',
            'longitude' => '',
            'timezone'  => 'UTC',
        ),
        $atts,
        'roxy_natal_chart'
    );
    if ( empty( $atts['date'] ) || empty( $atts['time'] ) || empty( $atts['latitude'] ) || empty( $atts['longitude'] ) ) {
        return '<p>Date, time, latitude, and longitude are required.</p>';
    }
    if ( ! defined( 'ROXY_API_KEY' ) ) {
        return '<p>RoxyAPI key not configured.</p>';
    }
    $payload = array(
        'date'      => sanitize_text_field( $atts['date'] ),
        'time'      => sanitize_text_field( $atts['time'] ),
        'latitude'  => floatval( $atts['latitude'] ),
        'longitude' => floatval( $atts['longitude'] ),
        'timezone'  => sanitize_text_field( $atts['timezone'] ),
    );
    $response = wp_remote_post(
        'https://roxyapi.com/api/v2/astrology/natal-chart',
        array(
            'headers' => array(
                'X-API-Key'    => ROXY_API_KEY,
                'Content-Type' => 'application/json',
            ),
            'body'    => wp_json_encode( $payload ),
            'timeout' => 15,
        )
    );
    if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
        return '<p>Could not generate chart.</p>';
    }
    $data = json_decode( wp_remote_retrieve_body( $response ), true );
    return '<pre class="roxy-chart">' . esc_html( wp_json_encode( $data, JSON_PRETTY_PRINT ) ) . '</pre>';
}
```

Use it like this:

```
[roxy_natal_chart date="1990-05-12" time="14:30:00" latitude="40.7128" longitude="-74.0060" timezone="America/New_York"]
```

### curl preview

```bash
curl -X POST "https://roxyapi.com/api/v2/astrology/natal-chart" \
  -H "X-API-Key: $ROXY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "date": "1990-05-12",
    "time": "14:30:00",
    "latitude": 40.7128,
    "longitude": -74.0060,
    "timezone": "America/New_York"
  }'
```


For a real production page, replace the raw `<pre>` JSON dump with a styled grid of planets, houses, and aspects. The [astrology guide](/docs/guides/astrology) documents the response shape.

### Public REST proxy for JavaScript widgets

If you want a JavaScript widget on the frontend to fetch fresh data after page load, register a custom REST route that proxies the call.

```php
<?php
add_action( 'rest_api_init', function () {
    register_rest_route(
        'roxy/v1',
        '/horoscope/(?P<sign>[a-z]+)',
        array(
            'methods'             => 'GET',
            'callback'            => 'roxy_rest_horoscope',
            'permission_callback' => '__return_true',
        )
    );
} );

function roxy_rest_horoscope( $request ) {
    $sign = strtolower( $request['sign'] );
    $valid = array( 'aries', 'taurus', 'gemini', 'cancer', 'leo', 'virgo', 'libra', 'scorpio', 'sagittarius', 'capricorn', 'aquarius', 'pisces' );
    if ( ! in_array( $sign, $valid, true ) ) {
        return new WP_Error( 'invalid_sign', 'Invalid zodiac sign', array( 'status' => 400 ) );
    }
    if ( ! defined( 'ROXY_API_KEY' ) ) {
        return new WP_Error( 'no_key', 'API key not configured', array( 'status' => 500 ) );
    }
    $cache_key = 'roxy_rest_horoscope_' . $sign;
    $cached    = get_transient( $cache_key );
    if ( false !== $cached ) {
        return rest_ensure_response( $cached );
    }
    $response = wp_remote_get(
        'https://roxyapi.com/api/v2/astrology/horoscope/' . $sign . '/daily',
        array( 'headers' => array( 'X-API-Key' => ROXY_API_KEY ), 'timeout' => 10 )
    );
    if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
        return new WP_Error( 'upstream', 'Upstream error', array( 'status' => 502 ) );
    }
    $data = json_decode( wp_remote_retrieve_body( $response ), true );
    set_transient( $cache_key, $data, HOUR_IN_SECONDS );
    return rest_ensure_response( $data );
}
```

Your endpoint is live at `https://your-site.com/wp-json/roxy/v1/horoscope/aries`. The browser only sees your own domain, never roxyapi.com.

## Step 3, scale to the full surface

You have one shortcode working. Adding the next 130 endpoints is the same pattern: copy the snippet, change the URL, change the callback name, the `ROXY_API_KEY` constant is shared. Three places to pick the next one:

- **[API reference](/api-reference)** has a pre-filled test key. Try a call in the browser, copy the curl, translate into `wp_remote_get` or `wp_remote_post`.
- **Domain guides** for which endpoints to call in what order:
  - [Western Astrology](/docs/guides/astrology), [Vedic Astrology](/docs/guides/vedic-astrology), [Tarot](/docs/guides/tarot), [Numerology](/docs/guides/numerology), [I Ching](/docs/guides/iching), [Dreams](/docs/guides/dreams), [Crystals](/docs/guides/crystals), [Angel Numbers](/docs/guides/angel-numbers)
- **Most-used endpoints** that fit WordPress sites: [`GET /astrology/horoscope/{sign}/daily`](/api-reference#tag/western-astrology/GET/astrology/horoscope/{sign}/daily), [`POST /astrology/natal-chart`](/api-reference#tag/western-astrology/POST/astrology/natal-chart), [`POST /vedic-astrology/birth-chart`](/api-reference#tag/vedic-astrology/POST/vedic-astrology/birth-chart), [`POST /numerology/life-path`](/api-reference#tag/numerology/POST/numerology/life-path), [`GET /crystals/zodiac/{sign}`](/api-reference#tag/crystals-and-healing-stones/GET/crystals/zodiac/{sign}), [`GET /dreams/symbols`](/api-reference#tag/dreams/GET/dreams/symbols), [`GET /angel-numbers/numbers/{number}`](/api-reference#tag/angel-numbers/GET/angel-numbers/numbers/{number}).

## Where to put the code

Four options, roughly in order of "the right thing to do":

1. **Code Snippets plugin.** Best for non-developers. Survives theme switches.
2. **Child theme `functions.php`.** Survives parent theme updates. Loses everything if you switch themes.
3. **`mu-plugins` directory.** Auto-loaded, survives every theme switch, never needs activation. Best for "this is part of the site forever".
4. **Custom plugin.** Best if you plan to share or version the code separately.

Avoid editing the parent theme `functions.php` directly. Updates wipe it.

## Gotchas

- **Backend-only key.** The API key lives in `wp-config.php` or Code Snippets. Never put it in `wp_options`, a theme file that loads on the frontend, a custom field, or a JavaScript file.
- **Timezone.** Prefer IANA strings (`"America/New_York"`, `"Asia/Kolkata"`). Decimal offsets like `5.5` are accepted but do not handle daylight saving. The server resolves IANA to the DST-correct offset for the request date.
- **Rate limits.** Every Roxy plan has daily and monthly caps. Every snippet on this page uses transients for at least an hour. For permanent data (dream symbols, hexagrams, angel numbers) use `DAY_IN_SECONDS` or `WEEK_IN_SECONDS`.
- **Object cache plugins.** Redis or Memcached transients are per-process and flush on cache reset. If you need durability, use `update_option` or a custom table.
- **Refresh permalinks after adding a REST route.** Go to **Settings, Permalinks**, click Save. WordPress regenerates the rewrite rules.
- **cURL SSL errors.** If `wp_remote_get` errors with "cURL error 60", the host has stale CA certificates. Contact hosting support. Do not disable SSL verification; that opens you to man-in-the-middle attacks.

## What to build next

- The [astrology guide](/docs/guides/astrology) and [Vedic astrology guide](/docs/guides/vedic-astrology) cover endpoint ordering for blog-style sites.
- The [Next.js integration](/docs/integrations/nextjs) is the right move when you outgrow shortcodes and want a typed framework.
- The [SDK guide](/docs/sdk) is the reference for typed calls if you port logic off WordPress.
- Browse the [API reference](/api-reference) for every endpoint across 12 domains.
