Billing
The billing proxy lets your deployed application create Stripe checkout sessions, customer portal sessions, and manage pricing without embedding Stripe API keys in your app. All Stripe operations are proxied through HiveForge.
Access the billing proxy via hiveforge.billing.
import { HiveForgeClient } from '@producthacker/hiveforge-sdk';
const hiveforge = new HiveForgeClient({
deploymentId: process.env.HIVEFORGE_DEPLOYMENT_ID!,
deploymentSecret: process.env.HIVEFORGE_DEPLOYMENT_SECRET!,
});
await hiveforge.initialize();Billing features are only available on tiers where billing_enabled is true. Check with hiveforge.billing.isEnabled() before making calls.
Methods
createCheckout(options)
Create a Stripe checkout session for new subscriptions or one-time payments.
const checkout = await hiveforge.billing.createCheckout({
priceId: 'price_1N2b3c4D5e6F7g8H9i0J',
customerEmail: 'jane@example.com',
successUrl: 'https://myapp.com/welcome?session_id={CHECKOUT_SESSION_ID}',
cancelUrl: 'https://myapp.com/pricing',
mode: 'subscription',
allowPromotionCodes: true,
});
console.log('Session ID:', checkout.session_id);
console.log('Checkout URL:', checkout.url);
// Redirect the user to Stripe
window.location.href = checkout.url;Parameters (CheckoutOptions):
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
priceId | string | Yes | -- | Stripe price ID (e.g. price_1N2b3c...) |
customerEmail | string | Yes | -- | Customer's email address |
successUrl | string | Yes | -- | URL to redirect to after successful payment |
cancelUrl | string | Yes | -- | URL to redirect to if checkout is canceled |
metadata | Record<string, unknown> | No | -- | Custom metadata attached to the session |
quantity | number | No | 1 | Quantity of the price |
allowPromotionCodes | boolean | No | true | Whether to show promotion code field |
mode | 'subscription' | 'payment' | No | 'subscription' | Checkout mode |
Returns (CheckoutResponse):
| Field | Type | Description |
|---|---|---|
session_id | string | Stripe checkout session ID |
url | string | URL to redirect the customer to |
expires_at | string | Optional ISO timestamp when the session expires |
Throws: BillingProxyException if billing is not enabled or Stripe returns an error.
Equivalent curl request
curl -X POST https://api.hiveforge.dev/api/v1/proxy/billing/checkout \
-H "Content-Type: application/json" \
-H "X-Deployment-ID: d9f2a1b4-7c3e-4f8a-b5d6-1e2f3a4b5c6d" \
-H "X-Deployment-Secret: sk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" \
-d '{
"price_id": "price_1N2b3c4D5e6F7g8H9i0J",
"customer_email": "jane@example.com",
"success_url": "https://myapp.com/welcome",
"cancel_url": "https://myapp.com/pricing",
"mode": "subscription",
"quantity": 1,
"allow_promotion_codes": true
}'createPortal(options)
Create a Stripe customer portal session so users can manage their subscription, update payment methods, or cancel.
const portal = await hiveforge.billing.createPortal({
customerId: 'cus_P1q2R3s4T5u6V7w8',
returnUrl: 'https://myapp.com/account',
});
console.log('Portal URL:', portal.url);
window.location.href = portal.url;Parameters (PortalOptions):
| Parameter | Type | Required | Description |
|---|---|---|---|
customerId | string | Yes | Stripe customer ID |
returnUrl | string | Yes | URL to return to after portal session |
Returns (PortalResponse):
| Field | Type | Description |
|---|---|---|
url | string | URL to redirect the customer to |
created | string | ISO timestamp when session was created |
getCustomer(email)
Get or create a Stripe customer by email address.
const customer = await hiveforge.billing.getCustomer('jane@example.com');
console.log('Customer ID:', customer.id); // cus_P1q2R3s4T5u6V7w8
console.log('Email:', customer.email);
console.log('Created:', new Date(customer.created * 1000));Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
email | string | Yes | Customer email address |
Returns:
| Field | Type | Description |
|---|---|---|
id | string | Stripe customer ID |
email | string | Customer email |
created | number | Unix timestamp of creation |
listPrices(options?)
List available Stripe prices, optionally filtered by product.
const prices = await hiveforge.billing.listPrices({
activeOnly: true,
});
for (const price of prices) {
const amount = (price.unit_amount / 100).toFixed(2);
const interval = price.recurring?.interval ?? 'one-time';
console.log(`${price.nickname ?? price.id}: $${amount}/${interval}`);
}Parameters:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
productId | string | No | -- | Filter by Stripe product ID |
activeOnly | boolean | No | -- | Only return active prices |
Returns: Array<Price> where each price has:
| Field | Type | Description |
|---|---|---|
id | string | Stripe price ID |
product | string | Stripe product ID |
unit_amount | number | Price in cents |
currency | string | Currency code (e.g. 'usd') |
recurring | { interval, interval_count } | null | Recurring details or null for one-time |
nickname | string | null | Human-readable name |
active | boolean | Whether price is active |
redirectToCheckout(options)
Helper that creates a checkout session and immediately redirects the browser. Only works in browser environments.
// This will redirect -- execution does not continue past this call
await hiveforge.billing.redirectToCheckout({
priceId: 'price_1N2b3c4D5e6F7g8H9i0J',
customerEmail: 'jane@example.com',
successUrl: '/welcome',
cancelUrl: '/pricing',
});Parameters: Same as createCheckout().
Returns: Promise<never> -- always redirects or throws.
redirectToPortal(options)
Helper that creates a portal session and immediately redirects the browser.
await hiveforge.billing.redirectToPortal({
customerId: 'cus_P1q2R3s4T5u6V7w8',
returnUrl: '/account',
});Parameters: Same as createPortal().
Returns: Promise<never> -- always redirects or throws.
isEnabled()
Check if billing is enabled for the current tier (reads from cached entitlements).
if (hiveforge.billing.isEnabled()) {
// Show pricing UI
}Returns: boolean
Full Example: Pricing Page
import { HiveForgeClient, BillingProxyException } from '@producthacker/hiveforge-sdk';
const hiveforge = new HiveForgeClient({
deploymentId: process.env.HIVEFORGE_DEPLOYMENT_ID!,
deploymentSecret: process.env.HIVEFORGE_DEPLOYMENT_SECRET!,
});
await hiveforge.initialize();
async function showPricingPage() {
if (!hiveforge.billing.isEnabled()) {
console.log('Billing not available on current tier');
return;
}
// Fetch active prices
const prices = await hiveforge.billing.listPrices({ activeOnly: true });
// Display prices to user...
return prices;
}
async function handleSubscribe(priceId: string, email: string) {
try {
const checkout = await hiveforge.billing.createCheckout({
priceId,
customerEmail: email,
successUrl: `${window.location.origin}/welcome`,
cancelUrl: `${window.location.origin}/pricing`,
});
window.location.href = checkout.url;
} catch (error) {
if (error instanceof BillingProxyException) {
console.error(`Billing error [${error.code}]: ${error.message}`);
}
throw error;
}
}
async function handleManageSubscription(customerId: string) {
try {
await hiveforge.billing.redirectToPortal({
customerId,
returnUrl: `${window.location.origin}/account`,
});
} catch (error) {
if (error instanceof BillingProxyException) {
console.error(`Portal error [${error.code}]: ${error.message}`);
}
throw error;
}
}