Integrate Astrology API with Java Spring Boot

Integrate Astrology API with Java Spring Boot
Published: March 13, 2026 | By Vedika Intelligence | Reading time: 15 minutes

Java remains the language of choice for enterprise backends — and for good reason. Type safety, mature tooling, the Spring ecosystem, and decades of production-proven patterns make it the dominant platform for fintech, matrimony platforms, media companies, and enterprise SaaS. If you're building an astrology feature into an existing Java application, or starting a new astrology microservice from scratch, this guide shows you exactly how to integrate Vedika API using Spring Boot 3.x best practices.

By the end of this tutorial, you'll have a fully functional Spring Boot service with WebClient reactive calls, DTOs, service layer, Spring Cache for cost optimization, @ControllerAdvice error handling, and @Async parallel processing — all production-ready.

What You'll Build: A Spring Boot 3.x microservice that exposes astrology REST endpoints — birth chart, daily horoscope, AI-powered query, and compatibility matching — backed by Vedika API. Includes caching, error handling, async processing, and an application.yml configuration pattern suitable for enterprise deployment.

Why Vedika API for Java Enterprise Applications?

140+ Endpoints

Birth charts, dashas, transits, muhurta, numerology, AI chatbot — all via a single REST API with JSON payloads.

AI-Powered Queries

Natural language endpoint: ask "When is the best time to launch my product?" and get a chart-verified answer.

Swiss Ephemeris Precision

Astronomical-grade planetary calculations. Not a lookup table — real ephemeris math for every request.

$12/month Starting

Starter at $12, Pro at $60, Business at $120, Enterprise at $240. Pay only for what you use with wallet-based billing.

Prerequisites

Step 1: Project Setup with Spring Initializr

Generate a new project at start.spring.io with the following selections, or use this pom.xml:

<!-- pom.xml --> <project> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.3</version> </parent> <groupId>io.vedika</groupId> <artifactId>astrology-service</artifactId> <version>1.0.0</version> <dependencies> <!-- Spring Web + WebClient --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <!-- Spring MVC controllers --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Caffeine cache --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> </dependency> <!-- Validation --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <!-- Lombok for cleaner DTOs --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies> </project>

Step 2: Application Configuration

Configure your API key and base URL in application.yml. Never hardcode secrets — use environment variables or Spring Cloud Config in production:

# src/main/resources/application.yml vedika: api: base-url: https://api.vedika.io key: ${VEDIKA_API_KEY} # Set via environment variable spring: cache: type: caffeine caffeine: spec: maximumSize=500,expireAfterWrite=3600s task: execution: pool: core-size: 4 max-size: 16 queue-capacity: 100 thread-name-prefix: vedika-async-

Step 3: DTO Classes

Define strongly-typed DTOs for request and response payloads. Spring Boot's Jackson auto-maps JSON automatically:

// src/main/java/io/vedika/dto/BirthDetailsDto.java package io.vedika.dto; import jakarta.validation.constraints.*; import lombok.*; import com.fasterxml.jackson.annotation.JsonProperty; @Data @Builder @NoArgsConstructor @AllArgsConstructor public class BirthDetailsDto { @NotBlank private String datetime; // ISO-8601: "1990-06-15T14:30:00" @NotNull private Double latitude; @NotNull private Double longitude; @NotBlank private String timezone; // "+05:30" } // src/main/java/io/vedika/dto/AstrologyQueryDto.java @Data @Builder @NoArgsConstructor @AllArgsConstructor public class AstrologyQueryDto { @NotBlank private String question; @Valid private BirthDetailsDto birthDetails; } // src/main/java/io/vedika/dto/AstrologyResponseDto.java @Data @JsonIgnoreProperties(ignoreUnknown = true) public class AstrologyResponseDto { private String answer; private String system; private Map<String, Object> birthChart; private Map<String, Object> usage; }

Step 4: WebClient Configuration Bean

Configure a singleton WebClient bean with proper timeouts, base URL, and the API key header pre-loaded:

// src/main/java/io/vedika/config/VedikaClientConfig.java package io.vedika.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.*; import org.springframework.web.reactive.function.client.*; import io.netty.channel.ChannelOption; import reactor.netty.http.client.HttpClient; import java.time.Duration; @Configuration @EnableCaching @EnableAsync public class VedikaClientConfig { @Value("${vedika.api.key}") private String apiKey; @Value("${vedika.api.base-url}") private String baseUrl; @Bean public WebClient vedikaWebClient() { HttpClient httpClient = HttpClient.create() .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000) .responseTimeout(Duration.ofSeconds(60)); return WebClient.builder() .baseUrl(baseUrl) .clientConnector(new ReactorClientHttpConnector(httpClient)) .defaultHeader("x-api-key", apiKey) .defaultHeader("Content-Type", "application/json") .defaultHeader("Accept", "application/json") .build(); } }

Step 5: Astrology Service Layer

Build the service class that wraps all Vedika API interactions. Use @Cacheable on deterministic endpoints — the same birth data always produces the same chart, so caching eliminates redundant API costs:

// src/main/java/io/vedika/service/AstrologyService.java package io.vedika.service; import io.vedika.dto.*; import org.springframework.cache.annotation.Cacheable; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.client.WebClient; import java.util.concurrent.CompletableFuture; @Service public class AstrologyService { private final WebClient webClient; public AstrologyService(WebClient vedikaWebClient) { this.webClient = vedikaWebClient; } /** * Get AI-powered answer for any astrology question. * Birth chart data is verified against Swiss Ephemeris before the AI response. */ @Cacheable(value = "birthCharts", key = "#request.birthDetails.datetime + #request.birthDetails.latitude + #request.birthDetails.longitude") public AstrologyResponseDto query(AstrologyQueryDto request) { return webClient.post() .uri("/api/vedika/chat") .bodyValue(request) .retrieve() .onStatus(status -> status.is4xxClientError(), resp -> resp.bodyToMono(String.class) .map(body -> new VedikaApiException("Client error: " + body))) .onStatus(status -> status.is5xxServerError(), resp -> resp.bodyToMono(String.class) .map(body -> new VedikaApiException("Server error: " + body))) .bodyToMono(AstrologyResponseDto.class) .block(); } /** * Get birth chart — fully deterministic, aggressive caching is safe. */ @Cacheable(value = "birthCharts", key = "'chart:' + #details.datetime + ':' + #details.latitude + ':' + #details.longitude") public AstrologyResponseDto getBirthChart(BirthDetailsDto details) { AstrologyQueryDto request = AstrologyQueryDto.builder() .question("Generate my complete Vedic birth chart with planetary positions, houses, and active yogas.") .birthDetails(details) .build(); return query(request); } /** * Async batch method — generate horoscopes for multiple users in parallel. * Useful for overnight batch jobs sending daily horoscope notifications. */ @Async("taskExecutor") public CompletableFuture<AstrologyResponseDto> getDailyHoroscopeAsync( BirthDetailsDto details, String zodiacSign) { AstrologyQueryDto request = AstrologyQueryDto.builder() .question("What is today's detailed horoscope for " + zodiacSign + "? Include career, relationships, health, and finance predictions.") .birthDetails(details) .build(); AstrologyResponseDto result = query(request); return CompletableFuture.completedFuture(result); } /** * Kundali compatibility — no caching (pair-specific, less repetitive). */ public AstrologyResponseDto getCompatibility( BirthDetailsDto person1, BirthDetailsDto person2) { AstrologyQueryDto request = AstrologyQueryDto.builder() .question("Calculate the kundali matching score (Guna Milan) between these two birth charts. " + "Provide the Ashtakoot score and compatibility assessment.") .birthDetails(person1) .build(); return query(request); } }

Step 6: REST Controller

Expose clean REST endpoints that your frontend or other microservices can call. The controller stays thin — all business logic lives in the service layer:

// src/main/java/io/vedika/controller/AstrologyController.java package io.vedika.controller; import io.vedika.dto.*; import io.vedika.service.AstrologyService; import jakarta.validation.Valid; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.concurrent.CompletableFuture; @RestController @RequestMapping("/api/astrology") public class AstrologyController { private final AstrologyService astrologyService; public AstrologyController(AstrologyService astrologyService) { this.astrologyService = astrologyService; } /** POST /api/astrology/query — Ask any astrology question in natural language */ @PostMapping("/query") public ResponseEntity<AstrologyResponseDto> query( @Valid @RequestBody AstrologyQueryDto request) { AstrologyResponseDto response = astrologyService.query(request); return ResponseEntity.ok(response); } /** POST /api/astrology/birth-chart — Get complete Vedic birth chart */ @PostMapping("/birth-chart") public ResponseEntity<AstrologyResponseDto> birthChart( @Valid @RequestBody BirthDetailsDto details) { AstrologyResponseDto response = astrologyService.getBirthChart(details); return ResponseEntity.ok(response); } /** POST /api/astrology/daily-horoscope — Async daily prediction */ @PostMapping("/daily-horoscope") public CompletableFuture<ResponseEntity<AstrologyResponseDto>> dailyHoroscope( @Valid @RequestBody BirthDetailsDto details, @RequestParam String zodiacSign) { return astrologyService .getDailyHoroscopeAsync(details, zodiacSign) .thenApply(ResponseEntity::ok); } /** POST /api/astrology/compatibility — Kundali matching */ @PostMapping("/compatibility") public ResponseEntity<AstrologyResponseDto> compatibility( @Valid @RequestBody CompatibilityRequestDto request) { AstrologyResponseDto response = astrologyService .getCompatibility(request.getPerson1(), request.getPerson2()); return ResponseEntity.ok(response); } }

Step 7: Global Error Handling with @ControllerAdvice

Centralize error handling so your controllers stay clean. Map Vedika API errors to appropriate HTTP status codes with descriptive messages:

// src/main/java/io/vedika/exception/GlobalExceptionHandler.java package io.vedika.exception; import org.springframework.http.*; import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.MethodArgumentNotValidException; import java.util.Map; @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(VedikaApiException.class) public ResponseEntity<Map<String, Object>> handleVedikaError(VedikaApiException ex) { HttpStatus status = ex.getStatusCode() == 402 ? HttpStatus.PAYMENT_REQUIRED : ex.getStatusCode() == 429 ? HttpStatus.TOO_MANY_REQUESTS : HttpStatus.BAD_GATEWAY; return ResponseEntity.status(status).body(Map.of( "error", ex.getMessage(), "code", status.value(), "source", "vedika-api" )); } @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<Map<String, Object>> handleValidation( MethodArgumentNotValidException ex) { String message = ex.getBindingResult() .getFieldErrors() .stream() .map(fe -> fe.getField() + ": " + fe.getDefaultMessage()) .findFirst() .orElse("Validation failed"); return ResponseEntity.badRequest().body(Map.of( "error", message, "code", 400 )); } @ExceptionHandler(Exception.class) public ResponseEntity<Map<String, Object>> handleGeneral(Exception ex) { return ResponseEntity.internalServerError().body(Map.of( "error", "An unexpected error occurred", "code", 500 )); } }

Ready to Build Enterprise Astrology Features?

Try the FREE Sandbox — 65 mock endpoints, no auth required. Production plans from $12/month.

Explore the Sandbox

Step 8: Scheduled Batch Processing

Use Spring's @Scheduled and @Async together to generate daily horoscopes for all users in parallel overnight — dramatically reducing your peak-hour API usage:

// src/main/java/io/vedika/scheduler/DailyHoroscopeScheduler.java package io.vedika.scheduler; import io.vedika.service.*; import org.springframework.scheduling.annotation.*; import org.springframework.stereotype.Component; import java.util.*; import java.util.concurrent.CompletableFuture; @Component public class DailyHoroscopeScheduler { private final AstrologyService astrologyService; private final UserService userService; public DailyHoroscopeScheduler(AstrologyService astrologyService, UserService userService) { this.astrologyService = astrologyService; this.userService = userService; } // Runs daily at 1:00 AM IST (UTC+5:30 = 19:30 UTC previous day) @Scheduled(cron = "0 30 19 * * *", zone = "UTC") public void generateDailyHoroscopes() { List<UserProfile> users = userService.getAllActiveUsers(); // Fan out async calls — up to 16 concurrent (pool max-size in application.yml) List<CompletableFuture<?>> futures = users.stream() .map(user -> astrologyService.getDailyHoroscopeAsync( user.getBirthDetails(), user.getZodiacSign())) .toList(); CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join(); System.out.println("Generated horoscopes for " + users.size() + " users"); } }

Step 9: Integration Test

Write a Spring Boot integration test to verify your service wires correctly before deploying. Use @SpringBootTest with a mock WebClient for CI environments:

// src/test/java/io/vedika/service/AstrologyServiceTest.java @SpringBootTest class AstrologyServiceTest { @Autowired private AstrologyService astrologyService; @Test void testBirthChartQuery() { BirthDetailsDto details = BirthDetailsDto.builder() .datetime("1990-06-15T14:30:00") .latitude(28.6139) .longitude(77.2090) .timezone("+05:30") .build(); AstrologyResponseDto response = astrologyService.getBirthChart(details); assertNotNull(response); assertNotNull(response.getAnswer()); assertFalse(response.getAnswer().isEmpty()); } @Test void testCachingReducesApiCalls() { BirthDetailsDto details = BirthDetailsDto.builder() .datetime("1985-03-21T08:00:00") .latitude(19.0760).longitude(72.8777) .timezone("+05:30") .build(); // First call hits API, second call hits cache AstrologyResponseDto first = astrologyService.getBirthChart(details); AstrologyResponseDto second = astrologyService.getBirthChart(details); assertEquals(first.getAnswer(), second.getAnswer()); // Verify only 1 API call was made (check cache hit metrics) } }

Sample curl Request

Test your running Spring Boot service directly:

# Test birth chart endpoint curl -X POST http://localhost:8080/api/astrology/birth-chart \ -H "Content-Type: application/json" \ -d '{ "datetime": "1990-06-15T14:30:00", "latitude": 28.6139, "longitude": 77.2090, "timezone": "+05:30" }' # Test natural language query curl -X POST http://localhost:8080/api/astrology/query \ -H "Content-Type: application/json" \ -d '{ "question": "What are my career prospects for 2026?", "birthDetails": { "datetime": "1990-06-15T14:30:00", "latitude": 28.6139, "longitude": 77.2090, "timezone": "+05:30" } }'

Why Choose Vedika API Over Competitors?

AI Chatbot Built-In

No other astrology API includes a natural language AI engine. One endpoint handles any question — no complex orchestration required.

140+ Calculations

Birth charts, Vimshottari dasha, ashtakavarga, muhurta, numerology, compatibility, transit analysis — far more than the 50-80 endpoints competitors provide.

MCP Server Support

The world's first astrology MCP server. Your AI agents can call Vedika directly through the Model Context Protocol — no REST wrappers needed.

30 Languages

Support for Hindi, Tamil, Telugu, Bengali, Gujarati, Marathi, and 24 more languages for truly global astrology applications.

Swiss Ephemeris

Astronomical-grade ephemeris calculations — not lookup tables. Same engine used by professional Vedic astrology software worldwide.

Enterprise-Ready

99.9% uptime SLA, dual-region deployment (US + Mumbai), rate limiting, secure API key auth, and comprehensive monitoring.

Pricing

Vedika API uses wallet-based billing starting at $12/month — pay only for queries you actually run:

All plans include access to all 140+ endpoints, the AI chatbot, and 30-language support. Compare plans in detail.

Conclusion

Integrating Vedika API into a Java Spring Boot application follows standard enterprise patterns — no exotic dependencies or special adapters required. The key architectural decisions made in this guide:

Next steps:

  1. Get your API key at vedika.io/dashboard
  2. Try the free sandbox — 65 mock endpoints, no auth, no cost
  3. Review the full API reference for all 140+ endpoints
  4. Add Resilience4j circuit breaker for production-grade fault tolerance
  5. Set up Spring Actuator metrics to monitor cache hit rates and API latency

About Vedika Intelligence: Vedika is the only B2B astrology API with an AI-powered chatbot engine, serving production enterprise applications worldwide. The Vedika Intelligence Engine enables natural language astrology queries with Swiss Ephemeris-verified precision, supporting both Vedic and Western astrology across 30 languages.

Try the #1 Astrology API for Java Developers

140+ endpoints, Swiss Ephemeris precision, AI chatbot, 30 languages. Free sandbox included — no credit card required.

Try Free Sandbox View Documentation