RoxyAPI

Menu

Vedic Astrology API Integration Guide for Developers

15 min read
By Rajesh Kumar
Vedic AstrologyAPI IntegrationBirth Chart APIKundli APIAstrology Development

Complete guide to integrating Vedic astrology APIs in your application. Includes authentication, birth charts, panchang, dasha periods, and compatibility matching.

Vedic Astrology API Integration Guide for Developers

Integrating Vedic astrology calculations into your application requires accurate astronomical computations, proper timezone handling, and comprehensive astrological interpretations. This guide shows you how to integrate the RoxyAPI Vedic Astrology API into your Node.js, Python, or React applications with production-ready patterns.

By the end of this tutorial, you will have a complete API client with error handling, caching, and retry logic for all major Vedic astrology endpoints.

What We Will Build

Our integration covers all essential Vedic astrology features:

  1. Birth Chart Generation - Complete D1 Rashi chart with planetary positions
  2. Panchang Calculations - Tithi, Nakshatra, Yoga, Karana for any date
  3. Dasha Periods - Vimshottari Mahadasha, Antardasha, Pratyantardasha
  4. Compatibility Matching - Ashtakoot gun milan scoring
  5. Dosha Detection - Manglik and Kalsarpa dosha checking
  6. Navamsa Chart - D9 divisional chart for marriage analysis

Prerequisites

  • Node.js 18+ or Python 3.9+
  • RoxyAPI account with API key (sign up here)
  • Basic understanding of Vedic astrology concepts

Step 1: Authentication Setup

Node.js/TypeScript

// lib/vedic-api-client.ts
import fetch from 'node-fetch';

interface VedicAPIConfig {
  apiKey: string;
  baseURL?: string;
  timeout?: number;
}

class VedicAstrologyAPI {
  private apiKey: string;
  private baseURL: string;
  private timeout: number;

  constructor(config: VedicAPIConfig) {
    this.apiKey = config.apiKey;
    this.baseURL = config.baseURL || 'http://localhost:3001/api/v2/vedic-astrology';
    this.timeout = config.timeout || 10000;
  }

  private async request<T>(
    endpoint: string,
    method: 'GET' | 'POST' = 'POST',
    body?: any
  ): Promise<T> {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), this.timeout);

    try {
      const response = await fetch(`${this.baseURL}${endpoint}`, {
        method,
        headers: {
          'Content-Type': 'application/json',
          'X-API-Key': this.apiKey,
        },
        body: body ? JSON.stringify(body) : undefined,
        signal: controller.signal,
      });

      clearTimeout(timeoutId);

      if (!response.ok) {
        const error = await response.json().catch(() => ({}));
        throw new VedicAPIError(
          error.message || `API error: ${response.statusText}`,
          response.status,
          error
        );
      }

      return await response.json();
    } catch (error) {
      clearTimeout(timeoutId);
      if (error instanceof VedicAPIError) throw error;
      throw new VedicAPIError('Network error', 0, error);
    }
  }
}

class VedicAPIError extends Error {
  constructor(
    message: string,
    public statusCode: number,
    public details?: any
  ) {
    super(message);
    this.name = 'VedicAPIError';
  }
}

export { VedicAstrologyAPI, VedicAPIError };

Python

# vedic_api_client.py
import requests
from typing import Dict, Any, Optional
import json

class VedicAPIError(Exception):
    def __init__(self, message: str, status_code: int = 0, details: Any = None):
        super().__init__(message)
        self.status_code = status_code
        self.details = details

class VedicAstrologyAPI:
    def __init__(
        self,
        api_key: str,
        base_url: str = "http://localhost:3001/api/v2/vedic-astrology",
        timeout: int = 10
    ):
        self.api_key = api_key
        self.base_url = base_url
        self.timeout = timeout
        self.session = requests.Session()
        self.session.headers.update({
            'Content-Type': 'application/json',
            'X-API-Key': api_key
        })

    def _request(
        self,
        endpoint: str,
        method: str = 'POST',
        data: Optional[Dict[str, Any]] = None
    ) -> Dict[str, Any]:
        url = f"{self.base_url}{endpoint}"
        
        try:
            if method == 'POST':
                response = self.session.post(
                    url,
                    json=data,
                    timeout=self.timeout
                )
            else:
                response = self.session.get(url, timeout=self.timeout)
            
            response.raise_for_status()
            return response.json()
            
        except requests.exceptions.HTTPError as e:
            try:
                error_data = e.response.json()
                message = error_data.get('message', str(e))
            except:
                message = str(e)
            raise VedicAPIError(message, e.response.status_code, error_data)
        except requests.exceptions.RequestException as e:
            raise VedicAPIError(f"Network error: {str(e)}", 0)

Step 2: Birth Chart Endpoint

The birth chart endpoint returns a complete D1 Rashi chart with all planetary positions, nakshatras, and house descriptions.

TypeScript Implementation

interface BirthChartParams {
  year: number;
  month: number;    // 1-12
  day: number;      // 1-31
  hour: number;     // 0-23.99
  latitude: number;
  longitude: number;
}

interface Planet {
  graha: string;
  rashi: string;
  longitude: number;
  nakshatra: {
    name: string;
    pada: number;
    key: string;
    ratio: number;
  };
  isRetrograde: boolean;
}

interface BirthChartResponse {
  rashis: {
    [rashiName: string]: {
      rashi: string;
      planets: string[];
    };
  };
  meta: {
    [grahaName: string]: Planet;
  };
  houses: Array<{
    house: number;
    rashi: string;
    lord: string;
    description: string;
  }>;
}

class VedicAstrologyAPI {
  // ... previous code ...

  async getBirthChart(params: BirthChartParams): Promise<BirthChartResponse> {
    return this.request<BirthChartResponse>('/birth-chart', 'POST', params);
  }
}

// Usage example
const api = new VedicAstrologyAPI({
  apiKey: 'your_api_key_here',
});

const birthChart = await api.getBirthChart({
  year: 1990,
  month: 7,
  day: 15,
  hour: 14.5, // 14:30
  latitude: 28.6139,
  longitude: 77.209,
});

console.log('Lagna:', birthChart.meta.Lagna.rashi);
console.log('Sun:', birthChart.meta.Sun.rashi);
console.log('Moon Nakshatra:', birthChart.meta.Moon.nakshatra.name);

Python Implementation

from typing import TypedDict, List

class BirthChartParams(TypedDict):
    year: int
    month: int
    day: int
    hour: float
    latitude: float
    longitude: float

class VedicAstrologyAPI:
    # ... previous code ...
    
    def get_birth_chart(self, params: BirthChartParams) -> dict:
        return self._request('/birth-chart', 'POST', params)

# Usage
api = VedicAstrologyAPI(api_key='your_api_key_here')

birth_chart = api.get_birth_chart({
    'year': 1990,
    'month': 7,
    'day': 15,
    'hour': 14.5,
    'latitude': 28.6139,
    'longitude': 77.209
})

print(f"Lagna: {birth_chart['meta']['Lagna']['rashi']}")
print(f"Sun: {birth_chart['meta']['Sun']['rashi']}")
print(f"Moon Nakshatra: {birth_chart['meta']['Moon']['nakshatra']['name']}")

Example Response

{
  "rashis": {
    "aries": {
      "rashi": "Aries",
      "planets": ["Mars"]
    },
    "gemini": {
      "rashi": "Gemini",
      "planets": ["Sun", "Jupiter", "Venus"]
    },
    "cancer": {
      "rashi": "Cancer",
      "planets": ["Mercury"]
    },
    "leo": {
      "rashi": "Leo",
      "planets": ["Rahu"]
    },
    "sagittarius": {
      "rashi": "Sagittarius",
      "planets": ["Saturn"]
    },
    "aquarius": {
      "rashi": "Aquarius",
      "planets": ["Lagna", "Ketu"]
    },
    "pisces": {
      "rashi": "Pisces",
      "planets": ["Moon"]
    }
  },
  "meta": {
    "Lagna": {
      "graha": "Lagna",
      "rashi": "Aquarius",
      "longitude": 301.46,
      "nakshatra": {
        "name": "Dhanishta",
        "pada": 3,
        "key": "dhanishta",
        "ratio": 0.543
      },
      "isRetrograde": false
    },
    "Sun": {
      "graha": "Sun",
      "rashi": "Gemini",
      "longitude": 88.92,
      "nakshatra": {
        "name": "Punarvasu",
        "pada": 3,
        "key": "punarvasu",
        "ratio": 0.218
      },
      "isRetrograde": false
    },
    "Moon": {
      "graha": "Moon",
      "rashi": "Pisces",
      "longitude": 357.79,
      "nakshatra": {
        "name": "Revati",
        "pada": 4,
        "key": "revati",
        "ratio": 0.947
      },
      "isRetrograde": true
    }
  },
  "houses": [
    {
      "house": 1,
      "rashi": "Aquarius",
      "lord": "Saturn",
      "description": "Self, personality, physical body, general health"
    },
    {
      "house": 2,
      "rashi": "Pisces",
      "lord": "Jupiter",
      "description": "Wealth, family, speech, food, early education"
    }
  ]
}

Step 3: Panchang Endpoint

Calculate Tithi, Nakshatra, Yoga, and Karana for any date and location.

Implementation

interface PanchangParams {
  year: number;
  month: number;
  day: number;
  hour: number;
  latitude: number;
  longitude: number;
}

interface PanchangResponse {
  tithi: {
    number: number;
    name: string;
    paksha: string;
    completion: number;
    deity: string;
    element: string;
    characteristics: string;
  };
  nakshatra: {
    number: number;
    name: string;
    lord: string;
    deity: string;
    symbol: string;
    characteristics: string;
  };
  yoga: {
    number: number;
    name: string;
    completion: number;
    characteristics: string;
  };
  karana: {
    number: number;
    name: string;
    type: string;
    completion: number;
    characteristics: string;
  };
  sunLongitude: number;
  moonLongitude: number;
}

class VedicAstrologyAPI {
  // ... previous code ...

  async getPanchang(params: PanchangParams): Promise<PanchangResponse> {
    return this.request<PanchangResponse>('/panchang/basic', 'POST', params);
  }
}

// Usage
const panchang = await api.getPanchang({
  year: 2026,
  month: 7,
  day: 15,
  hour: 14.5,
  latitude: 28.6139,
  longitude: 77.209,
});

console.log('Tithi:', panchang.tithi.name);
console.log('Nakshatra:', panchang.nakshatra.name);
console.log('Yoga:', panchang.yoga.name);
console.log('Karana:', panchang.karana.name);

Example Response

{
  "tithi": {
    "number": 2,
    "name": "Dvītiyā",
    "paksha": "Shukla Paksha",
    "completion": 38.94,
    "deity": "Vidhāṭṛ",
    "element": "Earth",
    "characteristics": "Good for agriculture, ceremonies"
  },
  "nakshatra": {
    "number": 8,
    "name": "Pushya",
    "lord": "Saturn",
    "deity": "Brihaspati",
    "symbol": "Cow's Udder",
    "characteristics": "Most auspicious, disciplined, nurturing, protectors"
  },
  "yoga": {
    "number": 15,
    "name": "Vajra",
    "completion": 58.91,
    "characteristics": "Power Burst - wealthy, lascivious, changeable, forceful"
  },
  "karana": {
    "number": 3,
    "name": "Kaulav",
    "type": "char",
    "completion": 77.88,
    "characteristics": "Very friendly, talents like love and caring"
  },
  "sunLongitude": 88.924,
  "moonLongitude": 105.597
}

Step 4: Dasha Periods Endpoint

Get current Vimshottari Mahadasha, Antardasha, and Pratyantardasha.

Implementation

interface DashaParams {
  year: number;
  month: number;
  day: number;
  hour: number;
  latitude: number;
  longitude: number;
}

interface DashaPeriod {
  planet: string;
  startDate: string;
  endDate: string;
  durationYears: number;
  remainingYears: number;
  remainingMonths: number;
  remainingDays: number;
}

interface DashaResponse {
  birthMoonNakshatra: {
    name: string;
    lord: string;
  };
  mahadasha: DashaPeriod;
  antardasha: DashaPeriod;
  pratyantardasha: DashaPeriod;
}

class VedicAstrologyAPI {
  // ... previous code ...

  async getCurrentDasha(params: DashaParams): Promise<DashaResponse> {
    return this.request<DashaResponse>('/dasha/current', 'POST', params);
  }
}

// Usage
const dasha = await api.getCurrentDasha({
  year: 1990,
  month: 7,
  day: 15,
  hour: 14.5,
  latitude: 28.6139,
  longitude: 77.209,
});

console.log('Current Mahadasha:', dasha.mahadasha.planet);
console.log('Period:', dasha.mahadasha.startDate, 'to', dasha.mahadasha.endDate);
console.log('Remaining:', dasha.mahadasha.remainingYears, 'years');

Example Response

{
  "birthMoonNakshatra": {
    "name": "Ashwini",
    "lord": "Ketu"
  },
  "mahadasha": {
    "planet": "Moon",
    "startDate": "2023-01-15T00:00:00Z",
    "endDate": "2033-01-15T00:00:00Z",
    "durationYears": 10,
    "remainingYears": 6,
    "remainingMonths": 11,
    "remainingDays": 24
  },
  "antardasha": {
    "planet": "Jupiter",
    "startDate": "2025-12-15T00:00:00Z",
    "endDate": "2027-04-15T00:00:00Z",
    "durationYears": 1.33,
    "remainingYears": 1,
    "remainingMonths": 2,
    "remainingDays": 10
  },
  "pratyantardasha": {
    "planet": "Jupiter",
    "startDate": "2025-12-15T00:00:00Z",
    "endDate": "2026-02-20T00:00:00Z",
    "durationYears": 0.178,
    "remainingYears": 0,
    "remainingMonths": 1,
    "remainingDays": 12
  }
}

Step 5: Compatibility Matching

Calculate Ashtakoot gun milan compatibility between two people.

Implementation

interface CompatibilityParams {
  person1: BirthChartParams;
  person2: BirthChartParams;
}

interface CompatibilityBreakdown {
  category: string;
  score: number;
  description: string;
}

interface CompatibilityResponse {
  total: number;
  maxScore: number;
  percentage: number;
  isCompatible: boolean;
  breakdown: CompatibilityBreakdown[];
}

class VedicAstrologyAPI {
  // ... previous code ...

  async calculateCompatibility(
    params: CompatibilityParams
  ): Promise<CompatibilityResponse> {
    return this.request<CompatibilityResponse>('/compatibility', 'POST', params);
  }
}

// Usage
const compatibility = await api.calculateCompatibility({
  person1: {
    year: 1990,
    month: 7,
    day: 15,
    hour: 14.5,
    latitude: 28.6139,
    longitude: 77.209,
  },
  person2: {
    year: 1992,
    month: 3,
    day: 20,
    hour: 10.0,
    latitude: 19.076,
    longitude: 72.8777,
  },
});

console.log(`Compatibility: ${compatibility.total}/${compatibility.maxScore}`);
console.log(`Percentage: ${compatibility.percentage}%`);
console.log('Rating:', compatibility.isCompatible ? 'Compatible' : 'Not Compatible');

Example Response

{
  "total": 18.5,
  "maxScore": 36,
  "percentage": 51.39,
  "isCompatible": true,
  "breakdown": [
    {
      "category": "Nakshatra (Varna)",
      "score": 0,
      "description": "Spiritual compatibility"
    },
    {
      "category": "Gana",
      "score": 0,
      "description": "Temperament match"
    },
    {
      "category": "Yoni",
      "score": 0,
      "description": "Physical/sexual compatibility"
    },
    {
      "category": "Rashi Lord",
      "score": 3,
      "description": "Mutual affection"
    },
    {
      "category": "Vasya",
      "score": 1,
      "description": "Magnetic control"
    },
    {
      "category": "Tara",
      "score": 1.5,
      "description": "Birth star compatibility"
    },
    {
      "category": "Nadi",
      "score": 8,
      "description": "Health and progeny"
    },
    {
      "category": "Bhakoot",
      "score": 5,
      "description": "Love and prosperity"
    }
  ]
}

Step 6: Error Handling

Implement robust error handling with retries:

class VedicAstrologyAPI {
  // ... previous code ...

  async requestWithRetry<T>(
    endpoint: string,
    method: 'GET' | 'POST',
    body?: any,
    maxRetries = 3
  ): Promise<T> {
    let lastError: Error;

    for (let attempt = 0; attempt < maxRetries; attempt++) {
      try {
        return await this.request<T>(endpoint, method, body);
      } catch (error) {
        lastError = error as Error;

        // Don't retry on client errors (4xx)
        if (error instanceof VedicAPIError && error.statusCode >= 400 && error.statusCode < 500) {
          throw error;
        }

        // Wait before retrying (exponential backoff)
        if (attempt < maxRetries - 1) {
          const delay = Math.pow(2, attempt) * 1000;
          await new Promise((resolve) => setTimeout(resolve, delay));
        }
      }
    }

    throw lastError!;
  }
}

Python Error Handling

import time

class VedicAstrologyAPI:
    # ... previous code ...
    
    def _request_with_retry(
        self,
        endpoint: str,
        method: str = 'POST',
        data: Optional[Dict[str, Any]] = None,
        max_retries: int = 3
    ) -> Dict[str, Any]:
        last_error = None
        
        for attempt in range(max_retries):
            try:
                return self._request(endpoint, method, data)
            except VedicAPIError as e:
                last_error = e
                
                # Don't retry client errors
                if 400 <= e.status_code < 500:
                    raise
                
                # Wait before retrying (exponential backoff)
                if attempt < max_retries - 1:
                    delay = 2 ** attempt
                    time.sleep(delay)
        
        raise last_error

Step 7: Caching Strategy

Implement intelligent caching to reduce API calls:

import { createClient } from 'redis';

class CachedVedicAPI extends VedicAstrologyAPI {
  private redis: ReturnType<typeof createClient>;

  constructor(config: VedicAPIConfig) {
    super(config);
    this.redis = createClient({ url: process.env.REDIS_URL });
    this.redis.connect();
  }

  async getBirthChartCached(params: BirthChartParams): Promise<BirthChartResponse> {
    // Birth charts never change - cache indefinitely
    const cacheKey = `chart:${params.year}:${params.month}:${params.day}:${params.hour}:${params.latitude}:${params.longitude}`;
    
    const cached = await this.redis.get(cacheKey);
    if (cached) {
      return JSON.parse(cached);
    }

    const result = await this.getBirthChart(params);
    await this.redis.set(cacheKey, JSON.stringify(result), {
      EX: 86400 * 30, // 30 days
    });

    return result;
  }

  async getPanchangCached(params: PanchangParams): Promise<PanchangResponse> {
    // Panchang changes daily - shorter cache
    const cacheKey = `panchang:${params.year}:${params.month}:${params.day}:${params.latitude}:${params.longitude}`;
    
    const cached = await this.redis.get(cacheKey);
    if (cached) {
      return JSON.parse(cached);
    }

    const result = await this.getPanchang(params);
    await this.redis.set(cacheKey, JSON.stringify(result), {
      EX: 86400, // 1 day
    });

    return result;
  }
}

Step 8: Rate Limiting

Respect API rate limits with a queue:

class RateLimitedVedicAPI extends CachedVedicAPI {
  private queue: Array<() => Promise<any>> = [];
  private processing = false;
  private requestsPerSecond = 10;

  private async processQueue() {
    if (this.processing || this.queue.length === 0) return;

    this.processing = true;

    while (this.queue.length > 0) {
      const request = this.queue.shift();
      if (request) {
        await request();
        await new Promise((resolve) =>
          setTimeout(resolve, 1000 / this.requestsPerSecond)
        );
      }
    }

    this.processing = false;
  }

  protected async request<T>(
    endpoint: string,
    method: 'GET' | 'POST',
    body?: any
  ): Promise<T> {
    return new Promise((resolve, reject) => {
      this.queue.push(async () => {
        try {
          const result = await super.request<T>(endpoint, method, body);
          resolve(result);
        } catch (error) {
          reject(error);
        }
      });

      this.processQueue();
    });
  }
}

Step 9: Batch Operations

Process multiple charts efficiently:

class VedicAstrologyAPI {
  // ... previous code ...

  async getBirthChartsBatch(
    profiles: BirthChartParams[]
  ): Promise<BirthChartResponse[]> {
    // Process in parallel with concurrency limit
    const batchSize = 5;
    const results: BirthChartResponse[] = [];

    for (let i = 0; i < profiles.length; i += batchSize) {
      const batch = profiles.slice(i, i + batchSize);
      const batchResults = await Promise.all(
        batch.map((profile) => this.getBirthChart(profile))
      );
      results.push(...batchResults);
    }

    return results;
  }
}

Step 10: Complete Production Client

Here is the final production-ready client:

// vedic-api-client.ts
import fetch from 'node-fetch';
import { createClient } from 'redis';

export class VedicAstrologyClient {
  private apiKey: string;
  private baseURL: string;
  private timeout: number;
  private redis?: ReturnType<typeof createClient>;
  private maxRetries: number;

  constructor(config: {
    apiKey: string;
    baseURL?: string;
    timeout?: number;
    redisURL?: string;
    maxRetries?: number;
  }) {
    this.apiKey = config.apiKey;
    this.baseURL = config.baseURL || 'http://localhost:3001/api/v2/vedic-astrology';
    this.timeout = config.timeout || 10000;
    this.maxRetries = config.maxRetries || 3;

    if (config.redisURL) {
      this.redis = createClient({ url: config.redisURL });
      this.redis.connect();
    }
  }

  async getBirthChart(params: BirthChartParams): Promise<BirthChartResponse> {
    const cacheKey = `chart:${JSON.stringify(params)}`;
    return this.cachedRequest(cacheKey, '/birth-chart', params, 86400 * 30);
  }

  async getPanchang(params: PanchangParams): Promise<PanchangResponse> {
    const cacheKey = `panchang:${JSON.stringify(params)}`;
    return this.cachedRequest(cacheKey, '/panchang/basic', params, 86400);
  }

  async getCurrentDasha(params: DashaParams): Promise<DashaResponse> {
    return this.requestWithRetry('/dasha/current', 'POST', params);
  }

  async calculateCompatibility(
    params: CompatibilityParams
  ): Promise<CompatibilityResponse> {
    const cacheKey = `compat:${JSON.stringify(params)}`;
    return this.cachedRequest(cacheKey, '/compatibility', params, 86400 * 30);
  }

  private async cachedRequest<T>(
    cacheKey: string,
    endpoint: string,
    params: any,
    ttl: number
  ): Promise<T> {
    if (this.redis) {
      const cached = await this.redis.get(cacheKey);
      if (cached) return JSON.parse(cached);
    }

    const result = await this.requestWithRetry<T>(endpoint, 'POST', params);

    if (this.redis) {
      await this.redis.set(cacheKey, JSON.stringify(result), { EX: ttl });
    }

    return result;
  }

  private async requestWithRetry<T>(
    endpoint: string,
    method: 'GET' | 'POST',
    body?: any
  ): Promise<T> {
    let lastError: Error;

    for (let attempt = 0; attempt < this.maxRetries; attempt++) {
      try {
        return await this.request<T>(endpoint, method, body);
      } catch (error) {
        lastError = error as Error;

        if (error instanceof VedicAPIError && error.statusCode >= 400 && error.statusCode < 500) {
          throw error;
        }

        if (attempt < this.maxRetries - 1) {
          await new Promise((resolve) =>
            setTimeout(resolve, Math.pow(2, attempt) * 1000)
          );
        }
      }
    }

    throw lastError!;
  }

  private async request<T>(
    endpoint: string,
    method: 'GET' | 'POST',
    body?: any
  ): Promise<T> {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), this.timeout);

    try {
      const response = await fetch(`${this.baseURL}${endpoint}`, {
        method,
        headers: {
          'Content-Type': 'application/json',
          'X-API-Key': this.apiKey,
        },
        body: body ? JSON.stringify(body) : undefined,
        signal: controller.signal,
      });

      clearTimeout(timeoutId);

      if (!response.ok) {
        const error = await response.json().catch(() => ({}));
        throw new VedicAPIError(
          error.message || `API error: ${response.statusText}`,
          response.status,
          error
        );
      }

      return await response.json();
    } catch (error) {
      clearTimeout(timeoutId);
      if (error instanceof VedicAPIError) throw error;
      throw new VedicAPIError('Network error', 0, error);
    }
  }
}

class VedicAPIError extends Error {
  constructor(
    message: string,
    public statusCode: number,
    public details?: any
  ) {
    super(message);
    this.name = 'VedicAPIError';
  }
}

// Usage
const client = new VedicAstrologyClient({
  apiKey: process.env.VEDIC_API_KEY!,
  redisURL: process.env.REDIS_URL,
  maxRetries: 3,
});

const chart = await client.getBirthChart({
  year: 1990,
  month: 7,
  day: 15,
  hour: 14.5,
  latitude: 28.6139,
  longitude: 77.209,
});

Best Practices

1. Input Validation

Always validate user inputs before making API calls:

function validateBirthData(params: BirthChartParams): void {
  if (params.year < 1900 || params.year > 2100) {
    throw new Error('Year must be between 1900 and 2100');
  }
  if (params.month < 1 || params.month > 12) {
    throw new Error('Month must be between 1 and 12');
  }
  if (params.day < 1 || params.day > 31) {
    throw new Error('Day must be between 1 and 31');
  }
  if (params.hour < 0 || params.hour >= 24) {
    throw new Error('Hour must be between 0 and 23.99');
  }
  if (params.latitude < -90 || params.latitude > 90) {
    throw new Error('Latitude must be between -90 and 90');
  }
  if (params.longitude < -180 || params.longitude > 180) {
    throw new Error('Longitude must be between -180 and 180');
  }
}

2. Timezone Handling

Convert local time to UTC before sending to API:

import { DateTime } from 'luxon';

function convertToUTC(
  year: number,
  month: number,
  day: number,
  hour: number,
  timezone: string
): { year: number; month: number; day: number; hour: number } {
  const localTime = DateTime.fromObject(
    { year, month, day, hour: Math.floor(hour), minute: (hour % 1) * 60 },
    { zone: timezone }
  );

  const utcTime = localTime.toUTC();

  return {
    year: utcTime.year,
    month: utcTime.month,
    day: utcTime.day,
    hour: utcTime.hour + utcTime.minute / 60,
  };
}

3. Monitoring and Logging

Track API usage and errors:

class MonitoredVedicAPI extends VedicAstrologyClient {
  private logger: any; // Use your logging library

  protected async request<T>(
    endpoint: string,
    method: 'GET' | 'POST',
    body?: any
  ): Promise<T> {
    const startTime = Date.now();

    try {
      const result = await super.request<T>(endpoint, method, body);
      
      this.logger.info('API request successful', {
        endpoint,
        duration: Date.now() - startTime,
      });

      return result;
    } catch (error) {
      this.logger.error('API request failed', {
        endpoint,
        error: error instanceof Error ? error.message : 'Unknown error',
        duration: Date.now() - startTime,
      });

      throw error;
    }
  }
}

Conclusion

You now have a production-ready Vedic astrology API client with proper error handling, caching, rate limiting, and retry logic. The RoxyAPI Vedic Astrology API handles all complex astronomical calculations and astrological interpretations, allowing you to focus on building great user experiences.

Key features implemented:

  • Complete TypeScript and Python clients
  • Birth chart, panchang, dasha, and compatibility endpoints
  • Intelligent caching with Redis
  • Exponential backoff retry logic
  • Rate limiting and batch operations
  • Comprehensive error handling
  • Input validation and timezone conversion

Ready to integrate Vedic astrology into your app? Sign up for RoxyAPI and get your API key today. Full documentation at roxyapi.com/docs.