Skip to main content

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

StageTimeframeStatusAccess
Grace PeriodDays 0 – 7 after missed paymentpast_dueFull access (read + write)
SuspendedDays 8 – 37suspendedRead-only. Money operations exempt.
TerminatedDay 38+terminatedAll access revoked. Async soft-delete starts.
Payment receivedAny stage before termination completesInstant 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:

DayNotification
Day 0 (payment failure)Email + in-app: "Payment failed. Please update your payment method."
Day 2Email reminder: "Action required — payment overdue."
Day 4Email + in-app: "Your account will be suspended in 3 days."
Day 6Email + 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:

DayNotification
Day 8Email + in-app: "Account suspended. Data is safe. Pay to restore."
Day 15Email: "Your account has been suspended for 7 days."
Day 30Email + in-app: "Warning — termination in 7 days if payment is not received."
Day 37Email + 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.