Skip to main content

Overview

DeployHub maintains a complete history of all your payments and subscriptions. All completed orders are stored and accessible through your account dashboard.
Invoice data is retrieved from the CompletedOrder model defined in /prototype/backend/src/models/slices/completedOrder.model.js:1

Accessing Your Invoices

You can view all your invoices through the API endpoint:
GET /api/user/invoices
Implementation: /prototype/backend/src/controllers/slices/user/invoices.js:3

API Response

{
  "data": [
    {
      "_id": "65a1b2c3d4e5f6g7h8i9j0k1",
      "userid": "64f9e8d7c6b5a4f3e2d1c0b9",
      "orderid": "order_rcptid_0.123456789",
      "months": 12,
      "amount": 862800,  // paise (₹8,628)
      "plan": "pro",
      "status": "completed",
      "projectid": "65b2c3d4e5f6g7h8i9j0k1l2",
      "createdAt": "2026-01-15T10:30:00.000Z",
      "updatedAt": "2026-01-15T10:30:00.000Z"
    }
  ]
}

Invoice Data Structure

Each invoice contains the following information:
orderid
string
required
Unique Razorpay order ID (e.g., order_rcptid_0.123456789)
amount
number
required
Total amount paid in paise (divide by 100 for rupees)Example: 862800 paise = ₹8,628
months
number
required
Subscription duration purchasedCommon values: 1, 3, 6, 12, 24
plan
string
required
Subscription plan typeValues: "free" or "pro"
status
string
required
Payment status (always "completed" for invoices)
projectid
ObjectId
Associated project ID created with this subscription
createdAt
Date
Invoice creation timestamp
updatedAt
Date
Last update timestamp

Invoice Controller Implementation

The invoice retrieval logic is implemented as:
// From /prototype/backend/src/controllers/slices/user/invoices.js
import { Model } from "../../../models/index.js";

const Invoice = async (req, res) => {
  try {
    const user = req.user;
    
    // Fetch all completed orders for the user
    const invoices = await Model.CompletedOrder.find({ 
      userid: user._id 
    });
    
    return res.status(200).json({
      data: invoices,
    });
  } catch (err) {
    console.log(err);
    return res.status(500).json({
      error: "Internal Server Error",
    });
  }
};
The controller fetches all CompletedOrder records matching the authenticated user’s ID.

CompletedOrder Schema

Invoices are stored using the following Mongoose schema:
// From completedOrder.model.js:3-30
const completedorderschema = new mongoose.Schema({
  userid: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "User",
    required: true
  },
  orderid: {
    type: String,
    required: true
  },
  months: {
    type: Number,
    required: true
  },
  amount: {
    type: Number
  },
  plan: {
    type: String,
  },
  status: {
    type: String,
  },
  projectid: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "Project",
  }
}, { timestamps: true });
The timestamps: true option automatically adds createdAt and updatedAt fields.

Invoice Creation Flow

Invoices are created during payment verification:
1

Payment Initiated

User completes payment through Razorpay interface
2

Payment Verified

Server verifies Razorpay signature using HMAC-SHA256
// From verify.controller.js:20-23
const generated_signature = crypto
  .createHmac("sha256", process.env.KEY_SECRET)
  .update(razorpay_order_id + "|" + razorpay_payment_id)
  .digest("hex");
3

Order Completed

System creates CompletedOrder record
// From verify.controller.js:63-70
const payment = await Model.CompletedOrder.create({
  userid: orderfromdb.userid,
  orderid: orderfromdb.oderid,
  months: orderfromdb.months,
  amount: orderfromdb.amount,
  plan: orderfromdb.plan,
  status: "completed",
});
4

Project Created

New project linked to the payment record
// From verify.controller.js:73-79
const project = new Model.Project({
  paymentId: payment._id,
  plan: payment.plan,
  startDate: now,
  endDate: subscriptionend,
  owner: req.user._id
});
5

Invoice Available

CompletedOrder appears in user’s invoice list immediately

Calculating Invoice Amounts

Invoice amounts are calculated with volume discounts:
// From init.controller.js:47-50
const basePrice = parseInt(plans.basePrice); // 79900 paise
const discountRates = plans.discount;
const discount = discountRates[months] || 0;
const finalAmount = parseInt(months * basePrice * (1 - discount / 100).toFixed(2));

Example Calculations

months = 1
basePrice = 79900
discount = 0%
finalAmount = 1 × 79900 × (1 - 0/100)
            = 79900 paise
            =799

Subscription Renewal Invoices

When renewing a subscription, a new invoice is created:
// From verifyRenew.js:57-63
await Model.CompletedOrder.create({
  userid: orderfromdb.userid,
  oderid: orderfromdb.oderid,
  months: orderfromdb.months,
  amount: orderfromdb.amount,
  status: 'completed'
});
Renewal invoices preserve the original subscription duration (months) and pricing from the previous order.

Filtering and Sorting Invoices

You can extend the invoice query with filters:
const invoices = await Model.CompletedOrder.find({ 
  userid: user._id,
  plan: "pro"
}).sort({ createdAt: -1 });

Invoice Status Lifecycle

1

Pending Order Created

Initial order stored in PendingOrder collection
status: "pending"
expires: 7200 seconds (2 hours)
2

Payment Processing

User completes payment on RazorpayPendingOrder still exists with status “pending”
3

Payment Verified

Server confirms payment signaturePendingOrder updated:
orderfromdb.status = "completed";
await orderfromdb.save({ validateBeforeSave: false });
4

Invoice Generated

CompletedOrder created as permanent invoice record
status: "completed"
// No expiry - permanent record
PendingOrder records auto-expire after 2 hours (7200 seconds) if payment is not completed. Only CompletedOrder records appear as invoices.

Common Invoice Scenarios

When purchasing Pro for the first time:
  1. User selects plan duration (e.g., 12 months)
  2. Payment processed through Razorpay
  3. Invoice created with full amount (₹8,628 for 12 months)
  4. Project created and linked to invoice
  5. Subscription activated immediately
When renewing an existing subscription:
  1. System retrieves previous order duration
  2. Calculates renewal amount (same duration, no re-selection)
  3. Payment processed
  4. New invoice created
  5. Subscription extended from previous end date
From renewInfo.controller.js:7-14 - renewal uses previous subscription duration
Free plan projects do NOT generate invoices:
// From init.controller.js:28-37
if (plan === 'free') {
  const project = new Model.Project({
    paymentId: null,  // No payment
    owner: req.user._id,
  });
  
  await project.save({ validateBeforeSave: false });
  return res.json({ success: true, project });
}
No CompletedOrder created, no invoice generated.
If payment verification fails:
  • PendingOrder remains with status “pending”
  • NO CompletedOrder created
  • NO invoice generated
  • PendingOrder auto-expires after 2 hours
  • User must retry payment

Downloading Invoice Data

To export your invoices:
curl -X GET https://api.deployhub.com/api/user/invoices \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Accept: application/json"

Next Steps