Escalation Timeline
When a tenant's payment fails, the Billing Service applies a progressive escalation timeline before considering any data removal. The process provides at least 37 days and 5 or more notifications before any soft-delete begins.
Data safety guarantee: The platform never silently deletes tenant data. Termination only begins after the full escalation period has elapsed. Payment at any stage before completed termination restores full access instantly.
Overview
| Stage | Timeframe | Status | Access |
|---|---|---|---|
| Grace Period | Days 0 – 7 after missed payment | past_due | Full access (read + write) |
| Suspended | Days 8 – 37 | suspended | Read-only. Money operations exempt. |
| Terminated | Day 38+ | terminated | All access revoked. Async soft-delete starts. |
| Payment received | Any stage before termination completes | — | Instant reactivation → active |
Stage 1: Grace Period (Days 0 – 7)
Status: past_due. The tenant continues operating with full access.
No requests are blocked. The Billing Service sends escalating
notifications through the Notify primitive:
| Day | Notification |
|---|---|
| Day 0 (payment failure) | Email + in-app: "Payment failed. Please update your payment method." |
| Day 2 | Email reminder: "Action required — payment overdue." |
| Day 4 | Email + in-app: "Your account will be suspended in 3 days." |
| Day 6 | Email + in-app: "Last chance — account suspends tomorrow." |
| Day 7 (end of grace) | Email + in-app: "Account suspended." → transition to suspended |
All 5+ notifications are delivered via kernel.notify().send() — the
Notify primitive's Tenant Owner and billing contacts.
Stage 2: Suspended (Days 8 – 37)
Status: suspended. The tenant is in read-only mode:
GET /api/v1/* → 200 OK (all read operations pass through)
POST /api/v1/* → 402 Payment Required (all writes blocked)
PATCH /api/v1/* → 402 Payment Required
DELETE /api/v1/* → 402 Payment Required
EXCEPTION — Money operations always pass:
POST /api/v1/money/credit → 200 OK
POST /api/v1/money/debit → 200 OK
POST /api/v1/money/hold → 200 OK
POST /api/v1/money/transfer → 200 OK
POST /api/v1/money/cancel → 200 OK
FinCEN exemption: Wallet balances belong to users, not to the platform. Blocking fund movements during a billing dispute creates liability under FinCEN (Financial Crimes Enforcement Network) regulations. The platform does not hold user funds hostage for its own payment issues. Termination (day 38+) blocks even Money operations.
402 Response During Suspension
{
"type": "https://api.septemcore.com/problems/subscription-suspended",
"title": "Payment Required",
"status": 402,
"detail": "Your subscription is suspended due to a failed payment. The platform is in read-only mode. Update your payment method to restore full access.",
"instance": "/api/v1/data/records",
"traceId": "01j9ptr0000000000000010"
}
Notifications continue during suspension:
| Day | Notification |
|---|---|
| Day 8 | Email + in-app: "Account suspended. Data is safe. Pay to restore." |
| Day 15 | Email: "Your account has been suspended for 7 days." |
| Day 30 | Email + in-app: "Warning — termination in 7 days if payment is not received." |
| Day 37 | Email + in-app: "Final warning — account terminates tomorrow." |
Stage 3: Terminated (Day 38+)
Status: terminated. All requests return 402 — including Money
operations.
The termination process is a background async job — data is not deleted instantly:
Day 38: status → terminated (immediate)
All API requests: 402 Terminated
Background worker starts async soft-delete pipeline:
Phase 1: deleting_records (PostgreSQL soft-delete, 12–24h)
Phase 2: deleting_files (S3 object deletion, 12–24h)
Phase 3: deleting_cdn (CDN asset purge)
Phase 4: completed
Total expected duration: 24–48 hours
Termination Status API
GET https://api.septemcore.com/v1/admin/tenants/01j9ten0000000000000000/termination-status
Authorization: Bearer <platform-owner-token>
{
"tenantId": "01j9ten0000000000000000",
"status": "terminated",
"phase": "deleting_records",
"startedAt": "2026-04-22T00:00:00Z",
"estimatedCompletionAt": "2026-04-24T00:00:00Z"
}
phase values: deleting_records · deleting_files · deleting_cdn · completed
Recovery Before Completion
Recovery is possible up to and including phase deleting_files.
Once phase completed is reached, data is permanently deleted.
Recovery requires a Platform Owner action:
POST https://api.septemcore.com/v1/admin/tenants/01j9ten0000000000000000/restore
Authorization: Bearer <platform-owner-token>
Content-Type: application/json
{
"reason": "Customer paid outstanding balance."
}
Response 200 OK:
{
"tenantId": "01j9ten0000000000000000",
"status": "active",
"restoredAt": "2026-04-22T10:30:00Z"
}
Instant Reactivation on Payment
When a payment succeeds (via Stripe webhook invoice.paid), the
subscription transitions back to active immediately — regardless
of which escalation stage the tenant was in:
POST /api/v1/billing/webhooks/stripe
Event: invoice.paid
→ Billing: subscription status → active
→ Event Bus: billing.subscription.changed
→ Gateway: invalidate plan_info:{tenantId} cache
→ Next request: full access restored (no restart required)
If the tenant was in suspended mode, they regain write access on
the very next API request. If in terminated mode (before phase
completed), the soft-delete pipeline is halted and data is restored.