Subscription Lifecycle
Cargoman provides built-in support for subscription-based access control, designed to integrate with payment providers like Stripe.
Lifecycle States
┌──────────┐ ┌───────────┐ ┌─────────┐
│ Active │────▶│ Suspended │────▶│ Expired │
└──────────┘ └───────────┘ └─────────┘
│ │
│ ▼
│ ┌──────────┐
└──────────▶│ Frozen │
└──────────┘
Active
- Customer has full access to granted packages
- Normal operating state
Suspended
- Temporary block (e.g., payment failed)
- Used during grace period before cancellation
- Customer receives error when trying to download
Frozen
- Customer locked to specific versions
- Can still download frozen versions
- No access to newer releases
Expired
- Subscription fully cancelled
- No access to any packages
Integration with Stripe
Webhook Events
Handle Stripe webhooks to manage customer lifecycle:
// Stripe webhook handler (pseudo-code)
match event.type {
"customer.subscription.updated" => {
if subscription.status == "past_due" {
cargoman.suspend_customer(customer_id, "Payment past due");
}
},
"customer.subscription.deleted" => {
cargoman.freeze_customer(customer_id, current_versions);
// or: cargoman.expire_customer(customer_id);
},
"invoice.paid" => {
cargoman.reactivate_customer(customer_id);
}
}
Grace Period
Implement a grace period for failed payments:
- Payment fails -> Suspend customer
- Wait 7-14 days for retry
- If paid -> Reactivate
- If not paid -> Freeze or expire
Version Freezing
When freezing a customer, specify which versions they can access:
curl -X POST https://packages.example.com/api/v1/customers/cust_xyz789/freeze \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"versions": [
{"package": "vendor/core", "version": "2.5.0"},
{"package": "vendor/addon", "version": "1.2.0"}
]
}'
The customer can still download these specific versions but not newer ones.
Typical Flows
New Customer
- Customer signs up and pays
- Create customer in Cargoman with
external_id= Stripe customer ID - Grant package access
- Customer configures Composer
Payment Failure
- Stripe sends
invoice.payment_failedwebhook - Suspend customer with reason
- Customer sees error on
composer install - After grace period, freeze or expire
Subscription Renewal
- Stripe sends
invoice.paidwebhook - If suspended, reactivate customer
- Customer access restored
Cancellation
- Customer cancels in your dashboard
- Stripe sends
customer.subscription.deleted - Freeze customer to current versions
- Customer can still use existing code
API Reference
# Suspend
POST /api/v1/customers/{id}/suspend
Body: {"reason": "Payment failed"}
# Reactivate
POST /api/v1/customers/{id}/reactivate
# Freeze
POST /api/v1/customers/{id}/freeze
Body: {"versions": [...]}
# Get customer status
GET /api/v1/customers/{id}