Skip to content

Embeddable Widgets

Create and manage embeddable widgets for your website. A widget is a ready-made UI component for one astrology feature: a natal chart form, a moon calendar, a daily horoscope picker. You configure it in the dashboard or through this API, and place it on any page with one script tag.

Two APIs, two keys

  • The management API (/api/widgets) creates and configures widgets. It uses your normal API key.
  • The widget API (/api/widget-api) is what the SDK calls from the visitor's browser. It uses the widget's own key, which is safe to put in a page because it is scoped to that one widget.

Looking for the no-code guide? See Adding Widgets to Your Website.


Widget Types

Which widget types you can create depends on the modules on your organization. GET /api/widgets/options lists the ones available to you.

TypeDescriptionRequired modules
natalBirth data form with chart, positions and aspectsmodule:natal
synastryTwo birth data forms, synastry chart and cross aspectsmodule:natal, module:synastry
transitBirth data plus a transit moment, bi-wheel chartmodule:natal, module:transits
compositeTwo birth data forms, composite chartmodule:natal, module:composite
moonphaseCurrent moon phase with illuminationmodule:moon
daily-horoscopeSign picker with today's horoscopemodule:daily-report
numerologyName and birth date form with core numbersmodule:numerology
compatibilityTwo people, numerology compatibility scoremodule:numerology, module:compatibility
moon-calendarMonthly calendar with phases, moonrise and moonsetmodule:moon

Widget Management

All management endpoints are JSON:API and use the widget resource type.

List Widgets

bash
curl "https://api.astroapi.cloud/api/widgets" \
  -H "X-Api-Key: your-api-key"

Get Widget

bash
curl "https://api.astroapi.cloud/api/widgets/wgt_abc123" \
  -H "X-Api-Key: your-api-key"

Create Widget

bash
curl -X POST "https://api.astroapi.cloud/api/widgets" \
  -H "X-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "data": {
      "type": "widget",
      "attributes": {
        "name": "My Natal Chart Widget",
        "widgetType": "natal",
        "allowedDomains": ["example.com", "www.example.com"],
        "customization": {
          "language": "en",
          "layout": { "variant": "card" },
          "colors": {
            "primary": "#5b2d8e",
            "background": "#ffffff",
            "text": "#1a1a1a"
          },
          "widgetOptions": {
            "showAspects": true,
            "showPoints": true,
            "showHouses": true,
            "chartSize": "medium",
            "theme": "auto"
          }
        }
      }
    }
  }'

The response of a create is the only time the full widget API key is returned (apiKey). Store it, or regenerate it later; every other response only carries apiKeyPrefix.

json
{
    "data": {
        "type": "widget",
        "id": "wgt_abc123",
        "attributes": {
            "name": "My Natal Chart Widget",
            "widgetType": "natal",
            "customization": { "...": "as sent, merged with defaults when served" },
            "allowedDomains": ["example.com", "www.example.com"],
            "enabled": true,
            "createdAt": "2026-06-15T12:00:00.000Z",
            "updatedAt": "2026-06-15T12:00:00.000Z",
            "apiKey": "wk_live_...",
            "apiKeyPrefix": "wk_live_abc1"
        },
        "relationships": {
            "organization": { "data": { "type": "organization", "id": "org_..." } }
        }
    }
}

Update Widget

PATCH accepts any subset of name, enabled, allowedDomains and customization. Customization is replaced as a whole, so send the full object.

bash
curl -X PATCH "https://api.astroapi.cloud/api/widgets/wgt_abc123" \
  -H "X-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "data": {
      "type": "widget",
      "id": "wgt_abc123",
      "attributes": {
        "name": "Updated Widget Name",
        "customization": { "language": "nl" }
      }
    }
  }'

Delete Widget

bash
curl -X DELETE "https://api.astroapi.cloud/api/widgets/wgt_abc123" \
  -H "X-Api-Key: your-api-key"

Regenerate the widget API key

bash
curl -X POST "https://api.astroapi.cloud/api/widgets/wgt_abc123/regenerate-key" \
  -H "X-Api-Key: your-api-key"

Returns the widget with a fresh apiKey. Update the embed code on your site with the new key; the widget ID stays the same.


Available Widget Options

bash
curl "https://api.astroapi.cloud/api/widgets/options" \
  -H "X-Api-Key: your-api-key"
json
{
    "data": {
        "type": "widget-options",
        "id": "org_...",
        "attributes": {
            "plan": "Gold",
            "organizationModules": ["module:natal", "module:moon"],
            "availableWidgetTypes": ["natal", "moonphase", "moon-calendar"],
            "features": {
                "canRemoveBranding": false,
                "canUseCustomLogo": false,
                "canUseCustomCss": false,
                "maxDomains": 5
            },
            "allWidgetTypes": [
                {
                    "id": "natal",
                    "name": "Natal Chart",
                    "requiredModules": ["module:natal"],
                    "displayOptions": { "showChartSize": true, "showAspects": true, "showPoints": true }
                }
            ]
        }
    }
}

Plan Features

FeatureDescription
canRemoveBrandingbranding.showPoweredBy may be false
canUseCustomLogobranding.logoUrl and branding.companyName may be set
canUseCustomCsscustomCss is served to the widget
maxDomainsMaximum number of allowedDomains per widget, or "unlimited"

Customization Object

Every field is optional; what you leave out is filled from the defaults below when the widget is served. Colors are CSS color strings, sizes are numbers in pixels.

json
{
    "colors": {
        "primary": "#6366f1",
        "secondary": "#8b5cf6",
        "background": "#ffffff",
        "surface": "#f8fafc",
        "text": "#1e293b",
        "textSecondary": "#64748b",
        "border": "#e2e8f0",
        "error": "#ef4444",
        "success": "#22c55e",
        "accent": "#f59e0b"
    },
    "fonts": {
        "family": "Inter, system-ui, sans-serif",
        "sizeBase": 16,
        "sizeHeading": 24,
        "sizeSmall": 12,
        "weightNormal": 400,
        "weightBold": 600
    },
    "borders": { "radius": 8, "width": 1, "style": "solid" },
    "spacing": { "padding": 16, "margin": 16 },
    "shadows": { "preset": "sm", "custom": null },
    "layout": { "variant": "card" },
    "interaction": {
        "tooltipEnabled": true,
        "animationsEnabled": true,
        "clickThroughEnabled": false,
        "clickThroughUrl": null
    },
    "chartSettings": {},
    "labels": {},
    "language": "en",
    "branding": { "showPoweredBy": true, "logoUrl": null, "companyName": null },
    "customCss": null,
    "widgetOptions": {
        "showAspects": true,
        "showPoints": true,
        "showHouses": true,
        "chartSize": "medium",
        "theme": "light"
    },
    "numerologyOptions": {
        "showLifePath": true,
        "showExpression": true,
        "showSoulUrge": true,
        "showPersonality": true,
        "showBirthday": true,
        "showPersonalCycles": true
    },
    "dailyHoroscopeOptions": { "autoRefresh": false },
    "moonCalendarOptions": {
        "showMoonrise": true,
        "showMoonset": true,
        "showIllumination": true,
        "showPhaseEmoji": true,
        "highlightFullMoon": true,
        "highlightNewMoon": true
    },
    "compatibilityOptions": {
        "showScore": true,
        "showDescription": true,
        "showLifePaths": true
    }
}

Customization Fields

FieldTypeDescription
colors.*stringTen CSS colors, applied as CSS variables on the widget
fonts.familystringCSS font-family value
fonts.sizeBase / sizeHeading / sizeSmallnumberFont sizes in pixels
fonts.weightNormal / weightBoldnumberFont weights
borders.radius / widthnumberPixels; used by inputs, buttons and the card layout
borders.stylestringsolid, dashed, dotted or none
spacing.padding / marginnumberPixels; the card and compact layouts use padding
shadows.presetstringnone, sm, md, lg or xl (card layout)
shadows.customstring | nullA CSS box-shadow that overrides the preset
layout.variantstringSee Layout variants
interaction.tooltipEnabledbooleanHover tooltips on planet rows, aspect rows and calendar days
interaction.animationsEnabledbooleanEntry animations; always off for visitors who prefer reduced motion
interaction.clickThroughEnabledbooleanMakes the rendered chart a link to clickThroughUrl
interaction.clickThroughUrlstring | nullOpens in a new tab
chartSettingsobjectA partial chart theme merged over the default chart theme: colors per sign, point and aspect, stroke widths, showDegrees, showRetrograde and so on
labelsobjectOverrides for any label key; see Languages and labels
languagestringOne of the 13 supported language codes
branding.showPoweredBybooleanRequires canRemoveBranding to set false
branding.logoUrl / companyNamestring | nullRequire canUseCustomLogo
customCssstring | nullInjected into the page for the widget; requires canUseCustomCss
widgetOptions.showAspects / showPointsbooleanShow the aspect and position tables under a chart
widgetOptions.showHousesbooleanShow house numbers on the chart
widgetOptions.chartSizestring | numbersmall (300), medium (450), large (600) or a pixel width
widgetOptions.themestringlight, dark, cosmic, custom or auto
numerologyOptions.*booleanWhich numbers the numerology widget shows
dailyHoroscopeOptions.autoRefreshbooleanReserved
moonCalendarOptions.*booleanWhich details a calendar day shows and which phases are highlighted
compatibilityOptions.*booleanScore ring, description and life path numbers

Layout variants

ValueDescription
cardBordered surface with the configured radius, padding and shadow (default)
compactHalf the padding and slightly smaller type, for sidebars
fullEdge to edge, vertical padding only
minimalNo frame at all; inherits everything from the page

Themes

light, dark and cosmic are fixed palettes for surfaces and borders. auto uses the light palette and switches to the dark one when the visitor's system prefers dark. custom sets nothing and relies on your colors. In every theme the ten colors you set win over the palette.

Languages and labels

The SDK ships labels for en, nl, de, fr, es, es-419, it, pt, pt-BR, tr, ru, ja and zh-CN. Region variants fall back to their base language for anything they do not override. labels overrides individual strings on top of the chosen language, for example:

json
{ "language": "nl", "labels": { "calculateButton": "Bereken mijn horoscoop" } }

The language can also be set per page: data-lang="de" on the script tag, or ?lang=de in the page URL, both take precedence over the stored language.


Embedding a Widget

The SDK is served from https://widgets.astroapi.cloud/sdk.js. The dashboard's Embed tab produces both snippets below with your IDs filled in.

Auto-initialize

html
<script
  src="https://widgets.astroapi.cloud/sdk.js"
  data-widget-id="wgt_abc123"
  data-api-key="your-widget-api-key"
  data-api-url="https://api.astroapi.cloud"
></script>
<div id="astro-widget-wgt_abc123"></div>

Optional attributes: data-container="#my-element" to render somewhere other than the default div, and data-lang="nl" to override the language.

Programmatic

html
<script src="https://widgets.astroapi.cloud/sdk.js"></script>
<div id="my-widget"></div>
<script>
  AstroWidget.create({
    widgetId: "wgt_abc123",
    apiKey: "your-widget-api-key",
    apiBaseUrl: "https://api.astroapi.cloud",
    container: "#my-widget",
    language: "nl",
    defaultValues: {
      dateTime: "1990-06-15T14:30:00",
      latitude: 52.3676,
      longitude: 4.9041,
      timezone: "Europe/Amsterdam",
      placeName: "Amsterdam"
    },
    onLoad: () => console.log("Widget loaded"),
    onResult: (result) => console.log("Result", result),
    onError: (err) => console.error(err)
  }).then((widget) => {
    // widget.type, widget.getResult(), widget.setBirthData(), widget.calculate(), widget.destroy()
  });
</script>

defaultValues.dateTime is interpreted as local time in timezone; the form shows it exactly as given.

Instance API

MemberDescription
id, typeWidget ID and widget type
getResult()The latest result, whether the visitor calculated it or calculate() did
setBirthData(data)Birth data used by calculate()
calculate()Runs the calculation from script and shows the result. Supported for natal, transit (at the current moment), moonphase and moon-calendar (current month); the other types take their input from the visitor and reject with an error
destroy()Unmounts the widget

onResult fires for every result the widget shows, for all widget types. AstroWidget.version reports the SDK build.

Domains

allowedDomains restricts where the widget API key works, checked against the Origin of the browser request. Subdomain wildcards (*.example.com) are supported and www. is treated as the bare domain. With an empty list the key works on any domain, so fill it in before you publish the embed code.


Widget API

These are the endpoints the SDK calls on behalf of a visitor. They are listed so you can build your own front end against a widget; the SDK is the reference client.

Authentication is the widget API key in X-Api-Key. The dashboard preview uses a session instead.

EndpointBodyWidget type
GET /api/widget-api/config/:widgetIdany; public, returns widgetType and the merged customization
POST /api/widget-api/natal/:widgetId{ birthData }natal
POST /api/widget-api/synastry/:widgetId{ person1, person2 }synastry
POST /api/widget-api/transit/:widgetId{ birthData, transitDateTime, transitTimezone? }transit
POST /api/widget-api/composite/:widgetId{ person1, person2 }composite
POST /api/widget-api/moonphase/:widgetId{ date?, latitude? }moonphase
POST /api/widget-api/daily-horoscope/:widgetId{ zodiacSign, date? }daily-horoscope
POST /api/widget-api/numerology/:widgetId{ fullName, birthYear, birthMonth, birthDay }numerology
POST /api/widget-api/compatibility/:widgetId{ person1, person2 } (name and birth date parts)compatibility
POST /api/widget-api/moon-calendar/:widgetId{ year, month, latitude?, longitude?, timezone? }moon-calendar
GET /api/widget-api/geocoding/search/:widgetId?q=&limit=&lang=any; place search for the birth data form

birthData, person1 and person2 for the chart widgets are { dateTime, latitude, longitude, timezone, placeName? } with dateTime as local time (1990-06-15T14:30:00) in timezone. Calling an endpoint for a widget of another type returns 400; a disabled widget returns 403; a request from a domain outside allowedDomains returns 403 DOMAIN_NOT_ALLOWED.


Next Steps

AstroAPI Documentation