Logo
SDKs

Node JS

Install

To get started with Saazpay in your Node.js backend, install the Saazpay Node SDK:

npm install @saazpayhq/node-sdk

Environment Variables

Make sure to add the following environment variables to your backend server:

SAAZPAY_APP_ID=your_app_id_here
SAAZPAY_BASE_URL=https://saazpay.com
SAAZPAY_API_KEY=your_api_key_here

Variable Descriptions:

  • SAAZPAY_APP_ID: Your Saazpay application ID (backend only)
  • SAAZPAY_BASE_URL: The base URL for Saazpay API calls (backend only)
  • SAAZPAY_API_KEY: Your Saazpay API key for server-side operations (keep secret)

Usage

Import Functions

import {
  getPlans,
  getActiveSubscription,
  getManagementUrls,
  previewPlan,
  changePlan,
} from "@saazpayhq/node-sdk";

API Endpoints Implementation

Here are comprehensive examples of how to implement API endpoints using the Saazpay Node SDK:

Get Plans

Fetch all available pricing plans for your application.

app.get("/api/plans", async (req, res) => {
  try {
    const plans = await getPlans({
      appId: process.env.SAAZPAY_APP_ID,
    });
    res.json(plans);
  } catch (error) {
    console.error("Error fetching plans:", error);
    res.status(500).json({ error: "Failed to fetch plans" });
  }
});

Response Format:

// Returns IPlan[]
[
  {
    id: "plan_123",
    price: 1000,
    currency: "USD",
    tax_mode: "account_setting",
    name: "Basic Plan",
    description: "A basic subscription plan",
    billing_frequency: 1,
    billing_interval: "month",
    trial_frequency: null,
    trial_interval: null,
    quantity_minimum: 1,
    quantity_maximum: 1,
    product_id: "prod_123",
    createdAt: "2023-01-01T00:00:00Z",
    updatedAt: "2023-01-01T00:00:00Z",
    product: {
      id: "prod_123",
      name: "Basic Product",
      description: "Basic product description",
    },
  },
];

Get Active Subscription

Retrieve the active subscription for a specific user.

app.get("/api/subscription", async (req, res) => {
  try {
    const { userId } = req.query;
 
    if (!userId) {
      return res.status(400).json({ error: "userId is required" });
    }
 
    const subscription = await getActiveSubscription({
      appId: process.env.SAAZPAY_APP_ID,
      userId: userId,
    });
 
    res.json(subscription);
  } catch (error) {
    console.error("Error fetching subscription:", error);
    res.status(500).json({ error: "Failed to fetch subscription" });
  }
});

Response Format:

// Returns ISubscription | null
{
  id: "sub_123",
  customer_id: "cus_123",
  unique_identifier: "[email protected]",
  status: "active",
  paused_at: null,
  canceled_at: null,
  scheduled_change: null,
  next_billed_at: "2023-02-01T00:00:00Z",
  starts_at: "2023-01-01T00:00:00Z",
  ends_at: "2023-02-01T00:00:00Z",
  created_at: "2023-01-01T00:00:00Z",
  applicationId: "app_123",
  product: {
    id: "prod_123",
    name: "Basic Product",
    description: "Basic product description"
  },
  price: {
    id: "price_123",
    amount: 1000,
    currency: "USD"
  }
}

Get Management URLs

Fetch management URLs for a specific subscription.

app.get("/api/management-urls", async (req, res) => {
  try {
    const { subscriptionId } = req.query;
 
    if (!subscriptionId) {
      return res.status(400).json({ error: "subscriptionId is required" });
    }
 
    const urls = await getManagementUrls({
      appId: process.env.SAAZPAY_APP_ID,
      subscriptionId: subscriptionId,
    });
 
    res.json(urls);
  } catch (error) {
    console.error("Error fetching management URLs:", error);
    res.status(500).json({ error: "Failed to fetch management URLs" });
  }
});

Response Format:

// Returns IManagementUrl
{
  customerPortal: "https://checkout.paddle.com/customer/portal/...",
  cancelSubscription: "https://checkout.paddle.com/cancel/...",
  updatePaymentMethod: "https://checkout.paddle.com/update/..."
}

Preview Plan Change

Preview the changes and costs when switching to a new plan.

app.post("/api/preview-plan", async (req, res) => {
  try {
    const { planId, subscriptionId } = req.body;
 
    if (!planId || !subscriptionId) {
      return res.status(400).json({
        error: "planId and subscriptionId are required",
      });
    }
 
    const preview = await previewPlan({
      appId: process.env.SAAZPAY_APP_ID,
      newPlanId: planId,
      subscriptionId: subscriptionId,
    });
 
    res.json(preview);
  } catch (error) {
    console.error("Error previewing plan:", error);
    res.status(500).json({ error: "Failed to preview plan" });
  }
});

Response Format:

// Returns IProration
{
  currencyCode: "USD",
  proratedCharge: 500,
  creditAmount: 300,
  subTotal: 1500,
  tax: 150,
  discount: 0,
  creditApplied: 300,
  grandTotal: 1350
}

Change Plan

Change the subscription to a new plan.

app.put("/api/change-plan", async (req, res) => {
  try {
    const { planId, subscriptionId } = req.body;
 
    if (!planId || !subscriptionId) {
      return res.status(400).json({
        error: "planId and subscriptionId are required",
      });
    }
 
    const result = await changePlan({
      appId: process.env.SAAZPAY_APP_ID,
      newPlanId: planId,
      subscriptionId: subscriptionId,
    });
 
    res.json(result);
  } catch (error) {
    console.error("Error changing plan:", error);
    res.status(500).json({ error: "Failed to change plan" });
  }
});

Response Format:

// Returns IUpdatePlan
{
  id: "sub_123",
  status: "active"
}

Complete Express.js Example

Here's a complete example of an Express.js server with all Saazpay endpoints:

import express from "express";
import cors from "cors";
import {
  getPlans,
  getActiveSubscription,
  getManagementUrls,
  previewPlan,
  changePlan,
} from "@saazpayhq/node-sdk";
 
const app = express();
const PORT = process.env.PORT || 3001;
 
// Middleware
app.use(cors());
app.use(express.json());
 
// Validation middleware
const validateAppId = (req, res, next) => {
  if (!process.env.SAAZPAY_APP_ID) {
    return res.status(500).json({ error: "SAAZPAY_APP_ID not configured" });
  }
  next();
};
 
// Get all plans
app.get("/api/plans", validateAppId, async (req, res) => {
  try {
    const plans = await getPlans({
      appId: process.env.SAAZPAY_APP_ID,
    });
    res.json(plans);
  } catch (error) {
    console.error("Error fetching plans:", error);
    res.status(500).json({ error: "Failed to fetch plans" });
  }
});
 
// Get active subscription
app.get("/api/subscription", validateAppId, async (req, res) => {
  try {
    const { userId } = req.query;
 
    if (!userId) {
      return res.status(400).json({ error: "userId is required" });
    }
 
    const subscription = await getActiveSubscription({
      appId: process.env.SAAZPAY_APP_ID,
      userId: userId,
    });
 
    res.json(subscription);
  } catch (error) {
    console.error("Error fetching subscription:", error);
    res.status(500).json({ error: "Failed to fetch subscription" });
  }
});
 
// Get management URLs
app.get("/api/management-urls", validateAppId, async (req, res) => {
  try {
    const { subscriptionId } = req.query;
 
    if (!subscriptionId) {
      return res.status(400).json({ error: "subscriptionId is required" });
    }
 
    const urls = await getManagementUrls({
      appId: process.env.SAAZPAY_APP_ID,
      subscriptionId: subscriptionId,
    });
 
    res.json(urls);
  } catch (error) {
    console.error("Error fetching management URLs:", error);
    res.status(500).json({ error: "Failed to fetch management URLs" });
  }
});
 
// Preview plan change
app.post("/api/preview-plan", validateAppId, async (req, res) => {
  try {
    const { planId, subscriptionId } = req.body;
 
    if (!planId || !subscriptionId) {
      return res.status(400).json({
        error: "planId and subscriptionId are required",
      });
    }
 
    const preview = await previewPlan({
      appId: process.env.SAAZPAY_APP_ID,
      newPlanId: planId,
      subscriptionId: subscriptionId,
    });
 
    res.json(preview);
  } catch (error) {
    console.error("Error previewing plan:", error);
    res.status(500).json({ error: "Failed to preview plan" });
  }
});
 
// Change plan
app.put("/api/change-plan", validateAppId, async (req, res) => {
  try {
    const { planId, subscriptionId } = req.body;
 
    if (!planId || !subscriptionId) {
      return res.status(400).json({
        error: "planId and subscriptionId are required",
      });
    }
 
    const result = await changePlan({
      appId: process.env.SAAZPAY_APP_ID,
      newPlanId: planId,
      subscriptionId: subscriptionId,
    });
 
    res.json(result);
  } catch (error) {
    console.error("Error changing plan:", error);
    res.status(500).json({ error: "Failed to change plan" });
  }
});
 
// Error handling middleware
app.use((error, req, res, next) => {
  console.error("Unhandled error:", error);
  res.status(500).json({ error: "Internal server error" });
});
 
app.listen(PORT, () => {
  console.log(`Saazpay backend server running on port ${PORT}`);
});

Error Handling

The SDK may throw errors in the following scenarios:

  • Invalid App ID: When the provided appId is incorrect
  • Invalid API Key: When the API key is invalid or missing
  • Network Errors: When there are connectivity issues
  • Invalid Parameters: When required parameters are missing or invalid

Always wrap SDK calls in try-catch blocks and handle errors appropriately:

try {
  const plans = await getPlans({ appId: process.env.SAAZPAY_APP_ID });
  res.json(plans);
} catch (error) {
  if (error.message.includes("unauthorized")) {
    res.status(401).json({ error: "Invalid API key" });
  } else if (error.message.includes("not found")) {
    res.status(404).json({ error: "Resource not found" });
  } else {
    res.status(500).json({ error: "Internal server error" });
  }
}

TypeScript Support

The SDK includes TypeScript definitions. Here are the main interfaces:

interface IPlan {
  id: string;
  price: number;
  currency: string;
  tax_mode: string;
  name: string;
  description: string;
  billing_frequency: number;
  billing_interval: string;
  trial_frequency: null;
  trial_interval: null;
  quantity_minimum: number;
  quantity_maximum: number;
  product_id: string;
  createdAt: string;
  updatedAt: string;
  product: IProduct;
}
 
interface ISubscription {
  id: string;
  customer_id: string;
  unique_identifier: string;
  status: string;
  paused_at: null;
  canceled_at: null;
  scheduled_change: null;
  next_billed_at: string;
  starts_at: string;
  ends_at: string;
  created_at: string;
  applicationId: string;
  product: ISubscriptionProduct;
  price: ISubscriptionPrice;
}
 
interface IManagementUrl {
  customerPortal: string;
  cancelSubscription: string;
  updatePaymentMethod: string;
}
 
interface IProration {
  currencyCode: string;
  proratedCharge: number;
  creditAmount: number;
  subTotal: number;
  tax: number;
  discount: number;
  creditApplied: number;
  grandTotal: number;
}
 
interface IUpdatePlan {
  id: string;
  status: string;
}

On this page