Modes of failure
What can go wrong, what you'll see when it does, and what Strimz does about it automatically.
Things break. Network calls fail, customers cancel mid-flow, on-chain transactions get stuck. This page lists the failure modes Strimz already handles, what surfaces in each case, and where the automatic recovery stops.
A subscription charge fails
The contract emits SubscriptionChargeSkipped(subId, attemptId, outcome) with one of:
InsufficientFunds. Payer's USDC balance was below the charge amount.RevokedApproval. Payer revoked the contract's allowance to move their USDC.Cancelled. The subscription is already cancelled (race; rare).NotDue. The scheduler tried to charge beforenextChargeAt(defensive; the contract rejects).
The indexer projects this into SubscriptionCharge(status: failed, outcome: <enum>) and flips the Subscription to at_risk. The agent's recovery capability (if enabled) emails the customer per your recoveryStrategy. If the grace window expires without success, the agent's subscription-lapsed cron flips the sub to lapsed and fires subscription.lapsed.
You'll see this in:
GET /v1/subscriptions?status=at_risksubscription.charge_failedwebhooksubscription.lapsedwebhook (after grace)- The agent activity log under
recovery_notification_sent
A webhook delivery fails
Strimz POSTs the event to your URL with a 10-second timeout. Anything other than 2xx, including network errors, counts as a failure.
After permanent failure:
- Strimz emails the merchant with the delivery ID, last response, and last error.
- If the same endpoint has had 5+ permanent failures in 24 hours, the endpoint auto-disables (status:
disabled) and a separate notice goes out. You re-enable from the dashboard. - The delivery row stays in your
WebhookDeliverytable withstatus='permanently_failed'andlastErrorfor triage. You can manually replay viaPOST /v1/webhook-deliveries/:id/replay.
The on-chain payment is broadcast but doesn't confirm
Edge case: the scheduler's batchCharge tx hits the mempool, then a chain reorg orphans it. The indexer's confirmation depth (CONFIRMATIONS=5 by default) prevents projecting until the tx has 5+ blocks of finality. If a reorg drops a tx, the indexer never projects it; the scheduler's next sweep retries. The chargeAttemptId idempotency check on the contract handles the replay safely.
A customer cancels their subscription on-chain (without telling you)
The contract emits SubscriptionCancelled(subId, by). The indexer projects Subscription.status = cancelled and cancellationReason = 'on-chain cancel by 0x… in tx 0x…'. You'll receive subscription.cancelled webhook.
A refund tx is signed but never broadcast
The merchant created a refund (status: awaiting_signature), got wallet-signing instructions, but didn't follow through. The refund stays in awaiting_signature until manually voided (cancel via dashboard) or the merchant does eventually broadcast.
If they broadcast but submit the wrong tx hash to
POST /v1/refunds/:id/signature, the indexer's ERC-20 matcher
finds no corresponding Transfer event and the row sits in
submitted. Re-submit the correct hash to fix it; the row updates
idempotently.
API key leaks
Strimz scans public GitHub for live-mode key prefixes. If yours is found, the key is auto-revoked and you get an email within minutes. The old key returns authentication_error immediately. Audit logs show every action the key took before revocation.
What's not currently automated
These are real failure modes you should still build for:
- Customer's wallet permanently loses access (lost seed phrase, hardware wallet bricked). Their subscription will keep failing until they re-create a wallet and re-subscribe. There's no Strimz-side way to "transfer" a subscription to a new wallet. The on-chain authorisation is gone.
- Strimz API is down. Strimz is a single hosted service today. Outage equals downtime. The 99.9% / 99.99% SLAs on the Growth/Enterprise plans are real, but a Free-plan account isn't covered. The on-chain layer keeps working. Payments via direct contract calls still settle.
- Arc network outage. Same idea: this is a chain-level event. Strimz inherits Arc's availability.
For anything not on this page, open an issue. New failure modes and their recovery get documented here as they come up.
