Public vs Tenant-Scoped Pricing Endpoints: Why Both Matter
At first glance, exposing two pricing endpoints can seem redundant.
Why have both:
/api/pricing/plans
and
/api/subscriptions/plans
when they appear to return similar information?
The answer lies in one of the most important principles of SaaS architecture:
Public product information and tenant-specific billing information are not the same thing.
Treating them as separate concerns improves security, simplifies application design, and creates a more consistent customer experience.
Two Different Questions
Most pricing systems must answer two fundamentally different questions.
The first is:
What plans does the product offer?
The second is:
What plans are available to this organization right now?
While they sound similar, they serve very different audiences.
Public Pricing
Public pricing is intended for:
- Marketing pages
- Landing pages
- Checkout flows
- Documentation
- Sales conversations
Examples include:
- Plan names
- Feature summaries
- Monthly pricing
- Annual pricing
- Public limits
- Upgrade comparisons
This information should be available without authentication.
A typical endpoint looks like:
GET /api/pricing/plans
This endpoint represents the commercial catalog presented to the market.
Tenant-Scoped Pricing
Tenant-scoped pricing answers a different question.
It exists for authenticated users and organizations.
Examples include:
- Current subscription
- Eligible upgrades
- Eligible downgrades
- Trial status
- Legacy plans
- Contract pricing
- Custom entitlements
- Usage limits
- Organization-specific offers
A typical endpoint looks like:
GET /api/subscriptions/plans
This endpoint represents the organization's billing reality.
Why One Endpoint Usually Fails
Many SaaS platforms begin with a single pricing endpoint.
Initially this works.
Over time the platform grows.
Organizations receive:
- Grandfathered pricing
- Enterprise contracts
- Promotional discounts
- Custom plans
- Legacy subscriptions
- Feature flags
Eventually the same endpoint must serve both public visitors and existing customers.
At that point, the data model becomes increasingly complicated.
Questions emerge:
- Should internal plans be exposed publicly?
- Should legacy plans appear on marketing pages?
- Should enterprise pricing be visible?
- Should tenant-specific discounts be returned?
The API becomes responsible for conflicting concerns.
Separating public and tenant-scoped endpoints avoids this problem entirely.
Security Benefits
The separation is not only architectural.
It is also a security boundary.
A public endpoint should expose only information intended for public consumption.
For example:
{
"name": "Growth",
"price": 99,
"features": [...]
}
A tenant-aware endpoint may contain significantly more information:
{
"organizationId": "org_123",
"currentPlan": "enterprise",
"contractPrice": 2500,
"usageAllowance": 5000000,
"eligibleUpgrades": [...],
"trialEndsAt": null
}
These datasets should not be treated the same.
Separating endpoints reduces the risk of exposing internal billing information through public APIs.
Product Consistency
Another advantage is consistency across the customer journey.
A typical SaaS flow looks like:
Visitor
↓
Pricing Page
↓
Checkout
↓
Subscription Created
↓
Dashboard
Different stages require different information.
Before Signup
Customers need to understand:
- What plans exist
- What features are included
- What pricing looks like
Public pricing endpoints provide this information.
After Signup
Customers need to understand:
- What they purchased
- What they can upgrade to
- What limits apply
- How much usage remains
Tenant-scoped endpoints provide this information.
Using separate APIs keeps each experience focused on its intended audience.
Stripe and Pricing Catalogs
In many SaaS architectures, Stripe acts as the billing source of truth.
Stripe products and prices define commercial offerings.
However, applications often maintain their own pricing catalog because additional business logic must be layered on top.
Examples include:
- Feature mappings
- Entitlement rules
- Usage allowances
- Internal plan metadata
- UI presentation details
The public pricing endpoint can expose catalog information suitable for marketing and checkout.
The tenant-scoped endpoint can combine that catalog with:
- Stripe subscription state
- Organization ownership
- Entitlement projections
- Contract-specific overrides
This creates a clean separation between commercial offerings and operational reality.
Supporting Enterprise Growth
The distinction becomes increasingly important as companies move up-market.
Enterprise customers often introduce requirements such as:
- Negotiated pricing
- Multi-year contracts
- Private plans
- Custom limits
- Dedicated support tiers
These plans frequently should not appear on public pricing pages.
Yet they must remain visible to the organizations that own them.
A tenant-scoped pricing API provides that flexibility without complicating public pricing experiences.
Recommended Pattern
For most SaaS platforms, the following model works well:
Public Catalog
GET /api/pricing/plans
Returns:
- Public plans
- Public pricing
- Public features
- Marketing metadata
No authentication required.
Tenant Billing View
GET /api/subscriptions/plans
Returns:
- Current subscription
- Available upgrades
- Available downgrades
- Contract pricing
- Usage limits
- Entitlements
- Organization-specific billing state
Authentication required.
Final Thoughts
Pricing is not a single dataset.
It serves multiple audiences with different requirements.
Prospective customers need a clear understanding of what the product offers.
Existing customers need accurate information about what they own and what they can do next.
Separating public pricing endpoints from tenant-scoped subscription endpoints creates a cleaner architecture, a stronger security model, and a more consistent customer experience.
The result is an API design that scales with both the product and the business.