Billing API

The Billing API manages subscription plans, payment methods, invoices, and usage tracking. Billing is handled through an external billing service (Switch Labs).

Subscription Object

{
  id: string;                    // Subscription ID
  organization_id: string;       // UUID of the organization
  plan: string;                  // Plan tier: 'free', 'pro', 'business'
  status: string;                // 'active', 'trialing', 'past_due', 'canceled'
  current_period_start: string;  // ISO timestamp
  current_period_end: string;    // ISO timestamp
  cancel_at_period_end: boolean; // Whether subscription will cancel at period end
  seats: number;                 // Number of agent seats
  created_at: string;            // ISO timestamp
}

Plan Tiers

PlanDescription
freeFree tier with basic features
proProfessional tier with advanced features
businessBusiness tier with all features

Get Subscription Status

Retrieve the current subscription status.

Procedure: billing.getSubscriptionStatus

Authentication: Required (Admin)

Input: None

Example:

curl -X GET "https://your-domain.com/api/trpc/billing.getSubscriptionStatus" \
  -H "Cookie: your-session-cookie"

Response:

{
  "result": {
    "data": {
      "json": {
        "id": "sub_123",
        "plan": "pro",
        "status": "active",
        "current_period_start": "2024-01-01T00:00:00.000Z",
        "current_period_end": "2024-02-01T00:00:00.000Z",
        "cancel_at_period_end": false,
        "seats": 5,
        "features": {
          "ai_enabled": true,
          "automation_limit": 50,
          "integration_limit": 10,
          "sla_enabled": true,
          "custom_domain": true
        }
      }
    }
  }
}

Get Invoices

Retrieve billing history and invoices.

Procedure: billing.getInvoices

Authentication: Required (Admin)

Input:

{
  limit?: number;  // 1-100, default: 10
}

Example:

curl -X GET "https://your-domain.com/api/trpc/billing.getInvoices?input=%7B%22limit%22:20%7D" \
  -H "Cookie: your-session-cookie"

Response:

{
  "result": {
    "data": {
      "json": [
        {
          "id": "inv_123",
          "number": "INV-2024-001",
          "amount": 9900,
          "currency": "usd",
          "status": "paid",
          "period_start": "2024-01-01T00:00:00.000Z",
          "period_end": "2024-02-01T00:00:00.000Z",
          "paid_at": "2024-01-01T00:00:00.000Z",
          "pdf_url": "https://billing.example.com/invoices/inv_123.pdf"
        },
        {
          "id": "inv_122",
          "number": "INV-2023-012",
          "amount": 9900,
          "currency": "usd",
          "status": "paid",
          "period_start": "2023-12-01T00:00:00.000Z",
          "period_end": "2024-01-01T00:00:00.000Z",
          "paid_at": "2023-12-01T00:00:00.000Z",
          "pdf_url": "https://billing.example.com/invoices/inv_122.pdf"
        }
      ]
    }
  }
}

Initialize Subscription

Start a new subscription or upgrade plan. Admin only.

Procedure: billing.initializeSubscription

Authentication: Required (Admin)

Input:

{
  plan: 'pro' | 'business';  // Target plan
  seats?: number;            // Number of agent seats
}

Example:

curl -X POST "https://your-domain.com/api/trpc/billing.initializeSubscription" \
  -H "Content-Type: application/json" \
  -H "Cookie: your-session-cookie" \
  -d '{
    "json": {
      "plan": "pro",
      "seats": 5
    }
  }'

Response:

{
  "result": {
    "data": {
      "json": {
        "checkoutUrl": "https://billing.example.com/checkout/session_123",
        "sessionId": "session_123"
      }
    }
  }
}

Confirm Subscription

Confirm subscription after successful payment. Admin only.

Procedure: billing.confirmSubscription

Authentication: Required (Admin)

Input:

{
  sessionId: string;  // Checkout session ID
}

Example:

curl -X POST "https://your-domain.com/api/trpc/billing.confirmSubscription" \
  -H "Content-Type: application/json" \
  -H "Cookie: your-session-cookie" \
  -d '{"json":{"sessionId":"session_123"}}'

Response:

{
  "result": {
    "data": {
      "json": {
        "success": true,
        "subscription": {
          "id": "sub_123",
          "plan": "pro",
          "status": "active"
        }
      }
    }
  }
}

Get Update Card URL

Get a URL to update the payment method. Admin only.

Procedure: billing.getUpdateCardUrl

Authentication: Required (Admin)

Input: None

Example:

curl -X GET "https://your-domain.com/api/trpc/billing.getUpdateCardUrl" \
  -H "Cookie: your-session-cookie"

Response:

{
  "result": {
    "data": {
      "json": {
        "url": "https://billing.example.com/portal/session_456"
      }
    }
  }
}

Cancel Subscription

Cancel the current subscription. Admin only.

Procedure: billing.cancelSubscription

Authentication: Required (Admin)

Input:

{
  reason?: string;           // Cancellation reason
  immediate?: boolean;       // Cancel immediately vs end of period
}

Example:

curl -X POST "https://your-domain.com/api/trpc/billing.cancelSubscription" \
  -H "Content-Type: application/json" \
  -H "Cookie: your-session-cookie" \
  -d '{
    "json": {
      "reason": "Switching to competitor",
      "immediate": false
    }
  }'

Response:

{
  "result": {
    "data": {
      "json": {
        "success": true,
        "cancel_at": "2024-02-01T00:00:00.000Z",
        "message": "Subscription will cancel at the end of the billing period"
      }
    }
  }
}

Reactivate Subscription

Reactivate a canceled subscription before it ends. Admin only.

Procedure: billing.reactivateSubscription

Authentication: Required (Admin)

Input: None

Example:

curl -X POST "https://your-domain.com/api/trpc/billing.reactivateSubscription" \
  -H "Content-Type: application/json" \
  -H "Cookie: your-session-cookie" \
  -d '{"json":{}}'

Response:

{
  "result": {
    "data": {
      "json": {
        "success": true,
        "subscription": {
          "id": "sub_123",
          "status": "active",
          "cancel_at_period_end": false
        }
      }
    }
  }
}

Get Payment Methods

List saved payment methods. Admin only.

Procedure: billing.getPaymentMethods

Authentication: Required (Admin)

Input: None

Example:

curl -X GET "https://your-domain.com/api/trpc/billing.getPaymentMethods" \
  -H "Cookie: your-session-cookie"

Response:

{
  "result": {
    "data": {
      "json": [
        {
          "id": "pm_123",
          "type": "card",
          "card": {
            "brand": "visa",
            "last4": "4242",
            "exp_month": 12,
            "exp_year": 2025
          },
          "is_default": true
        }
      ]
    }
  }
}

Get Usage Stats

Get current usage statistics against plan limits. Admin only.

Procedure: billing.getUsageStats

Authentication: Required (Admin)

Input: None

Example:

curl -X GET "https://your-domain.com/api/trpc/billing.getUsageStats" \
  -H "Cookie: your-session-cookie"

Response:

{
  "result": {
    "data": {
      "json": {
        "agents": {
          "used": 3,
          "limit": 5,
          "percentage": 60
        },
        "tickets_this_month": {
          "count": 450,
          "limit": null
        },
        "ai_requests": {
          "used": 150,
          "limit": 1000,
          "percentage": 15
        },
        "automations": {
          "used": 12,
          "limit": 50,
          "percentage": 24
        },
        "storage_mb": {
          "used": 256,
          "limit": 5000,
          "percentage": 5
        }
      }
    }
  }
}

Subscription Statuses

StatusDescription
activeSubscription is active and paid
trialingIn free trial period
past_duePayment failed, grace period
canceledSubscription canceled
incompleteWaiting for initial payment

Webhooks

Billing events are received via webhook at /api/webhooks/stripe. See the Webhooks documentation for event handling details.

Billing Webhook Events

EventDescription
subscription.createdNew subscription started
subscription.updatedPlan or seats changed
subscription.canceledSubscription canceled
invoice.paidPayment successful
invoice.payment_failedPayment failed

Error Codes

CodeDescription
FORBIDDENOnly admins can manage billing
PAYMENT_REQUIREDPayment method required
SUBSCRIPTION_NOT_FOUNDNo active subscription
ALREADY_SUBSCRIBEDAlready have an active subscription
BILLING_ERRORExternal billing service error