DEV Community

Vedika Intelligence
Vedika Intelligence

Posted on

TypeScript API Integration: A Practical Guide with Vedika Astrology [2026-02]

In today's interconnected world, integrating with third-party APIs is a common task for developers. However, working with APIs in TypeScript can sometimes be tricky due to type safety concerns. How do we ensure we're using the API correctly while maintaining TypeScript's powerful type checking?

In this article, we'll explore a practical approach to TypeScript API integration using the Vedika Astrology API as our example. By the end, you'll have a solid understanding of how to create robust, type-safe API integrations in TypeScript.

Setting Up the Project

First, let's initialize a new TypeScript project:

npm init -y
npm install typescript ts-node @types/node
npx tsc --init
Enter fullscreen mode Exit fullscreen mode

Now, let's install the necessary dependencies for our API integration:

npm install axios
npm install --save-dev @types/axios
Enter fullscreen mode Exit fullscreen mode

Defining API Types

TypeScript's strength lies in its type system. Before making any API calls, let's define the types for our Vedika API integration:

// types/vedika.ts
export interface BirthDetails {
  datetime: string; // ISO 8601 format
  latitude: number;
  longitude: number;
}

export interface VedikaRequest {
  question: string;
  birthDetails: BirthDetails;
}

export interface VedikaResponse {
  answer: string;
  confidence: number;
  astrologicalInsights: {
    planetPositions: Record<string, number>;
    zodiacSign: string;
    housePositions: Record<string, number>;
  };
}
Enter fullscreen mode Exit fullscreen mode

Creating the API Client

Now, let's create a type-safe API client for the Vedika service:

// clients/vedikaClient.ts
import axios, { AxiosInstance } from 'axios';
import { VedakaRequest, VedikaResponse } from '../types/vedika';

export class VedikaClient {
  private client: AxiosInstance;

  constructor(baseURL: string = 'https://api.vedika.io') {
    this.client = axios.create({
      baseURL,
      headers: {
        'Content-Type': 'application/json',
      },
    });
  }

  async getAstrologicalInsights(request: VedikaRequest): Promise<VedikaResponse> {
    try {
      const response = await this.client.post<VedikaResponse>('/api/v1/astrology/query', request);
      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error)) {
        throw new Error(`Vedika API Error: ${error.response?.data?.message || error.message}`);
      }
      throw error;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Using the Client in Your Application

Let's create a service that uses our Vedika client:

// services/astrologyService.ts
import { VedikaClient } from '../clients/vedikaClient';
import { VedikaRequest, VedikaResponse } from '../types/vedika';

export class AstrologyService {
  private vedikaClient: VedikaClient;

  constructor(apiKey: string) {
    this.vedikaClient = new VedikaClient();
    // In a real app, you'd set the API key in the client headers
    this.vedikaClient.client.defaults.headers.common['Authorization'] = `Bearer ${apiKey}`;
  }

  async getPersonalizedInsights(
    question: string,
    birthDetails: { datetime: string; latitude: number; longitude: number }
  ): Promise<VedikaResponse> {
    const request: VedikaRequest = {
      question,
      birthDetails,
    };

    return this.vedikaClient.getAstrologicalInsights(request);
  }
}
Enter fullscreen mode Exit fullscreen mode

Implementing Error Handling

Robust error handling is crucial for API integrations. Let's enhance our client with better error handling:

// clients/vedikaClient.ts (enhanced)
export class VedikaClient {
  // ... previous code ...

  async getAstrologicalInsights(request: VedikaRequest): Promise<VedikaResponse> {
    try {
      const response = await this.client.post<VedikaResponse>('/api/v1/astrology/query', request);

      // Validate the response shape
      if (!response.data || typeof response.data.answer !== 'string') {
        throw new Error('Invalid response structure from Vedika API');
      }

      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error)) {
        const status = error.response?.status;
        const message = error.response?.data?.message || error.message;

        switch (status) {
          case 401:
            throw new Error('Authentication failed. Check your API key.');
          case 429:
            throw new Error('Rate limit exceeded. Please try again later.');
          case 400:
            throw new Error(`Bad request: ${message}`);
          default:
            throw new Error(`API Error (${status}): ${message}`);
        }
      }
      throw new Error(`Network error: ${error instanceof Error ? error.message : String(error)}`);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Using the Service with Example Data

Here's how you might use this service in your application:

// main.ts
import { AstrologyService } from './services/astrologyService';

async function main() {
  const astrologyService = new AstrologyService('your-api-key');

  try {
    const insights = await astrologyService.getPersonalizedInsights(
      'What does my future hold in terms of career?',
      {
        datetime: '1990-05-15T08:30:00Z',
        latitude: 40.7128,
        longitude: -74.0060,
      }
    );

    console.log('Astrological Insights:');
    console.log(`Answer: ${insights.answer}`);
    console.log(`Confidence: ${(insights.confidence * 100).toFixed(1)}%`);
    console.log('Zodiac Sign:', insights.astrologicalInsights.zodiacSign);
  } catch (error) {
    console.error('Failed to get insights:', error instanceof Error ? error.message : String(error));
  }
}

main();
Enter fullscreen mode Exit fullscreen mode

Practical Tips and Gotchas

  1. API Key Management: Never hardcode API keys in your source code. Use environment variables or a secret management service.

  2. Rate Limiting: Implement rate limiting in your application to avoid hitting API limits.

  3. Response Validation: Always validate API responses to match your expected types, especially when working with third-party APIs.

  4. Error Handling: Create specific error types for different failure scenarios to provide better debugging information.

  5. Caching: For APIs like Vedika that might return similar responses for the same inputs, consider implementing caching.

  6. Type Safety for Dynamic Data: When APIs return dynamic data (like different fields based on the question), use union types or discriminated unions.

Conclusion

TypeScript API integration doesn't have to be complex. By defining clear types, creating a dedicated client class, and implementing robust error handling, you can build type-safe API integrations that are both maintainable and reliable.

Next steps to enhance this integration:

  1. Add request/response logging for debugging
  2. Implement retry logic for transient failures
  3. Create unit tests for your API client
  4. Add request/response interceptors for common transformations
  5. Consider using a library like Zod for runtime type validation

The Vedika API example we've built here can serve as a template for integrating with any TypeScript API. Remember to adapt the types and error handling to match the specific API you're working with.

Happy coding!

Top comments (0)