Dart SDK · GitHub install

Free Advanced Dart Vedic Astrology Library & API

The VedAstro Dart library gives you instant access to the world's most comprehensive Vedic astrology engine — planet positions, divisional charts, dasa periods, compatibility reports, and AI-powered features, all through a lightweight SDK.

VedAstro Dart Library - Vedic Astrology meets Dart

Whether you're building a horoscope app, a matchmaking platform, or a research tool, VedAstro's Dart library removes every barrier between you and professional-grade Vedic astrology calculations. No complicated setup. No local binaries. No astrology expertise required to get started. Just install the library, set your API key, and start computing — the heavy lifting runs on VedAstro's cloud engine.

What You're Getting

684

Hosted calculations for Vedic astrology applications

47

Ayanamsa systems — Lahiri, Raman, KP, Fagan-Bradley & 43 more

D1–D60

Divisional charts — full Parashari varga system coverage

AI-Powered

Horoscope predictions and classical-text search

Lightweight

Everything runs in the cloud — your app stays lightweight

Open Source

MIT licensed, community maintained, fully auditable on GitHub

Simple by Design

The VedAstro Dart library is a thin, elegant wrapper around the VedAstro REST API. You write Dart; the cloud does the calculation.

Dart Code → vedastro library → VedAstro Cloud Engine → Result
No heavy installation

The library itself is tiny — everything runs server-side

Always up to date

Calculation improvements roll out on the server automatically

Scales with you

From personal projects to production apps, same code works

Install the Dart SDK

Dart >=3.0.0 <4.0.0 and an internet connection

VedAstro Dart SDK installation
dependencies:
  vedastro:
    git:
      url: https://github.com/VedAstro/VedAstro.Dart.git

Add this Git dependency to pubspec.yaml, then run dart pub get. The package is not currently available on pub.dev. Calls are async; close the client when finished. Repository demos import support.dart, so run them from the cloned repository.

FreeAPIUser allows 5 requests per minute. Pace multi-call examples or use your subscription key. Locations take longitude before latitude.

Ready to Unlock 684 Calculations?

Get unlimited access for just $1/month — no rate limits, all features included

Buy Now - $1/month

Instant activation • Cancel anytime • 99.9% uptime guarantee

See It in Action

Start with one Sun-sign calculation using the free key.

import 'package:vedastro/vedastro.dart';

Future<void> main() async {
  final client = VedAstroClient(apiKey: 'FreeAPIUser');

  final birth = Time.of(
    '14:30 25/10/1992 +05:30',            // HH:mm dd/MM/yyyy +HH:mm
    GeoLocation.of('Mumbai', 72.8777, 19.0760), // name, longitude, latitude
  );

  final sun = await client.calculate().planetRasiD1Sign(PlanetName.sun, birth);
  print(Response.string(sun, 'Name'));                        // Libra
  print(Response.string(sun, ['DegreesIn', 'DegreeMinuteSecond']));

  client.close();
}

Save as main.dart in your Dart project and run dart run main.dart.

birth chart basics

Run from the cloned SDK repository; helper files are included there.

import 'package:vedastro/vedastro.dart';

import 'support.dart';

/// Reads a full birth chart: every planet's sign, degree and constellation, plus the
/// house cusps.
///
///     dart run example/birth_chart_basics.dart
Future<void> main() async {
  final client = demoClient();
  final birth = demoBirth();
  final pace = demoShouldPace(client);

  demoHeading('Planets');
  for (final planet in [
    PlanetName.sun,
    PlanetName.moon,
    PlanetName.mars,
    PlanetName.mercury,
    PlanetName.jupiter,
    PlanetName.venus,
    PlanetName.saturn,
  ]) {
    final result = await client.calculate().planetRasiD1Sign(planet, birth);
    demoField(
      planet.wireName,
      '${Response.string(result, 'Name')} '
      '${Response.string(result, ['DegreesIn', 'DegreeMinuteSecond'])}',
    );
    await demoPace(enabled: pace);
  }

  demoHeading('House signs');
  for (final house in [
    HouseName.house1,
    HouseName.house4,
    HouseName.house7,
    HouseName.house10
  ]) {
    final sign = await client.calculate().houseSignName(house, birth);
    demoField(house.wireName, sign);
    await demoPace(enabled: pace);
  }

  demoHeading('Constellations');
  for (final planet in [PlanetName.sun, PlanetName.moon]) {
    final star = await client.calculate().planetConstellation(planet, birth);
    demoField(planet.wireName, star);
    await demoPace(enabled: pace);
  }

  client.close();
}
View example source

daily panchanga

Run from the cloned SDK repository; helper files are included there.

import 'package:vedastro/vedastro.dart';

import 'support.dart';

/// The five limbs of the day, plus the inauspicious windows that depend on sunrise.
///
///     dart run example/daily_panchanga.dart
Future<void> main() async {
  final client = demoClient();
  final now = Time.now(GeoLocation.of('Kuala Lumpur', 101.6869, 3.1390));
  final pace = demoShouldPace(client);

  demoHeading('Panchanga for ${now.stdTime}');

  final tithi = await client.calculate().lunarDay(now);
  demoField('Tithi', Response.string(tithi, 'Name'));
  demoField('Paksha', Response.string(tithi, 'Paksha'));
  demoField('Phase', Response.string(tithi, 'Phase'));
  await demoPace(enabled: pace);

  final yoga = await client.calculate().nithyaYoga(now);
  demoField('Nithya yoga', Response.string(yoga, 'Name'));
  await demoPace(enabled: pace);

  final karana = await client.calculate().karana(now);
  demoField('Karana', karana);
  await demoPace(enabled: pace);

  demoHeading('Sun and Rahu');
  demoField('Sunrise', await client.calculate().sunriseTime(now));
  await demoPace(enabled: pace);
  demoField('Sunset', await client.calculate().sunsetTime(now));
  await demoPace(enabled: pace);
  demoField('Rahu kala', await client.calculate().rahuKala(now));

  client.close();
}
View example source

Stop Using the Free Tier — Go Pro for $1/month

Remove rate limits and get instant access to all 684 calculations

Buy API Key Now

684 Calculations Across Every Major Category

Category What's Included
Planets Positions, longitudes, strengths, aspects, conjunctions, retrograde status
Houses / Bhavas House signs, lords, bhava chart, all house data
Divisional Charts D1 through D60 — Navamsha, Drekkana, and all varga charts
Zodiac / Rasi Sign-based calculations, planet-in-sign queries
Dasas Vimshottari dasa periods with explicit starting rules and configurable depth
Events & Muhurtha Auspicious time finding, event predictions over any date range
Match / Compatibility Kuta scoring, full compatibility reports, BaZi integration, AI chat analysis
AI Features Birth time auto-fill from partial data, natural language horoscope search

Full method reference: vedastro.org/API.html

47 Ayanamsa Systems — Vedic, Western, and KP

Switch ayanamsa systems with SDK-specific settings

Lahiri

Modern Vedic standard

Raman

Classical Vedic system

Krishnamurti

KP System

Fagan-Bradley

Western sidereal

import 'package:vedastro/vedastro.dart';

import 'support.dart';

/// Ayanamsa is the difference between the tropical and the sidereal zodiac, and the
/// choice shifts every position by up to a degree. VedAstro supports 47 systems.
///
///     dart run example/custom_ayanamsa.dart
Future<void> main() async {
  final birth = demoBirth();
  final base = demoClient();

  demoHeading('The same moment, read four ways');
  for (final ayanamsa in [
    Ayanamsa.lahiri, // the Indian government standard
    Ayanamsa.raman,
    Ayanamsa.krishnamurti, // KP
    Ayanamsa.faganBradley, // Western sidereal
  ]) {
    // Drawn from the same environment, so the key and base URL are identical; only
    // the ayanamsa differs. The ayanamsa travels with each request, so it is safe to
    // keep several clients side by side.
    final scoped = VedAstroClient(
      apiKey: base.apiKey,
      baseUrl: base.baseUrl,
      silent: true,
      defaultAyanamsa: ayanamsa,
    );

    final sun =
        await scoped.calculate().planetRasiD1Sign(PlanetName.sun, birth);
    final ayanamsaValue = await scoped.calculate().ayanamsaDegree(birth);

    demoField(
      ayanamsa.wireName,
      '${Response.string(sun, 'Name')} '
      '${Response.string(sun, ['DegreesIn', 'DegreeMinuteSecond'])} '
      '| ayanamsa $ayanamsaValue',
    );

    scoped.close();
    // Four clients x two calls each outruns the free tier; a paid key would not need
    // this.
    await demoPace(enabled: demoShouldPace(base));
  }

  demoHeading('Which ayanamsa is in force');
  demoField('Client default', base.ayanamsa?.wireName ?? 'the API default');
  demoField('Ayanamsas available', Ayanamsa.values.length);

  base.close();
}

Run this example inside the cloned repository. View source.

Start Free. Scale When You're Ready.

Free

Rate-limited

'FreeAPIUser'

No signup required — ideal for exploration and development

Subscriber

Unlimited access

Buy Now - $1/month

High-speed access to all 684 calculations for production apps

final client = VedAstroClient(apiKey: 'your-key-here');

Ready-to-Run Examples

Clone the repository to run these examples with their included helpers. Expand an example to read and copy its source.

View source on GitHub
import 'package:vedastro/vedastro.dart';

import 'support.dart';

/// A batch of charts, paced for the free tier.
///
///     dart run example/batch_processing.dart
///
/// The point of this example is not the loop; it is what the loop does *not* do. The
/// SDK never retries and never throttles, so pacing is yours to own - and it has to
/// be central, because the per-key limit is shared across every process you run.
Future<void> main() async {
  final client = demoClient();
  final pace = demoShouldPace(client);

  // A small set of people to chart.
  final people = <String, Time>{
    'Asha': Time.of(
      '14:30 25/10/1992 +05:30',
      GeoLocation.of('Mumbai', 72.8777, 19.0760),
    ),
    'Bala': Time.of(
      '06:45 02/07/1988 +08:00',
      GeoLocation.of('Kuala Lumpur', 101.6869, 3.1390),
    ),
    'Chen': Time.of(
      '21:10 19/12/2000 +08:00',
      GeoLocation.of('Singapore', 103.8198, 1.3521),
    ),
  };

  demoHeading('Ascendants');
  for (final entry in people.entries) {
    final sign =
        await client.calculate().houseSignName(HouseName.house1, entry.value);
    demoField(entry.key, sign);
    // The free tier allows five calls a minute; a paid key does not need this.
    await demoPace(enabled: pace);
  }

  demoHeading('Suns');
  for (final entry in people.entries) {
    final sun =
        await client.calculate().planetRasiD1Sign(PlanetName.sun, entry.value);
    demoField(entry.key, Response.string(sun, 'Name'));
    await demoPace(enabled: pace);
  }

  // WHAT A PRODUCTION BATCH WOULD ADD ---------------------------------------
  //
  // - A CONCURRENCY LIMIT. Six calls at once is fine; six hundred is not. A
  //   fixed-size pool (or a package such as `pool`) keeps the pressure bounded.
  //
  // - A RETRY ON VedAstroException ONLY. That means the request never completed, so
  //   trying again is reasonable. An ApiException means the API rejected the call -
  //   repeating it verbatim will fail the same way.
  //
  // - CACHING KEYED BY THE CHART INPUT. `birth.stdTime` plus the location is the
  //   natural key; the same person is charted many times.
  //
  // - PROGRESS AND A FAILURE LIST, so one bad date does not abandon the whole run:
  //
  //     final failures = <String, Object>{};
  //     for (final entry in people.entries) {
  //       try { ... } catch (failure) { failures[entry.key] = failure; }
  //     }

  demoHeading('Done');
  // ignore: avoid_print
  print('   charted ${people.length} people, ${people.length * 2} calls');

  client.close();
}

View source on GitHub
import 'package:vedastro/vedastro.dart';

import 'support.dart';

/// Reads a full birth chart: every planet's sign, degree and constellation, plus the
/// house cusps.
///
///     dart run example/birth_chart_basics.dart
Future<void> main() async {
  final client = demoClient();
  final birth = demoBirth();
  final pace = demoShouldPace(client);

  demoHeading('Planets');
  for (final planet in [
    PlanetName.sun,
    PlanetName.moon,
    PlanetName.mars,
    PlanetName.mercury,
    PlanetName.jupiter,
    PlanetName.venus,
    PlanetName.saturn,
  ]) {
    final result = await client.calculate().planetRasiD1Sign(planet, birth);
    demoField(
      planet.wireName,
      '${Response.string(result, 'Name')} '
      '${Response.string(result, ['DegreesIn', 'DegreeMinuteSecond'])}',
    );
    await demoPace(enabled: pace);
  }

  demoHeading('House signs');
  for (final house in [
    HouseName.house1,
    HouseName.house4,
    HouseName.house7,
    HouseName.house10
  ]) {
    final sign = await client.calculate().houseSignName(house, birth);
    demoField(house.wireName, sign);
    await demoPace(enabled: pace);
  }

  demoHeading('Constellations');
  for (final planet in [PlanetName.sun, PlanetName.moon]) {
    final star = await client.calculate().planetConstellation(planet, birth);
    demoField(planet.wireName, star);
    await demoPace(enabled: pace);
  }

  client.close();
}

View source on GitHub
import 'package:vedastro/vedastro.dart';

import 'support.dart';

/// Every planet's sign right now, from one call.
///
///     dart run example/current_planets.dart
Future<void> main() async {
  final client = demoClient();

  // "Now" at the place you care about. The API needs a location, not just a time.
  final now = Time.now(GeoLocation.of('Kuala Lumpur', 101.6869, 3.1390));
  demoHeading('Now: ${now.stdTime}');

  final signs = await client.calculate().allPlanetRasiSigns(now);
  for (final entry in Response.list(signs, [])) {
    demoField(
      Response.string(entry, 'Planet'),
      Response.string(entry, 'Sign'),
    );
  }

  demoHeading('Full data for the Moon');
  final moon = await client.calculate().allPlanetData(PlanetName.moon, now);
  demoField('Sign', Response.string(moon, 'Sign'));
  demoField('Constellation', Response.string(moon, 'Constellation'));
  demoField(
      'Degrees', Response.string(moon, ['DegreesIn', 'DegreeMinuteSecond']));

  client.close();
}

View source on GitHub
import 'package:vedastro/vedastro.dart';

import 'support.dart';

/// Ayanamsa is the difference between the tropical and the sidereal zodiac, and the
/// choice shifts every position by up to a degree. VedAstro supports 47 systems.
///
///     dart run example/custom_ayanamsa.dart
Future<void> main() async {
  final birth = demoBirth();
  final base = demoClient();

  demoHeading('The same moment, read four ways');
  for (final ayanamsa in [
    Ayanamsa.lahiri, // the Indian government standard
    Ayanamsa.raman,
    Ayanamsa.krishnamurti, // KP
    Ayanamsa.faganBradley, // Western sidereal
  ]) {
    // Drawn from the same environment, so the key and base URL are identical; only
    // the ayanamsa differs. The ayanamsa travels with each request, so it is safe to
    // keep several clients side by side.
    final scoped = VedAstroClient(
      apiKey: base.apiKey,
      baseUrl: base.baseUrl,
      silent: true,
      defaultAyanamsa: ayanamsa,
    );

    final sun =
        await scoped.calculate().planetRasiD1Sign(PlanetName.sun, birth);
    final ayanamsaValue = await scoped.calculate().ayanamsaDegree(birth);

    demoField(
      ayanamsa.wireName,
      '${Response.string(sun, 'Name')} '
      '${Response.string(sun, ['DegreesIn', 'DegreeMinuteSecond'])} '
      '| ayanamsa $ayanamsaValue',
    );

    scoped.close();
    // Four clients x two calls each outruns the free tier; a paid key would not need
    // this.
    await demoPace(enabled: demoShouldPace(base));
  }

  demoHeading('Which ayanamsa is in force');
  demoField('Client default', base.ayanamsa?.wireName ?? 'the API default');
  demoField('Ayanamsas available', Ayanamsa.values.length);

  base.close();
}

View source on GitHub
import 'package:vedastro/vedastro.dart';

import 'support.dart';

/// The five limbs of the day, plus the inauspicious windows that depend on sunrise.
///
///     dart run example/daily_panchanga.dart
Future<void> main() async {
  final client = demoClient();
  final now = Time.now(GeoLocation.of('Kuala Lumpur', 101.6869, 3.1390));
  final pace = demoShouldPace(client);

  demoHeading('Panchanga for ${now.stdTime}');

  final tithi = await client.calculate().lunarDay(now);
  demoField('Tithi', Response.string(tithi, 'Name'));
  demoField('Paksha', Response.string(tithi, 'Paksha'));
  demoField('Phase', Response.string(tithi, 'Phase'));
  await demoPace(enabled: pace);

  final yoga = await client.calculate().nithyaYoga(now);
  demoField('Nithya yoga', Response.string(yoga, 'Name'));
  await demoPace(enabled: pace);

  final karana = await client.calculate().karana(now);
  demoField('Karana', karana);
  await demoPace(enabled: pace);

  demoHeading('Sun and Rahu');
  demoField('Sunrise', await client.calculate().sunriseTime(now));
  await demoPace(enabled: pace);
  demoField('Sunset', await client.calculate().sunsetTime(now));
  await demoPace(enabled: pace);
  demoField('Rahu kala', await client.calculate().rahuKala(now));

  client.close();
}

View source on GitHub
import 'package:vedastro/vedastro.dart';

import 'support.dart';

/// Divisional (varga) charts: the same moment read at finer resolutions.
///
///     dart run example/divisional_charts.dart
Future<void> main() async {
  final client = demoClient();
  final birth = demoBirth();
  final pace = demoShouldPace(client);

  demoHeading('Navamsha (D9)');
  for (final planet in [PlanetName.sun, PlanetName.moon, PlanetName.jupiter]) {
    final sign = await client.calculate().planetNavamshaD9Sign(planet, birth);
    demoField(planet.wireName, Response.string(sign, 'Name'));
    await demoPace(enabled: pace);
  }

  demoHeading('Every planet, one division at a time');
  demoField(
    'Navamsha D9',
    demoTruncate(await client.calculate().allPlanetNavamshaSign(birth), 90),
  );
  await demoPace(enabled: pace);
  demoField(
    'Dashamamsha D10',
    demoTruncate(await client.calculate().allPlanetDashamamshaSign(birth), 90),
  );
  await demoPace(enabled: pace);
  demoField(
    'Dwadashamsha D12',
    demoTruncate(await client.calculate().allPlanetDwadashamshaSign(birth), 90),
  );

  client.close();
}

View source on GitHub
import 'package:vedastro/vedastro.dart';

import 'support.dart';

/// Every way a call can fail, and what each one tells you.
///
///     dart run example/error_handling.dart
Future<void> main() async {
  final client = demoClient();
  final birth = demoBirth();

  // 1. Client-side validation fails before any network call, which is the cheapest
  //    possible failure: no request, no rate-limit cost, a message naming the field.
  demoHeading('1. Validation, before the network');
  for (final attempt in <void Function()>[
    () =>
        Time.of('25/10/1992 14:30', GeoLocation.of('Mumbai', 72.8777, 19.0760)),
    () => Time.of(
        '10:00 31/02/2020 +00:00', GeoLocation.of('Mumbai', 72.8777, 19.0760)),
    () => GeoLocation.of('Swapped', 19.0760, 72.8777),
  ]) {
    try {
      attempt();
      // ignore: avoid_print
      print('   ✗ accepted something it should have rejected');
    } on ArgumentError catch (failure) {
      // ignore: avoid_print
      print('   ✓ rejected: ${failure.message}');
    }
  }

  // 2. An ApiException means the API answered and rejected the call. Retrying the
  //    identical request will not help.
  demoHeading('2. The API rejected the call');
  try {
    // An intentionally unknown endpoint.
    await client.call('NoSuchCalculatorExists', parameters: {'time': birth});
  } on ApiException catch (failure) {
    demoField('Type', 'ApiException');
    demoField('Endpoint', failure.endpoint);
    demoField('HTTP status', failure.statusCode);
    demoField('Message', demoTruncate(failure.message, 100));
  }

  // 3. A VedAstroException means the request never completed - DNS, TLS, a reset
  //    connection. This is the one worth retrying.
  demoHeading('3. The request never completed');
  final unreachable = VedAstroClient(
    apiKey: client.apiKey,
    baseUrl: 'https://not-a-real-vedastro-host.test/api/Calculate',
    silent: true,
    timeout: const Duration(seconds: 5),
  );
  try {
    await unreachable.calculate().planetRasiD1Sign(PlanetName.sun, birth);
  } on VedAstroException catch (failure) {
    demoField('Type', failure.runtimeType.toString());
    demoField('Message', demoTruncate(failure.message, 100));
  } finally {
    unreachable.close();
  }

  // 4. The API key never appears in a message, so an exception is safe to log.
  demoHeading('4. The key is redacted');
  // ignore: avoid_print
  print('   configured key: ${client.apiKey.isEmpty ? "(none)" : "[present]"}');
  try {
    await client.call('NoSuchCalculatorExists', parameters: {'time': birth});
  } on ApiException catch (failure) {
    final leaks =
        client.apiKey.isNotEmpty && failure.toString().contains(client.apiKey);
    // ignore: avoid_print
    print('   ${leaks ? "✗ LEAKED" : "✓ not present in the message"}');
  }

  client.close();
}

View source on GitHub
import 'dart:io';

import 'package:vedastro/vedastro.dart';

import 'support.dart';

/// Runs the whole stack against the real API, through the real HTTP transport.
///
/// Unlike the test suite - which uses a fake transport and needs no network - this
/// spends real API calls, so it is deliberately not part of CI.
///
///     dart run example/live_check.dart
///
/// Set `VEDASTRO_API_KEY` to use a paid key; otherwise the free tier applies and the
/// checks pace themselves.
Future<void> main() async {
  final client = demoClient(silent: false);
  final birth = demoBirth();
  final pace = demoShouldPace(client);
  final transport =
      client.timeout == null ? 'stream (no deadline)' : 'with a deadline';

  // ignore: avoid_print
  print('VedAstro Dart SDK — live check against ${client.baseUrl}');
  // ignore: avoid_print
  print('transport: $transport\n');

  var failures = 0;

  Future<void> check(String label, Future<Object?> Function() action) async {
    try {
      final result = await action();
      // ignore: avoid_print
      print('  ✓ ${label.padRight(14)} $result');
    } catch (failure) {
      failures++;
      // ignore: avoid_print
      print('  ✗ ${label.padRight(14)} $failure');
    }
    await demoPace(enabled: pace);
  }

  await check('Sun sign', () async {
    final sun =
        await client.calculate().planetRasiD1Sign(PlanetName.sun, birth);
    return '${Response.string(sun, 'Name')} at '
        '${Response.string(sun, ['DegreesIn', 'DegreeMinuteSecond'])}';
  });

  await check('Ascendant', () async {
    final sign =
        await client.calculate().houseSignName(HouseName.house1, birth);
    return sign;
  });

  await check('Panchanga', () async {
    final tithi = await client.calculate().lunarDay(birth);
    return '${Response.string(tithi, 'Name')} (${Response.string(tithi, 'Paksha')})';
  });

  await check('Numerology', () async {
    final number = await client.calculate().birthNumber(birth);
    return 'birth number $number';
  });

  await check('Constellation', () async {
    final star =
        await client.calculate().planetConstellation(PlanetName.moon, birth);
    return star;
  });

  await check('RAG search', () async {
    final passages = await client
        .calculate()
        .searchSourceText('effects of Saturn in the 7th house');
    return '${Response.count(passages, [])} passage(s)';
  });

  client.close();

  // ignore: avoid_print
  print('');
  if (failures > 0) {
    // ignore: avoid_print
    print('$failures live check(s) failed.');
    exitCode = 1;
    return;
  }
  // ignore: avoid_print
  print('All live checks passed.');
}

View source on GitHub
import 'package:vedastro/vedastro.dart';

import 'support.dart';

/// Numerology: the numbers derived from a birth moment and a name.
///
///     dart run example/numerology.dart
Future<void> main() async {
  final client = demoClient();
  final birth = demoBirth();

  demoHeading('From the birth moment');
  demoField('Birth number', await client.calculate().birthNumber(birth));
  demoField('Destiny number', await client.calculate().destinyNumber(birth));

  demoHeading('From a name');
  final prediction =
      await client.calculate().nameNumberPrediction('Ada Lovelace');
  demoField(
      'Name number', Response.get(prediction, 'NameNumber') ?? prediction);
  demoField('Meaning', Response.string(prediction, 'Meaning'));

  client.close();
}

View source on GitHub
import 'package:vedastro/vedastro.dart';

import 'support.dart';

/// The smallest useful program: one client, one moment, one calculation.
///
///     dart run example/quick_start.dart
Future<void> main() async {
  final client = demoClient();
  final birth = demoBirth();

  demoHeading('Position of the Sun');
  final sun = await client.calculate().planetRasiD1Sign(PlanetName.sun, birth);
  demoField('Sign', Response.string(sun, 'Name'));
  demoField('Degrees in sign',
      Response.string(sun, ['DegreesIn', 'DegreeMinuteSecond']));

  demoHeading('Ascendant');
  final ascendant =
      await client.calculate().houseSignName(HouseName.house1, birth);
  demoField('Rising sign', ascendant);

  client.close();
}

View source on GitHub
import 'package:vedastro/vedastro.dart';

import 'support.dart';

/// Semantic search across classical Vedic texts, so an answer can be grounded in a
/// source rather than in a model's memory.
///
///     dart run example/rag_vedic_books.dart
Future<void> main() async {
  final client = demoClient();
  final pace = demoShouldPace(client);

  demoHeading('Which texts are indexed');
  final sources = await client.calculate().getAvailableSourceTexts();
  for (final source in Response.list(sources, [])) {
    // Each entry is a name and the number of chunks indexed for it.
    // ignore: avoid_print
    print('   - $source');
  }

  await demoPace(enabled: pace);

  const question = 'effects of Saturn in the seventh house';
  demoHeading('Searching: "$question"');

  final passages = await client.calculate().searchSourceText(question, topK: 3);
  for (final passage in Response.list(passages, [])) {
    demoField('Source', Response.string(passage, 'sourceName'));
    demoField('Page', Response.intValue(passage, 'pageNumber'));
    demoField('Score', Response.doubleValue(passage, 'score'));
    // ignore: avoid_print
    print('   ${demoTruncate(Response.string(passage, 'text'), 220)}\n');
  }

  client.close();
}

View source on GitHub
import 'dart:convert';
import 'dart:io';

import 'package:vedastro/vedastro.dart';

import 'support.dart';

/// How to use the SDK inside a long-running server.
///
/// This file is written to be **read** — the handler below is the shape you would
/// paste into a Shelf, Dart Frog or `HttpServer` app. Run it to see the same logic
/// print its answers instead of serving them:
///
///     dart run example/server_usage.dart
Future<void> main() async {
  // ONE CLIENT, CREATED ONCE -------------------------------------------------
  //
  // The client is immutable and holds no per-request state, so build it when the
  // isolate starts and share it. Building one per request would throw away the
  // connection pool and add a TLS handshake to every call.
  //
  // `silent: true` matters on a server: the start-up banner would otherwise be
  // written into a response body.
  final vedAstro = VedAstroClient.fromEnvironment(
    Platform.environment,
    silent: true,
  );

  // WHAT A HANDLER LOOKS LIKE ------------------------------------------------
  Future<(int, String)> sunSignHandler(Map<String, String> query) async {
    try {
      final birth = Time.of(
        query['when']!,
        GeoLocation.of(
          'query',
          double.parse(query['lon']!),
          double.parse(query['lat']!),
        ),
      );

      final result = await vedAstro.calculate().planetRasiD1Sign(
            PlanetName.sun,
            birth,
          );

      return (200, jsonEncode({'sign': Response.string(result, 'Name')}));
    } on ArgumentError catch (failure) {
      // The caller sent something malformed. Their fault, and cheap to answer.
      return (400, jsonEncode({'error': failure.message}));
    } on ApiException catch (failure) {
      // The API answered and rejected the call. Do not retry the same request.
      stderr.writeln(failure); // the key is already redacted
      return (502, jsonEncode({'error': 'upstream rejected the request'}));
    } on VedAstroException catch (failure) {
      // The request never completed. This one is worth a bounded retry.
      stderr.writeln(failure);
      return (503, jsonEncode({'error': 'upstream unavailable'}));
    }
  }

  // The rest of this file just drives that handler so the output is visible.
  demoHeading('A well-formed request');
  final ok = await sunSignHandler({
    'when': '14:30 25/10/1992 +05:30',
    'lon': '72.8777',
    'lat': '19.0760',
  });
  demoField('status', ok.$1);
  demoField('body', ok.$2);

  demoHeading('A malformed request');
  final bad = await sunSignHandler({
    'when': '25/10/1992 14:30', // the wrong date order
    'lon': '72.8777',
    'lat': '19.0760',
  });
  demoField('status', bad.$1);
  demoField('body', demoTruncate(bad.$2, 90));

  // NOTES WORTH KEEPING ------------------------------------------------------
  //
  // - NO REQUEST TIMEOUT is applied by default, on purpose. A calculation can take
  //   minutes, and a fixed deadline would only ever truncate a valid answer. Set
  //   `timeout: const Duration(seconds: 30)` only when your own request budget
  //   demands one.
  //
  // - CACHE BY CHART INPUT. The same birth details recur constantly, and a cache hit
  //   costs no API calls at all. A `Map` keyed by the wire time string is enough to
  //   start; move it to Redis when you run more than one isolate.
  //
  // - THE FREE TIER IS 5 CALLS PER MINUTE, counted per key across every process. Pace
  //   centrally rather than per isolate, or two workers will throttle each other.
  //
  // - RETRY ONLY VedAstroException, and only a bounded number of times with backoff.
  //   An ApiException means the API actively rejected the call.
  //
  // - CALL close() ON SHUTDOWN so the HTTP client's connections are released.
  //
  // - THROW AWAY NOTHING. The SDK never retries and never throttles, so your queue,
  //   your framework and your observability see exactly what the API did.

  demoHeading('Shutting down');
  vedAstro.close();
  // ignore: avoid_print
  print('   client closed');
}

View source on GitHub
import 'dart:io';

import 'package:vedastro/vedastro.dart';

/// Shared helpers for the examples in this folder.
///
/// Every example is a standalone program: `dart run example/quick_start.dart`.
/// They default to the free tier, and honour two environment variables:
///
/// - `VEDASTRO_API_KEY` — use your own key instead of the free tier.
/// - `VEDASTRO_BASE_URL` — point at a different Calculate service.
///
/// The free tier allows five calls per minute, so the examples that make several
/// calls pace themselves with [demoPace].
const double demoFreeTierGapSeconds = 13.0;

/// Builds a client for the examples.
///
/// The banner is silenced by default: in a server it would corrupt a response body,
/// and in a demo it is noise.
VedAstroClient demoClient({bool silent = true}) {
  final client =
      VedAstroClient.fromEnvironment(Platform.environment, silent: silent);
  return client;
}

/// A birth moment to calculate with: Mumbai, 25 October 1992 at 14:30 IST.
Time demoBirth() => Time.of(
      '14:30 25/10/1992 +05:30',
      GeoLocation.of('Mumbai', 72.8777, 19.0760),
    );

/// A second birth moment, for the compatibility example.
Time demoPartner() => Time.of(
      '09:15 12/03/1995 +05:30',
      GeoLocation.of('Delhi', 77.2090, 28.6139),
    );

/// Prints a section heading so the output of a demo is easy to scan.
void demoHeading(String title) {
  // ignore: avoid_print
  print('\n── $title');
}

/// Prints a labelled line.
void demoField(String label, Object? value) {
  // ignore: avoid_print
  print('   ${label.padRight(18)} $value');
}

/// Waits out the free tier's per-minute allowance.
///
/// `usleep` rather than `sleep` is not needed in Dart, but the gap is: the limit is
/// counted per key across every process, so a tight loop fails even on one machine.
Future<void> demoPace({bool enabled = true}) async {
  if (!enabled) return;
  await Future<void>.delayed(
    Duration(milliseconds: (demoFreeTierGapSeconds * 1000).round()),
  );
}

/// Whether the examples should pace themselves, which they skip for a paid key.
bool demoShouldPace(VedAstroClient client) => !client.hasApiKey;

/// Truncates long text so a demo's output stays readable.
String demoTruncate(Object? value, [int limit = 120]) {
  final text = value?.toString() ?? '';
  return text.length <= limit ? text : '${text.substring(0, limit)}...';
}

Browse All Examples on GitHub

Open Source MIT License

Open Source at Its Core

The VedAstro Dart library is fully open source under the MIT License. You can read the code, verify every API call, and contribute improvements back to the community. The library is maintained alongside the main VedAstro engine — when new calculations are added to the API, the Dart wrapper updates to match.

Note: Calculator wrappers are generated to follow the hosted API. See the repository for source, generator guidance, and contribution instructions.

Ready to Build?

Install the library, try the free tier, and see how fast you can go from zero to a working Vedic astrology application. When your project is ready for the real world, your API key is one click away.

dart pub get

Made and funded by users — Support VedAstro