Widgets guide

A widget is one dependency-free web component. Add the script and a tag, and it draws a chart or daily reading. Its calls go through a route on your own server, so your key never reaches the page.

1. Try it in the gallery

The widget gallery lets you pick a widget, theme and language and copy the tag. It runs on vedika.io, so it needs no setup.

2. Put it on your page

The Vedika API answers browser calls only from vedika.io, so a widget on your own site sends its calls to your server, and your server forwards them. This one file is that server and the page. It needs no key: the widget reads the sandbox, which charges nothing.

Node.js

// Node.js 18 or later. Save as server.mjs and run: node server.mjs
import http from 'node:http';

const page = `<!doctype html>
<html lang="en">
  <head><meta charset="utf-8"></head>
  <body>
    <script src="https://vedika.io/js/embed/vedika-widget.js"></script>
    <vedika-astro-widget type="daily-horoscope" sign="aries" base-url="/vedika"></vedika-astro-widget>
  </body>
</html>`;

// Only the daily horoscope routes are forwarded, so the key cannot be used for anything else.
const ROUTE = /^\/(sandbox|v2)\/daily\/horoscope\/[A-Za-z]{3,12}$/;

http.createServer(async (req, res) => {
  const url = new URL(req.url, 'http://localhost'); // resolves dot segments before we check the path
  if (!url.pathname.startsWith('/vedika/')) {
    res.writeHead(200, { 'Content-Type': 'text/html' });
    return res.end(page);
  }
  const path = url.pathname.slice('/vedika'.length);
  if (req.method !== 'GET' || !ROUTE.test(path)) {
    res.writeHead(404);
    return res.end();
  }
  // The sandbox needs no key. Set VEDIKA_API_KEY to call the paid route.
  const key = process.env.VEDIKA_API_KEY;
  const upstream = await fetch('https://api.vedika.io' + path + url.search, {
    redirect: 'manual',
    headers: key ? { Authorization: 'Bearer ' + key } : {},
  });
  res.writeHead(upstream.status, { 'Content-Type': upstream.headers.get('content-type') || 'application/json' });
  res.end(Buffer.from(await upstream.arrayBuffer()));
}).listen(8080, () => console.log('http://localhost:8080'));

Python

# Python 3.9 or later, standard library only. Save as server.py and run: python3 server.py
import os
import re
import urllib.error
import urllib.parse
import urllib.request
from http.server import BaseHTTPRequestHandler, HTTPServer

PAGE = b"""<!doctype html>
<html lang="en">
  <head><meta charset="utf-8"></head>
  <body>
    <script src="https://vedika.io/js/embed/vedika-widget.js"></script>
    <vedika-astro-widget type="daily-horoscope" sign="aries" base-url="/vedika"></vedika-astro-widget>
  </body>
</html>"""

# Only the daily horoscope routes are forwarded, so the key cannot be used for anything else.
ROUTE = re.compile(r"^/(sandbox|v2)/daily/horoscope/[A-Za-z]{3,12}$")


class NoRedirect(urllib.request.HTTPRedirectHandler):
    def redirect_request(self, *args, **kwargs):
        return None  # never send the key to another address


OPENER = urllib.request.build_opener(NoRedirect)


class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        parts = urllib.parse.urlsplit(self.path)
        if not parts.path.startswith("/vedika/"):
            return self.reply(200, "text/html", PAGE)
        path = parts.path[len("/vedika"):]
        if not ROUTE.match(path):
            return self.reply(404, "text/plain", b"")
        # The sandbox needs no key. Set VEDIKA_API_KEY to call the paid route.
        headers = {}
        if os.environ.get("VEDIKA_API_KEY"):
            headers["Authorization"] = "Bearer " + os.environ["VEDIKA_API_KEY"]
        url = "https://api.vedika.io" + path + ("?" + parts.query if parts.query else "")
        try:
            upstream = OPENER.open(urllib.request.Request(url, headers=headers), timeout=10)
        except urllib.error.HTTPError as error:
            upstream = error
        except ValueError:
            return self.reply(400, "text/plain", b"")
        except OSError:
            return self.reply(502, "text/plain", b"")
        self.reply(upstream.status, upstream.headers.get("Content-Type", "application/json"), upstream.read())

    def reply(self, status, content_type, body):
        self.send_response(status)
        self.send_header("Content-Type", content_type)
        self.end_headers()
        self.wfile.write(body)


HTTPServer(("", 8080), Handler).serve_forever()

Run it and open http://localhost:8080. Both versions forward only the daily horoscope routes, so a key set later cannot be used for anything else.

The data the widget reads

The widget calls GET /sandbox/daily/horoscope/{sign} and draws the data block. You can call the same route yourself. The sandbox answers with a fixed sample and a billing block that shows charged: 0.

curl

curl --fail-with-body --silent --show-error \
  "https://api.vedika.io/sandbox/daily/horoscope/aries"

JavaScript

// Node.js 18 or later.
const response = await fetch('https://api.vedika.io/sandbox/daily/horoscope/aries', {
  method: 'GET',
});
const result = await response.json();
if (!response.ok) throw new Error(result.error?.message ?? response.status);
console.log(result.data);

Python

# Python 3, standard library only.
import json, os, urllib.request

request = urllib.request.Request(
    'https://api.vedika.io/sandbox/daily/horoscope/aries',
    method='GET',
    headers={},
)
with urllib.request.urlopen(request) as response:
    print(json.load(response)['data'])

3. Go to production

Set VEDIKA_API_KEY in the environment of the same server and change the tag to mode="live". The widget then calls GET /v2/daily/horoscope/{sign} through your server, which adds the key. A call costs $0.016. Never put the key in the page.

<vedika-astro-widget type="daily-horoscope" sign="aries" mode="live" base-url="/vedika"></vedika-astro-widget>

Add your own checks on who may load the page and how often the route may be called before you publish it, because each call is charged to your wallet.

Widgets

Set type to one of these 31 widgets. window.VedikaWidgets.types() lists them in the page. Each reads its own route, so check the price of that route in the reference before you go live.

birth-chart, nakshatra, dasha, mangal-dosha, kaal-sarp-dosha, shadbala, ashtakavarga, panchang, houses, kp-chart, kp-cusps, kp-planets, horoscope, daily-horoscope, guna-milan, chara-dasha, numerology, tarot, iching, runes, angel-number, dreams, chinese-zodiac, crystals, human-design, biorhythm, chakra, vitality, ayurveda, health-timing, career

Attributes

AttributeWhat it does
typeWhich widget to draw. See the list below. Default birth-chart.
themeOne of light, dark, auto. auto follows the visitor's colour scheme. Default light.
skinOne of clean, watercolor, crayon (plain is accepted for clean). Default clean.
chart-styleFor chart widgets: north, south, western, wheel, kp. Default north.
langLanguage code: en, hi, bn, te, ta, gu, kn, ml, mr, pa, od, ur. Default en.
signZodiac sign for horoscope widgets, for example aries. Default aries.
base-urlWhere the widget sends its calls. Set it to a route on your own server, as in this guide.
modeSet live together with base-url to call the paid routes without a key in the page. Your server adds the key. Leave it out for the sandbox.
api-keyA key in the page source. Do not use it in a page you publish; use base-url and your server instead.
dob, tob, lat, lon, tz, place, nameBirth details for chart widgets. The sandbox ignores them and returns one demo chart.

Errors and limits

In the sandbox each caller gets 100 calls a day (UTC) and short per-minute and per-hour limits; the widget shows a plain message when one is reached. In production the widget shows a message for an empty wallet (402) or a key Vedika did not accept (401 or 403). Look at the status your server returns before you change the page. See rate limits.

Next steps