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
| Attribute | What it does |
|---|---|
type | Which widget to draw. See the list below. Default birth-chart. |
theme | One of light, dark, auto. auto follows the visitor's colour scheme. Default light. |
skin | One of clean, watercolor, crayon (plain is accepted for clean). Default clean. |
chart-style | For chart widgets: north, south, western, wheel, kp. Default north. |
lang | Language code: en, hi, bn, te, ta, gu, kn, ml, mr, pa, od, ur. Default en. |
sign | Zodiac sign for horoscope widgets, for example aries. Default aries. |
base-url | Where the widget sends its calls. Set it to a route on your own server, as in this guide. |
mode | Set 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-key | A 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, name | Birth 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
- Widget gallery: pick a widget, theme and language and copy the tag.
- API reference: every operation a widget reads.
- Reports guide: single-call analyses.