Skip to main content

Subscription Management

Subscription Management provides comprehensive subscription retrieval, advanced filtering, and administrative oversight functionality within the DashClicks billing system.

API Endpoints Overview

MethodEndpointDescription
GET/v1/admin/billing/subscriptionsRetrieve subscriptions with advanced filtering
GET/v1/admin/billing/filtersGet subscription filter counts and statistics

Service Methods & Business Logic

Subscription Retrieval and Filtering

querySubs(filters, sort, pagination) - Comprehensive subscription retrieval

  • Service Method: billingService.querySubs(filters, sort, pagination)
  • Controller: billingController.getSubscriptions
  • Route: GET /v1/admin/billing/subscriptions
  • Parameters:
    • status - Array of status filters (active, past_due, canceled, etc.)
    • products - Array of product type filters
    • search - Search term across accounts and products
    • page, limit - Pagination parameters
    • sort_by, order - Sorting configuration
  • Status Filtering Logic:
    • Supports multiple status combinations
    • Special handling for product-specific status filtering
  • Search Functionality: Multi-field search across:
    • Partner account name and email
    • Buyer account name and email
    • Product name and tier information
  • MongoDB Aggregation Pipeline:
    • Lookup to _accounts for partner (seller) information
    • Lookup to _accounts for buyer information via metadata.account_id
    • Lookup to _store.products for product details
    • Discount calculation with coupon information
  • Collections Used: _store.subscriptions, _accounts, _store.products
  • Returns: Paginated subscriptions with partner, buyer, and product data

retrySub(subId) - Retry failed subscription payment

  • Service Method: billingService.retrySub(subId)
  • Controller: billingController.retrySubscription
  • Route: PUT /v1/admin/billing/subscriptions/:sub_id/retry
  • Process: Retrieves subscription and triggers Stripe payment retry
  • Returns: Updated subscription status

cancelSub(subId, immediate) - Cancel subscription

  • Service Method: billingService.cancelSub(subId, immediate)
  • Controller: billingController.cancelSubscription
  • Route: DELETE /v1/admin/billing/subscriptions/:sub_id
  • Parameters:
    • subId - Subscription ID to cancel
    • immediate - Boolean for immediate vs period-end cancellation
  • Process: Updates Stripe subscription cancellation
  • Returns: Cancellation confirmation

resumeCancelSub(subId) - Resume canceled subscription

  • Service Method: billingService.resumeCancelSub(subId)
  • Controller: billingController.resumeCancelSubscription
  • Route: POST /v1/admin/billing/subscriptions/:sub_id/resume
  • Process: Resumes previously canceled subscription in Stripe
  • Returns: Resumed subscription status

clearSub(subId) - Clear/delete subscription record

  • Service Method: billingService.clearSub(subId)
  • Controller: billingController.clearSubscription
  • Route: DELETE /v1/admin/billing/subscriptions/:sub_id/clear
  • Process: Removes subscription record from database
  • Returns: Deletion confirmation

Filter Statistics Generation

getFilters(billingFilters) - Dynamic filter count calculation for administrative interface

  • Generates real-time filter statistics for administrative subscription filtering interface
  • Status Filter Counts: Calculates subscription counts for each status category:
    • Real-time aggregation of subscription status distribution
    • Dynamic count calculation based on current subscription state
    • Filter-specific matching logic for accurate statistics
  • Product Filter Counts: Calculates subscription counts by product type:
    • Product-type based aggregation with metadata matching
    • Active subscription filtering (excludes canceled/expired)
    • Product category distribution statistics
  • Dynamic Aggregation: Flexible filter count calculation:
    • Configurable filter categories and values
    • Efficient MongoDB aggregation for performance
    • Null-safe count calculation with fallback values
  • MongoDB Collections: _store.subscriptions, _store.products with aggregation
  • Returns: Updated filter objects with current count statistics

Technical Implementation Details

Advanced Subscription Filtering Pipeline

const buildSubscriptionFilter = filters => {
let statusMatch = { status: { $in: [] } };

// Status-based filtering logic
if (filters.status?.length) {
filters.status.forEach(status => {
switch (status) {
case 'active':
statusMatch.status.$in.push('active', 'trialing');
break;
case 'past_due':
statusMatch.status.$in.push('past_due');
break;
case 'canceled':
statusMatch.status.$in.push('canceled');
statusMatch.team_tasks_pending = true;
statusMatch['plan.metadata.product_type'] = {
$nin: ['listings', 'phone_number', 'site', 'software'],
};
break;
case 'cancels_on':
statusMatch.status.$in.push('active', 'trialing');
statusMatch.cancel_at_period_end = true;
break;
case 'unpaid':
statusMatch.status.$in.push('unpaid');
break;
}
});
} else {
// Default to active subscriptions
statusMatch.status = { $in: ['active', 'trialing', 'past_due'] };
}

return statusMatch;
};

Multi-Dimensional Search Implementation

const buildSearchFilter = searchTerm => {
if (!searchTerm) return {};

const searchMatch = {
$or: [
// ObjectId-based account matching
...(mongoose.isObjectIdOrHexString(searchTerm)
? [
{ 'partner._id': { $eq: new ObjectId(searchTerm) } },
{ 'buyer._id': { $eq: new ObjectId(searchTerm) } },
]
: []),

// Text-based search across multiple fields
{
'partner.name': {
$regex: searchTerm.trim(),
$options: 'i',
},
},
{
'buyer.name': {
$regex: searchTerm.trim(),
$options: 'i',
},
},
{
'plan.nickname': {
$regex: searchTerm.trim(),
$options: 'i',
},
},
{
'product.name': {
$regex: searchTerm.trim(),
$options: 'i',
},
},
],
};

return searchMatch;
};

Subscription Aggregation Pipeline

const subscriptionAggregationPipeline = (filters, sort, pagination) => {
const skip = (pagination.page - 1) * pagination.limit;

return [
// Initial status filtering
{ $match: buildSubscriptionFilter(filters) },

// Partner (seller) account lookup
{
$lookup: {
from: '_accounts',
localField: 'account',
foreignField: '_id',
as: 'partner',
},
},
{
$set: {
partner: { $arrayElemAt: ['$partner', 0] },
},
},

// Buyer account lookup via metadata
{
$lookup: {
from: '_accounts',
localField: 'metadata.account_id',
foreignField: '_id',
as: 'buyer',
},
},
{
$set: {
buyer: { $arrayElemAt: ['$buyer', 0] },
},
},

// Product information lookup
{
$lookup: {
from: '_store.products',
let: { stripe_id: '$plan.product' },
pipeline: [
{
$match: {
'metadata.v1_product_type': { $exists: false },
$expr: { $eq: ['$stripe_id', '$$stripe_id'] },
},
},
],
as: 'product',
},
},
{
$set: {
product: { $arrayElemAt: ['$product', 0] },
},
},

// V1 product compatibility lookup
{
$lookup: {
from: '_store.products',
let: { stripe_id: '$plan.product' },
pipeline: [
{
$match: {
'metadata.v1_product_type': { $exists: true },
$expr: {
$and: [
{ $eq: ['$stripe_id', '$$stripe_id'] },
{
$in: [
'$metadata.v1_product_type',
[
'facebook_ads',
'seo',
'content',
'google_ads',
'listings',
'social_posting',
],
],
},
],
},
},
},
],
as: 'v1products',
},
},
{
$set: {
v1products: { $arrayElemAt: ['$v1products', 0] },
},
},

// Search filtering
...(filters.search ? [{ $match: buildSearchFilter(filters.search) }] : []),

// Pagination and counting
{
$facet: {
paginatedResults: [
// Discount calculation
{
$addFields: {
discountedCost: {
$multiply: [
'$plan.amount',
{
$subtract: [
1,
{
$divide: [{ $ifNull: ['$discount.coupon.percent_off', 0] }, 100],
},
],
},
],
},
},
},

// Final projection
{
$project: {
partner: {
name: 1,
phone: 1,
email: 1,
account: 1,
},
buyer: {
name: 1,
phone: 1,
email: 1,
account: 1,
},
product: {
$cond: {
if: { $not: ['$product.name'] },
then: null,
else: {
name: '$product.name',
tier: '$plan.nickname',
interval: '$plan.interval',
interval_count: '$plan.interval_count',
amount: '$plan.amount',
amount_due: '$discountedCost',
images: '$product.images',
},
},
},
v1_products: {
$cond: {
if: { $not: ['$v1products.name'] },
then: null,
else: {
name: '$v1products.name',
tier: '$plan.nickname',
interval: '$plan.interval',
interval_count: '$plan.interval_count',
amount: '$plan.amount',
amount_due: '$discountedCost',
images: '$product.images',
},
},
},
status: 1,
team_tasks_pending: 1,
cancel_at_period_end: 1,
current_period_start: 1,
current_period_end: 1,
cancel_at: 1,
ended_at: 1,
subscription_id: {
stripe: '$stripe_id',
internal: '$_id',
},
renew_date: '$current_period_end',
created: 1,
},
},

// Sorting
{
$sort: sort.sort_by
? { [sort.sort_by]: sort.order === 'asc' ? 1 : -1 }
: { created: -1 },
},

// Pagination
{ $skip: skip || 0 },
{ $limit: pagination.limit },
],

totalCount: [{ $count: 'count' }],
},
},
];
};

API Response Formats

Subscription List Response

{
"success": true,
"message": "SUCCESS",
"data": [
{
"partner": {
"name": "DashClicks Agency",
"phone": "+1234567890",
"email": "agency@dashclicks.com",
"account": "partner_account_id"
},
"buyer": {
"name": "Client Business Inc",
"phone": "+1987654321",
"email": "client@business.com",
"account": "buyer_account_id"
},
"product": {
"name": "SEO Management",
"tier": "Professional",
"interval": "month",
"interval_count": 1,
"amount": 29999,
"amount_due": 25499,
"images": ["https://example.com/seo-product.jpg"]
},
"v1_products": null,
"status": "active",
"team_tasks_pending": false,
"cancel_at_period_end": false,
"current_period_start": "2024-10-01T00:00:00.000Z",
"current_period_end": "2024-11-01T00:00:00.000Z",
"cancel_at": null,
"ended_at": null,
"subscription_id": {
"stripe": "sub_stripe_id_123",
"internal": "subscription_internal_id"
},
"renew_date": "2024-11-01T00:00:00.000Z",
"created": "2024-10-01T00:00:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 150,
"pages": 15
}
}

Filter Counts Response

{
"success": true,
"message": "SUCCESS",
"data": {
"statuses": {
"active": 125,
"past_due": 8,
"canceled": 12,
"cancels_on": 5,
"unpaid": 3
},
"products": {
"seo": 45,
"google_ads": 32,
"facebook_ads": 28,
"content": 20,
"social_posting": 15,
"listings": 10
}
}
}

Query Parameters

Subscription Filtering Parameters

  • status (array) - Filter by subscription status: ['active', 'past_due', 'canceled', 'cancels_on', 'unpaid']
  • products (array) - Filter by product type: ['seo', 'google_ads', 'facebook_ads', 'content', 'social_posting', 'listings']
  • search (string) - Search across partner names, buyer names, product names, and account IDs
  • sort_by (string) - Sort field: 'created', 'current_period_end', 'status'
  • order (string) - Sort order: 'asc' or 'desc' (default: 'desc')
  • page (number) - Page number for pagination (default: 1)
  • limit (number) - Items per page (default: 10, max: 100)

Available Status Values

  • active - Currently active subscriptions (includes trialing)
  • past_due - Subscriptions with failed payment attempts
  • canceled - Fully canceled subscriptions with pending team tasks
  • cancels_on - Active subscriptions scheduled for period-end cancellation
  • unpaid - Subscriptions with unpaid invoices

Available Product Types

  • seo - SEO management services
  • google_ads - Google Ads management
  • facebook_ads - Facebook Ads management
  • content - Content creation services
  • social_posting - Social media posting services
  • listings - Business listings management
  • phone_number - Phone number services
  • site - Website services
  • software - Software products

Error Handling

Subscription Management Error Scenarios

  • 400 Bad Request: Invalid filtering parameters or malformed query
  • 500 Internal Server Error: Database aggregation failures or MongoDB connection issues

Empty Results Response

{
"success": true,
"message": "SUCCESS",
"data": [],
"pagination": {
"page": 1,
"limit": 10,
"total": 0,
"pages": 0
}
}

Usage Examples

Get All Active Subscriptions

GET /v1/admin/billing/subscriptions?status=active&limit=20
Authorization: Bearer {admin_token}

Search Subscriptions by Partner Name

GET /v1/admin/billing/subscriptions?search=DashClicks&page=1&limit=10
Authorization: Bearer {admin_token}

Filter by Multiple Statuses and Product Types

GET /v1/admin/billing/subscriptions?status=active,past_due&products=seo,google_ads&sort_by=created&order=desc
Authorization: Bearer {admin_token}

Get Canceled Subscriptions with Pending Tasks

GET /v1/admin/billing/subscriptions?status=canceled&limit=50
Authorization: Bearer {admin_token}

Get Filter Statistics

GET /v1/admin/billing/filters
Authorization: Bearer {admin_token}
💬

Documentation Assistant

Ask me anything about the docs

Hi! I'm your documentation assistant. Ask me anything about the docs!

I can help you with:
- Code examples
- Configuration details
- Troubleshooting
- Best practices

Try asking: How do I configure the API?
09:31 AM