Manages all Stripe billing operations for Unite-Hub including product/price creation, subscription management, checkout sessions, webhooks, and dual-mode (test/live) billing for staff vs. customer ...
Agent ID: unite-hub.stripe-agent
Model: claude-sonnet-4-5-20250929
MCP Server: stripe (via @stripe/mcp)
Manages all Stripe billing operations for Unite-Hub including product/price creation, subscription management, checkout sessions, webhooks, and dual-mode (test/live) billing for staff vs. customer separation.
Create Products
// Create a product for a pricing tier
mcp__stripe__create_product({
name: "Unite Hub Professional",
description: "Full CRM and AI marketing automation",
metadata: {
tier: "professional",
features: "unlimited_contacts,ai_scoring,drip_campaigns"
}
})
Create Prices
// Monthly price (AUD, GST included)
mcp__stripe__create_price({
product: "prod_xxx",
unit_amount: 89500, // $895.00 AUD in cents
currency: "aud",
recurring: { interval: "month" },
metadata: { tier: "professional", billing: "monthly", gst_included: "true" }
})
// Annual price (AUD, GST included)
mcp__stripe__create_price({
product: "prod_xxx",
unit_amount: 895000, // $8,950.00 AUD (2 months free)
currency: "aud",
recurring: { interval: "year" },
metadata: { tier: "professional", billing: "annual", gst_included: "true" }
})
Create Checkout Session
mcp__stripe__create_checkout_session({
mode: "subscription",
customer_email: "customer@example.com",
line_items: [{
price: "price_xxx",
quantity: 1
}],
success_url: "https://synthex.social/dashboard?success=true",
cancel_url: "https://synthex.social/pricing?cancelled=true",
metadata: {
workspace_id: "uuid",
tier: "professional"
}
})
List Subscriptions
mcp__stripe__list_subscriptions({
customer: "cus_xxx",
status: "active"
})
Update Subscription (upgrade/downgrade)
// Via API route, update subscription items
// Switch from starter to professional price
Cancel Subscription
// Via API route with proper handling
// Options: immediate or at_period_end
Create Customer
mcp__stripe__create_customer({
email: "new@customer.com",
name: "John Doe",
metadata: {
user_id: "uuid",
workspace_id: "uuid"
}
})
List Customers
mcp__stripe__list_customers({
email: "customer@example.com"
})
List Invoices
mcp__stripe__list_invoices({
customer: "cus_xxx",
status: "paid"
})
Create Invoice
mcp__stripe__create_invoice({
customer: "cus_xxx",
auto_advance: true,
metadata: {
workspace_id: "uuid"
}
})
Unite-Hub uses a dual-mode billing system to separate staff testing from real customer payments.
// From src/lib/billing/stripe-router.ts
// TEST Mode triggers:
// 1. Staff roles: founder, staff_admin, internal_team, super_admin
// 2. Registered sandbox emails (SANDBOX_STAFF_REGISTRY)
// 3. Internal domains: unite-group.in, disasterrecoveryqld.au, carsi.com.au
// LIVE Mode:
// All other users (real customers)
# TEST Mode (for staff/internal)
STRIPE_TEST_SECRET_KEY=sk_test_...
STRIPE_TEST_WEBHOOK_SECRET=whsec_test_...
STRIPE_TEST_PRICE_STARTER=price_...
STRIPE_TEST_PRICE_PRO=price_...
STRIPE_TEST_PRICE_ELITE=price_...
NEXT_PUBLIC_STRIPE_TEST_PUBLISHABLE_KEY=pk_test_...
# LIVE Mode (for customers)
STRIPE_LIVE_SECRET_KEY=sk_live_...
STRIPE_LIVE_WEBHOOK_SECRET=whsec_live_...
STRIPE_LIVE_PRICE_STARTER=price_...
STRIPE_LIVE_PRICE_PRO=price_...
STRIPE_LIVE_PRICE_ELITE=price_...
NEXT_PUBLIC_STRIPE_LIVE_PUBLISHABLE_KEY=pk_live_...
| Tier | Monthly | Annual | Features | |------|---------|--------|----------| | Starter | $495 | $4,950 | Basic CRM, 500 contacts, Email integration | | Professional | $895 | $8,950 | Full CRM, Unlimited contacts, AI scoring, Drip campaigns | | Elite | $1,295 | $12,950 | Everything + White-label, Priority support, Custom integrations |
Currency: Australian Dollars (AUD) Tax: All prices include 10% GST
Trigger: "Setup Stripe products" or first-time billing initialization
Steps:
Output:
{
"products": {
"starter": "prod_xxx",
"professional": "prod_yyy",
"elite": "prod_zzz"
},
"prices": {
"starter_monthly": "price_xxx",
"starter_annual": "price_xxy",
"professional_monthly": "price_yyy",
"professional_annual": "price_yyz",
"elite_monthly": "price_zzz",
"elite_annual": "price_zza"
}
}
Trigger: User clicks "Subscribe" on pricing page
Input:
{
"email": "user@example.com",
"tier": "professional",
"billing": "monthly",
"workspaceId": "uuid",
"userId": "uuid"
}
Steps:
Trigger: User clicks "Upgrade" in billing settings
Input:
{
"currentTier": "starter",
"targetTier": "professional",
"subscriptionId": "sub_xxx",
"workspaceId": "uuid"
}
Steps:
Trigger: Stripe webhook received
Events Handled:
checkout.session.completed → Activate subscriptioncustomer.subscription.created → Create subscription recordcustomer.subscription.updated → Update tier, sync statuscustomer.subscription.deleted → Deactivate subscriptioninvoice.paid → Mark paid, extend accessinvoice.payment_failed → Flag account, send notificationTrigger: "Generate billing report" or scheduled monthly
Output:
{
"period": "2025-11",
"revenue": {
"total": 15890.00,
"byTier": {
"starter": 4850.00,
"professional": 8910.00,
"elite": 2130.00
}
},
"subscriptions": {
"active": 87,
"new": 12,
"churned": 3,
"mrr": 15890.00
},
"trials": {
"active": 23,
"converted": 8,
"expired": 5
}
}
Trigger: "Audit Stripe setup" or health check
Checks:
Output:
{
"status": "healthy" | "degraded" | "critical",
"checks": {
"env_vars": { "status": "pass", "missing": [] },
"products": { "status": "pass", "count": 3 },
"prices": { "status": "pass", "count": 6 },
"webhooks": { "status": "warn", "message": "Live webhook not configured" }
},
"recommendations": [
"Add STRIPE_LIVE_WEBHOOK_SECRET to production environment"
]
}
https://your-domain.com/api/webhooks/stripe/testSTRIPE_TEST_WEBHOOK_SECREThttps://your-domain.com/api/webhooks/stripe/liveSTRIPE_LIVE_WEBHOOK_SECRET| Error | Cause | Resolution |
|-------|-------|------------|
| StripeCardError | Card declined | Notify customer, request new card |
| StripeInvalidRequestError | Bad API call | Check parameters, log for debugging |
| StripeAuthenticationError | Invalid API key | Verify environment variables |
| StripeRateLimitError | Too many requests | Implement exponential backoff |
const MAX_RETRIES = 3;
const RETRY_DELAYS = [1000, 2000, 4000]; // Exponential backoff
async function stripeWithRetry(operation) {
for (let i = 0; i < MAX_RETRIES; i++) {
try {
return await operation();
} catch (error) {
if (error.type === 'StripeRateLimitError' && i < MAX_RETRIES - 1) {
await sleep(RETRY_DELAYS[i]);
continue;
}
throw error;
}
}
}
Orchestrator
├─→ [On new signup] → Stripe Agent: Create customer
├─→ [On upgrade request] → Stripe Agent: Process upgrade
├─→ [On webhook] → Stripe Agent: Handle event
└─→ [On audit] → Stripe Agent: Audit configuration
After Stripe operations, sync to Supabase:
// After successful subscription
await supabase.from('subscriptions').upsert({
workspace_id: workspaceId,
stripe_customer_id: customerId,
stripe_subscription_id: subscriptionId,
tier: tier,
status: 'active',
current_period_end: periodEnd
});
| Card Number | Scenario |
|-------------|----------|
| 4242424242424242 | Success |
| 4000000000000002 | Decline |
| 4000000000009995 | Insufficient funds |
| 4000002500003155 | 3D Secure required |
# Trigger test webhook
stripe trigger checkout.session.completed
# Listen for webhooks locally
stripe listen --forward-to localhost:3008/api/webhooks/stripe/test
| File | Purpose |
|------|---------|
| src/lib/billing/stripe-router.ts | Dual-mode routing logic |
| src/lib/billing/pricing-config.ts | Pricing tier definitions |
| src/lib/payments/stripeClient.ts | Stripe client wrapper |
| src/app/api/billing/subscription/route.ts | Subscription API |
| src/app/api/webhooks/stripe/[mode]/route.ts | Webhook handlers |
| src/app/api/stripe/checkout/route.ts | Checkout session creation |
# Run Stripe setup script (to be created)
npm run stripe:setup
# Audit Stripe configuration
npm run stripe:audit
# Sync products from Stripe
npm run stripe:sync
# Test webhook locally
npm run stripe:webhook-test
Skill file created: 2025-11-28
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer