# Use RoxyAPI with Wix

> Ship a natal chart tool, a daily horoscope widget, a tarot reading page, or a Life Path calculator on any [Wix](https://www.wix.com) or [Wix Studio](https://www.wix.com/studio) site in under 20 minutes. No external backend.

Wix Velo is the JavaScript dev layer inside Wix Editor and Wix Studio. You get a Secrets Manager for API keys, backend web modules for server code, and the `wix-fetch` client for outbound calls. That is exactly the layout you need to keep a Roxy key off the page and the response on the screen.

## What you can build on Wix

- Natal chart generator that reads birth date, time, and place from a form
- Daily horoscope widget bound to 12 zodiac buttons on the homepage
- Tarot reading page with three-card or Celtic Cross spreads
- Life Path calculator that captures name and birth date
- Vedic kundli page with nakshatra, Vimshottari Dasha, and panchang
- Dream meaning lookup on a search input
- Transit report panel paired with a saved natal chart

## What you need, 30 seconds

1. A Roxy API key. Get one on the [pricing page](/pricing).
2. A Wix site with **Dev Mode** enabled. In Wix Editor click **Dev Mode, Turn on Dev Mode**. In Wix Studio the code panel is already open.
3. Ten minutes.

**Tip: Run the [quickstart](/docs/quickstart) curl once in a terminal before you bring the key into Wix. A successful JSON response confirms the key itself is good.**

## Step 1, connect your first endpoint

The Wix pattern has three pieces:

1. **Secrets Manager** holds the Roxy key, encrypted, readable only from backend code.
2. **Backend web module** (`.web.js` file) calls `wix-fetch` with the key.
3. **Page code** imports the web method and binds results to elements.

Store the key first:

1. Wix dashboard, **Settings**, scroll to **Developer Tools**, open **Secrets Manager**.
2. **Add Secret**. Name `ROXY_API_KEY` (uppercase, underscore). Paste your key from [your account](/account). Save.

**Warning: Wix requires a Members Area to exist on the site before you create your first secret. `getSecret()` reads do not require it. If you see the "Members Area required" prompt, follow the wizard once and then come back.**

Now create the backend web module. Wix Studio sidebar, **Backend**, `+`, **New .web.js file**. Name it `roxy.web.js`. Paste:

```javascript
// backend/roxy.web.js
import { Permissions, webMethod } from 'wix-web-module';
import wixFetch from 'wix-fetch';
import wixSecretsBackend from 'wix-secrets-backend';

const ROXY_BASE = 'https://roxyapi.com/api/v2';

async function roxyGet(path) {
  const apiKey = await wixSecretsBackend.getSecret('ROXY_API_KEY');
  const res = await wixFetch(`${ROXY_BASE}${path}`, {
    method: 'GET',
    headers: { 'X-API-Key': apiKey },
  });
  if (!res.ok) throw new Error(`RoxyAPI ${res.status}`);
  return res.json();
}

async function roxyPost(path, body) {
  const apiKey = await wixSecretsBackend.getSecret('ROXY_API_KEY');
  const res = await wixFetch(`${ROXY_BASE}${path}`, {
    method: 'POST',
    headers: {
      'X-API-Key': apiKey,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(body),
  });
  if (!res.ok) throw new Error(`RoxyAPI ${res.status}`);
  return res.json();
}

export const getDailyHoroscope = webMethod(
  Permissions.Anyone,
  async (sign) => roxyGet(`/astrology/horoscope/${sign}/daily`),
);

export const getNatalChart = webMethod(
  Permissions.Anyone,
  async (birthData) => roxyPost('/astrology/natal-chart', birthData),
);
```

What this gives you:

- `wixFetch` runs on the backend (Node fetch under the hood).
- `wixSecretsBackend.getSecret` reads the encrypted secret.
- `webMethod(Permissions.Anyone, ...)` exposes the function to page code. Switch to `Permissions.SiteMember` or `Permissions.Admin` to restrict access.

Web method files must end in `.web.js`. The older `.jsw` format is deprecated.

## Step 2, ship a useful feature

Here is the full flow for a natal chart form. The most common Wix use case.


### Page code

```javascript
import { getNatalChart } from 'backend/roxy.web';

$w.onReady(() => {
  $w('#submitButton').onClick(async () => {
    $w('#submitButton').disable();
    $w('#statusText').text = 'Calculating your chart...';
    const payload = {
      date: $w('#birthDate').value,
      time: `${$w('#birthTime').value}:00`,
      latitude: Number($w('#latitude').value),
      longitude: Number($w('#longitude').value),
      timezone: $w('#timezone').value || 'UTC',
    };
    try {
      const chart = await getNatalChart(payload);
      const byName = (name) => chart.planets.find(p => p.name === name);
      $w('#sunSign').text = byName('Sun').sign;
      $w('#moonSign').text = byName('Moon').sign;
      $w('#risingSign').text = chart.ascendant.sign;
      $w('#resultBox').show();
      $w('#statusText').text = '';
    } catch (err) {
      $w('#statusText').text = 'Could not generate chart. Please check your inputs.';
      console.error(err);
    } finally {
      $w('#submitButton').enable();
    }
  });
});
```

### Form elements

| Element | ID | Purpose |
|---------|----|---------|
| Date picker | `#birthDate` | Birth date (YYYY-MM-DD) |
| Text input | `#birthTime` | Birth time, format `HH:MM` |
| Number input | `#latitude` | Birth place latitude |
| Number input | `#longitude` | Birth place longitude |
| Text input | `#timezone` | IANA zone, for example `America/New_York` |
| Button | `#submitButton` | Generate chart |
| Text | `#statusText` | Loading and error messages |
| Container | `#resultBox` | Hidden until chart returns |
| Text | `#sunSign`, `#moonSign`, `#risingSign` | Result display |

### 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"
  }'
```


**Tip: Looking up coordinates from a city name is painful. Roxy includes a location endpoint at [`GET /location/search?q=mumbai`](/api-reference#tag/location-and-timezone/GET/location/search) that returns latitude, longitude, and an IANA timezone string. Add another `webMethod` that proxies that call and wire it to an autocomplete field on your form. Users type the city, your backend resolves the rest.**

## Step 3, scale to the full surface

You have one web module. Adding the next 130 endpoints is the same pattern: new `webMethod` in the same `roxy.web.js` file, change the URL, change the body, `getSecret` is reused. 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 URL and body, paste into a new Velo web method.
- **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)
- **Most-used endpoints** that fit Wix 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 /vedic-astrology/panchang/detailed`](/api-reference#tag/vedic-astrology/POST/vedic-astrology/panchang/detailed), [`POST /tarot/spreads/three-card`](/api-reference#tag/tarot/POST/tarot/spreads/three-card), [`POST /numerology/life-path`](/api-reference#tag/numerology/POST/numerology/life-path).

## Caching web method results

Every daily horoscope is stable for 24 hours. Most lookup data (dream symbols, hexagram meanings, angel numbers) is stable forever. Wix web methods support built-in caching.

```javascript
export const getDailyHoroscope = webMethod(
  Permissions.Anyone,
  async (sign) => roxyGet(`/astrology/horoscope/${sign}/daily`),
  {
    cache: {
      ttl: 3600,
      tags: ['roxy-horoscope'],
    },
  },
);
```

`ttl` is seconds (3600 for an hour, 86400 for a day). `tags` is required for caching to activate. Wix caches the return per argument set, so each sign caches independently.

**Warning: Never cache user-specific results (personal natal charts, numerology for a specific name, birth transits for a specific moment). Only cache data that is the same for every visitor for a known period.**

## Gotchas

- **Backend-only key.** Never call `wix-fetch` against Roxy from page code and never hardcode the key in page code. Frontend calls expose the key in the browser and hit CORS restrictions on POST endpoints. Always route through a `.web.js` backend module with the key in the Secrets Manager.
- **Timezone.** Prefer IANA strings (`"America/New_York"`, `"Asia/Kolkata"`) in the birth data payload. 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. Cache daily content with the `webMethod` `cache` option rather than hitting Roxy on every page load.
- **Sandbox vs Live.** Preview runs in a sandboxed environment that sometimes masks errors. If a call works in Preview but fails on a live site, check Wix Developer Console, redeploy the site, confirm the secret exists on the site that is live (not only on a sandbox staging version).
- **Members Area prompt.** First-time secret creation requires a Members Area. Follow the wizard once, then continue.
- **Element IDs.** `$w('#id')` only works inside `$w.onReady` or event handlers. Calling a web method before `onReady` fires can reference elements that do not exist yet.

## What to build next

- The [astrology guide](/docs/guides/astrology) and [Vedic astrology guide](/docs/guides/vedic-astrology) cover endpoint ordering.
- The [AI chatbot tutorial](/docs/tutorials/ai-chatbot) shows how to add a Roxy-backed AI chat inside a Wix site.
- The [SDK guide](/docs/sdk) is there if you outgrow Velo and move logic to a server.
- Browse the [API reference](/api-reference) for every endpoint across 12 domains.
