Strimz
Concepts

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 before nextChargeAt (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_risk
  • subscription.charge_failed webhook
  • subscription.lapsed webhook (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.

attempt 1 → fail → wait 1m   → attempt 2 → fail → wait 5m
attempt 3 → fail → wait 30m  → attempt 4 → fail → wait 2h
attempt 5 → fail → permanently_failed

After permanent failure:

  1. Strimz emails the merchant with the delivery ID, last response, and last error.
  2. 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.
  3. The delivery row stays in your WebhookDelivery table with status='permanently_failed' and lastError for triage. You can manually replay via POST /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.

On this page