
# Bubble astrology app, no code API connector

> Add a natal chart generator, a daily horoscope page, a Life Path calculator, or a tarot reading to your [Bubble](https://bubble.io/) app in about 20 minutes. No code.

The **API Connector** routes every call through a Bubble server, so the key stays out of the visitor browser and every response field becomes bindable dynamic data. One collection, one auth setting, and all 259+ endpoints are open to you.

**Tip: Only showing a reading? Skip the API Connector**
If the page just displays a chart or a horoscope and never stores anything, the faster path is a copy-paste widget in an **HTML element**. One snippet plus a publishable `pk_` key, and the widget renders its own inputs and fetches in the visitor browser. Grab the prefilled snippet from the [widgets gallery](/widgets); the [widgets guide](/docs/widgets) covers the rest. Come back here when you need the data inside your Bubble database.

## The call that proves it

Run this in a terminal first. A 200 here means the key is good, so anything that fails next is Bubble wiring.

```bash
curl "https://roxyapi.com/api/v2/astrology/horoscope/aries/daily" \
  -H "X-API-Key: $ROXY_API_KEY"
```

No key yet? One key covers every domain and checkout is instant: [pricing](/pricing).

Now set up the collection. The key goes in the collection authentication and nowhere else.

1. **Plugins**, **Add plugin**, install the Bubble-built **API Connector**.
2. Open it and click **+ New** to add a collection.
3. **Collection name** `RoxyAPI`.
4. **Authentication** `Private key in header`.
5. **Key name** `X-API-Key`.
6. **Private key** paste your key from [your account](/account?tab=keys).
7. Under **Shared headers for all calls**, add `Content-Type` with the value `application/json`. Every POST call needs it and this way you set it once.

**Warning: The key belongs in the collection authentication, nowhere else**
Never put it in a page element, an Option Set, a custom state, a workflow input, or a database field. All of those are readable from the browser or from a database export. The collection name itself also ships in your client-side source, so keep the key out of that too.

Add the first call:

1. Click to add a call. **Call name** `GetDailyHoroscope`.
2. **Use as** `Data` for page bindings, or `Action` for workflows. The table below says which to pick.
3. **Method** `GET`.
4. **URL** `https://roxyapi.com/api/v2/astrology/horoscope/[sign]/daily`. Square brackets create a parameter row. Set the `sign` default to `aries`.
5. Click **Initialize call**. Bubble fires the request once, learns the response shape, and exposes every field to the dynamic data picker: `sign`, `date`, `overview`, `love`, `career`, `health`, `finance`, `advice`, `column`, `luckyNumber`, `luckyColor`, `moonSign`, `moonPhase`, `energyRating`.

| Use as | Where it appears | Best for |
|--------|------------------|----------|
| **Data** | Under "Get data from an external API" on any element | Horoscope panels, dream lookups, tarot displays |
| **Action** | In the workflow editor under Plugins | Form submits, generate-my-chart buttons, database writes |

**Warning: Initialize with sample data only**
Whatever you type into a parameter to initialize a call becomes part of the API schema, and that schema is embedded in your app source code. Initialize with a placeholder birth date, never the birth details of a real person. Once the call is initialized you can clear the value or tick **Allow blank**.

## Ship a daily horoscope page

One dropdown, one text element, one call.

1. Drop a **Dropdown** with the twelve zodiac signs as options.
2. Drop a **Text** element.
3. Click it, **Insert dynamic data**, **Get data from an external API**.
4. Pick **RoxyAPI, GetDailyHoroscope**.
5. Drag the dropdown value into the `sign` parameter.
6. Pick the field you want: `overview`, `luckyNumber`, `moonSign`, `energyRating`.

Preview the page, pick a sign, and the horoscope for today renders.

Add a `lang` parameter for one of ten languages (`en`, `tr`, `de`, `es`, `hi`, `pt`, `fr`, `ru`, `zh-Hans`, `zh-Hant`). Machine values such as `sign` stay English; the prose translates.

## Send birth data with a POST

Charts, panchang, dasha, compatibility and synastry all take a birth moment.


### API Connector body

1. Add a call. **Method** `POST`. **URL** `https://roxyapi.com/api/v2/astrology/natal-chart`.
2. **Body type** `JSON`. Paste:
   ```json
   {
     "date": "<date>",
     "time": "<time>",
     "latitude": <latitude>,
     "longitude": <longitude>,
     "timezone": "<timezone>"
   }
   ```
3. Set the parameter types: `date` text (`YYYY-MM-DD`), `time` text (`HH:MM:SS`), `latitude` number, `longitude` number, `timezone` text (an IANA name such as `America/New_York`). Leave latitude and longitude unquoted in the body so they are sent as numbers.
4. **Initialize call** with sample values.

All five fields are required. Optional `houseSystem` (`placidus` by default) and `nodeType` (`true` by default) can be added the same way.

### Import from cURL

Faster than typing it out. Grab any curl example from the [API reference](/api-reference) and paste it into the API Connector cURL import. Bubble maps the method, URL, headers and body for you. Then delete the `X-API-Key` header line from the imported call, because the collection authentication already sends it and a duplicate belongs to that one call rather than to the collection.

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


**Warning: Resolve the city first, never ask for coordinates**
No user knows their birth latitude. Add a second `Data` call on `https://roxyapi.com/api/v2/location/search?q=[q]` and bind it to a search input. It returns a `cities` array with `city`, `province`, `country`, `latitude`, `longitude` and `timezone` on each entry, so the user picks a place and you carry the three values forward. The `timezone` is an IANA name, which is what you want: the server resolves it to the correct offset for the birth date, so a summer birth and a winter birth are both right. A decimal offset such as `5.5` is accepted but knows nothing about daylight saving.

Hook the Action to a form submit and save the response as a new `Chart` Thing. The `planets` field is a list of objects with `name`, `sign`, `degree`, `house`, `isRetrograde` and `dignity`, so a Repeating Group over it renders the whole chart with no expressions.

## Cache what does not change

The API Connector does not cache. A horoscope is identical all day for one sign, so store it:

1. Create a `DailyHoroscope` data type with `sign`, `date`, `overview`, `luckyNumber` and whatever else you display.
2. Schedule a Backend Workflow once a day that loops the twelve signs and writes one Thing each.
3. Page elements read the Thing for today and the selected sign.

Your request usage then stays flat no matter how much traffic the page gets. The [caching guide](/docs/guides/caching) lists how long each kind of result stays valid.

## Gotchas


### New fields are not showing in the dynamic data picker
Bubble caches the response shape from the last successful **Initialize call**. Change the URL, a parameter, or the body and you have to initialize again. The same applies after you tick **Include errors in response**, which changes the response format.

### I get a 400 and cannot tell which field is wrong
A 400 carries `issues[]` listing every field problem at once, so read that array instead of guessing one field at a time. All errors come back as `{ error, code }`. Tick **Include errors in response & allow workflow actions to continue** on the call and you get the status code, message and body as a dynamic expression instead of a stopped workflow.

### Latitude comes through as text and the call fails
The value is quoted in the body template. Write `"latitude": <latitude>` without quotes and set the parameter type to number.

### I cannot find "Make the call directly in the browser"
That checkbox only appears when a call has no headers, all its parameters are private, and the collection has no shared headers or parameters. A RoxyAPI collection always carries an auth header, so the option never shows, which is the behaviour you want: the call runs on a Bubble server and the key never reaches the visitor.

### 429 on a busy page
You are through your monthly request allowance, usually because a page calls the API on every load. Cache into a Thing as above. See [authentication](/docs/authentication) for the quota headers on every response.

### I need the same endpoint in both a page and a workflow
Add it twice under the same collection with different names, one **Use as Data** and one **Use as Action**. The auth is shared, so there is nothing to configure twice.

## Pick the next endpoint

- **Domain guides**, for which endpoints to call and in what order: [Western Astrology](/docs/guides/astrology), [Vedic Astrology](/docs/guides/vedic-astrology), [KP Astrology](/docs/guides/kp), [Human Design](/docs/guides/human-design), [Forecast](/docs/guides/forecast), [Chinese Astrology](/docs/guides/chinese-astrology), [Feng Shui](/docs/guides/feng-shui), [Biorhythm](/docs/guides/biorhythm), [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), [Ayurveda](/docs/guides/ayurveda), [Kabbalah](/docs/guides/kabbalah), [Vastu](/docs/guides/vastu), [Mesoamerican Astrology](/docs/guides/mesoamerican-astrology).
- **Common in Bubble apps:** [`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 /astrology/compatibility-score`](/api-reference#tag/western-astrology/POST/astrology/compatibility-score), [`POST /vedic-astrology/birth-chart`](/api-reference#tag/vedic-astrology/POST/vedic-astrology/birth-chart), [`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), [`POST /numerology/chart`](/api-reference#tag/numerology/POST/numerology/chart), [`GET /dreams/symbols`](/api-reference#tag/dreams/GET/dreams/symbols).
- The [API reference](/api-reference) is the source of truth for every field on every response.
- The [SDK guide](/docs/sdk) is there when you outgrow no-code and want typed calls.

## FAQ

**Can I build an astrology app on Bubble without code?**

Yes. Install the API Connector, create one collection with `Private key in header` authentication and the key name `X-API-Key`, then add one call per endpoint. Bubble learns each response shape when you initialize the call, after which every field is bindable dynamic data. One key reaches all 18 domains.

**Where do I put an API key in the Bubble API Connector?**

In the collection Authentication, set to `Private key in header`, with **Key name** `X-API-Key` and your key in **Private key**. Every call in that collection inherits it. Never store it in a page element, Option Set, custom state, workflow input or database field, because all of those are reachable from the browser or from an export.

**Should a RoxyAPI call be Use as Data or Use as Action?**

Data if a page element displays the result, because Data calls appear under "Get data from an external API". Action if a workflow triggers it, for example a form submit that saves a chart to your database. You can add the same endpoint twice with different names if you need both.

**How do I let a Bubble user enter a birth city instead of coordinates?**

Add a Data call on `GET /location/search?q=[q]`, bind it to a search input, and let the user pick from the `cities` array it returns. Each entry carries `latitude`, `longitude` and an IANA `timezone`, which you then pass into the chart call. Daylight saving for the birth date is handled for you.

**Is my API key visible to Bubble app visitors?**

No, as long as it is in the collection Authentication. Calls with a header run on a Bubble server, and the browser-side option is not even offered for a collection that carries shared headers. What does leak is anything you type into a page element, a custom state or a parameter you initialize with, so keep the key and any real personal data out of those.
