Audit failed Stripe payments in DynamoDB with a Slack triage note

By General Input

When a Stripe charge fails, save the failure to your DynamoDB audit table with duplicate protection and post a Slack triage line that says how worried to be.

Integrations

  • Amazon DynamoDB
  • Stripe
  • Slack Bot

Type

Agentic Task

Categories

  • Finance
  • Operations

When Stripe fires a charge.failed webhook, log the failure to a DynamoDB audit table and post a triage line to the finance Slack channel that classifies how worried we should be.

Trigger: Stripe webhook, event type charge.failed. The event payload includes the failed charge id, customer id, amount, and failure reason.

Steps:

  1. Read the charge id, customer id, amount, and failure reason from the charge.failed event payload.

  2. Use Stripe Retrieve Customer with that customer id to pull the customer's name and email.

  3. Use Stripe List Charges filtered by that customer id and a created timestamp in the last 90 days, so we can see prior successes and failures in that window. Count the failures (status = failed) for use in the classification and the audit row.

  4. Use Amazon DynamoDB Query against the payment_failures table with a KeyConditionExpression on the customer_id partition key, to fetch any prior failure rows already on file for this customer.

  5. Use Amazon DynamoDB Put Item to write a new row to payment_failures with customer_id as the partition key, charge_id as the sort key, and the following attributes: amount, failure_reason, customer_id, timestamp (event created), and prior_90d_failures (the count from step 3). Set ConditionExpression to attribute_not_exists(charge_id) so a retried webhook cannot double-write. If DynamoDB returns ConditionalCheckFailedException, treat it as an already-logged duplicate: stop the workflow cleanly and do NOT post to Slack again.

  6. Use Slack Bot Send a Message to post a single-line triage note to the finance channel. Include the customer name, the amount, the failure reason, and a link to the Stripe dashboard entry at https://dashboard.stripe.com/payments/{charge_id}. Prefix the note with exactly one of these three classifications:

    • "first time, likely a card issue" — the customer has zero prior failures in the last 90 days AND is not over the high-value threshold.

    • "recurring, dunning candidate" — the customer has one or more prior 90-day failures AND is not over the high-value threshold.

    • "high-value customer, human review" — the customer's lifetime revenue exceeds the configurable threshold, regardless of prior failure count.

Computing lifetime revenue: sum the amount of all succeeded charges returned by Stripe List Charges for the customer. If you already carry lifetime revenue elsewhere, use that instead.

Rules:

  • Never DM the customer directly. This workflow is internal only. No Stripe emails, no SMS, no customer-facing messages.

  • Only escalate to "high-value customer, human review" when lifetime revenue exceeds the configured threshold.

  • If Put Item's ConditionExpression fails (ConditionalCheckFailedException), stop the workflow. Do not re-post to Slack. This is the expected idempotency path for retried Stripe webhooks.

  • The DynamoDB table must exist ahead of time with customer_id as the partition key and charge_id as the sort key.

Configurables:

  • financeChannelId — the Slack channel id the triage note is posted to.

  • highValueRevenueThresholdUsd — lifetime revenue above which a customer is escalated to human review. Default: 10000.

  • lookbackDays — window used to count prior failures and successes. Default: 90.

  • tableName — DynamoDB table name. Default: payment_failures.

Related prompts

Explore more prompts
Let support send one-off Loops emails without an engineerA brand asset library your marketing team actually searchesTurn Mailjet email clicks into ranked HubSpot follow-upsClean out the Looker dashboards and Looks nobody opensLiveKit live operations console for room moderationWake up dormant Keap leads with a researched reasonCustomer lifecycle inspector for Loops, Stripe and PostHogLiveChat coverage board for planning next week's shiftsPhone routing control panel for LiveKit voice agentsLinkedIn Ads budget pacing dashboard for every client account