> ## Documentation Index
> Fetch the complete documentation index at: https://learn.actionist.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Stripe

> Automate payments, subscriptions, and billing events — connect Stripe to Actionist and handle every revenue moment before it becomes a problem.

<div className="mxp-hero xc-border">
  <div className="exp-eyebrow mxp-rise">REVENUE AUTOMATION</div>

  <h2 className="mxp-hero-title mxp-rise" style={{animationDelay:'0.06s'}}>
    Every billing event handled <span style={{background:'linear-gradient(90deg,#24A4FF,#9000FF,#E3008E)',WebkitBackgroundClip:'text',backgroundClip:'text',color:'transparent'}}>before it becomes a problem.</span>
  </h2>

  <p className="mxp-hero-dek mxp-rise" style={{animationDelay:'0.13s'}}>
    Failed payments recovered before your inbox catches them. Subscriptions created the moment a deal closes. Month-end reconciled overnight while no one is in the office. Connect Stripe once — and your revenue operations never wait on a human again.
  </p>
</div>

<div className="w-full py-10">
  <div className="actionist-tight flex flex-col gap-2 mb-6">
    <span className="actionist-section-eyebrow">Live event stream</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">Watch a billing event become an automated action.</h2>

    <p className="text-base text-gray-600 dark:text-gray-400 max-w-3xl">
      A Stripe webhook fires. An Actionist trigger wakes the agent. The agent acts — before anyone reads a notification. Pick a trigger below and trace the full path.
    </p>
  </div>

  <div className="xast-stream exp-tool-shell xast-stream-shell xc-try">
    <div className="mxp-srch-chips">
      <label htmlFor="xast-t1"><input className="mxp-r" type="radio" name="xast-trig" id="xast-t1" defaultChecked />Invoice Paid</label>
      <label htmlFor="xast-t2"><input className="mxp-r" type="radio" name="xast-trig" id="xast-t2" />Failed Payment</label>
      <label htmlFor="xast-t3"><input className="mxp-r" type="radio" name="xast-trig" id="xast-t3" />Canceled Subscription</label>
      <label htmlFor="xast-t4"><input className="mxp-r" type="radio" name="xast-trig" id="xast-t4" />New Dispute</label>
    </div>

    {/* ── Invoice Paid ── */}

    <div className="xast-echo xast-e1">trigger · invoice.payment\_succeeded</div>

    <div className="xast-panel xast-p1">
      <div className="mxp-window" style={{marginTop:4}}>
        <div className="mxp-window-bar">
          <span className="mxp-window-dot" />

          <span className="mxp-window-dot" />

          <span className="mxp-window-dot" />

          <span className="mxp-window-title">agent · finance-bot · invoice paid · 14:07</span>
        </div>

        <div className="mxp-window-body" style={{minHeight:'auto',padding:'14px 18px'}}>
          <div className="mxp-s1"><span className="mxp-stream-event">webhook · invoice.payment\_succeeded · inv\_3QxN8…</span></div>
          <div className="mxp-stream-line mxp-s2"><span className="mxp-stream-time">14:07</span><span className="mxp-stream-text">Invoice <em>inv\_3QxN8K2eZvKYlo</em> paid — <em>\$1,200</em> — customer <em>cus\_Northwind</em>.</span></div>
          <div className="mxp-stream-line mxp-s3"><span className="mxp-stream-time">14:07</span><span className="mxp-stream-text">Posting payment summary to <em>#revenue</em> Slack channel.</span></div>
          <div className="mxp-s4"><span className="mxp-stream-event">tool · slack\_post\_message · #revenue</span></div>
          <div className="mxp-stream-line mxp-s5"><span className="mxp-stream-time">14:07</span><span className="mxp-stream-text">Slack posted. Updating CRM record for <em>Northwind</em> — last payment date and amount.</span></div>
          <div className="mxp-s6"><span className="mxp-stream-event">tool · crm\_update\_record · northwind</span></div>
          <div className="mxp-stream-line mxp-s7"><span className="mxp-stream-time">14:08</span><span className="mxp-stream-text">Done. CRM updated. Invoice marked as processed in tracker.<span className="mxp-caret" /></span></div>
        </div>
      </div>

      <div className="mxs-match" style={{marginTop:10}}>
        <strong>Invoice Paid</strong> fires on every successful payment. Route it to a Finance Agent that posts a summary to Slack, updates the CRM, and appends a row to the reconciliation tracker — zero manual touchpoints.
      </div>
    </div>

    {/* ── Failed Payment ── */}

    <div className="xast-echo xast-e2">trigger · invoice.payment\_failed</div>

    <div className="xast-panel xast-p2">
      <div className="mxp-window" style={{marginTop:4}}>
        <div className="mxp-window-bar">
          <span className="mxp-window-dot" />

          <span className="mxp-window-dot" />

          <span className="mxp-window-dot" />

          <span className="mxp-window-title">agent · dunning-bot · payment failed · 09:22</span>
        </div>

        <div className="mxp-window-body" style={{minHeight:'auto',padding:'14px 18px'}}>
          <div className="mxp-s1"><span className="mxp-stream-event">webhook · invoice.payment\_failed · inv\_4R2Zp9…</span></div>
          <div className="mxp-stream-line mxp-s2"><span className="mxp-stream-time">09:22</span><span className="mxp-stream-text">Payment failed for <em>cus\_Acme</em> — card ending <em>4242</em> declined. Invoice <em>\$840</em>.</span></div>
          <div className="mxp-stream-line mxp-s3"><span className="mxp-stream-time">09:22</span><span className="mxp-stream-text">Creating new Checkout Session for card update link.</span></div>
          <div className="mxp-s4"><span className="mxp-stream-event">tool · stripe\_create\_checkout\_session · cus\_Acme</span></div>
          <div className="mxp-stream-line mxp-s5"><span className="mxp-stream-time">09:22</span><span className="mxp-stream-text">Session created. Sending recovery email with update link.</span></div>
          <div className="mxp-s6"><span className="mxp-stream-event">tool · email\_send · [acme@example.com](mailto:acme@example.com)</span></div>
          <div className="mxp-stream-line mxp-s7"><span className="mxp-stream-time">09:23</span><span className="mxp-stream-text">Recovery email sent. Attempt logged to memory.<span className="mxp-caret" /></span></div>
        </div>
      </div>

      <div className="mxs-match" style={{marginTop:10}}>
        <strong>Failed Payment</strong> is the highest-ROI trigger. The agent detects the failure, creates a fresh Checkout Session link, sends a card-update email, and logs the attempt — all before a human reads the notification.
      </div>
    </div>

    {/* ── Canceled Subscription ── */}

    <div className="xast-echo xast-e3">trigger · customer.subscription.deleted</div>

    <div className="xast-panel xast-p3">
      <div className="mxp-window" style={{marginTop:4}}>
        <div className="mxp-window-bar">
          <span className="mxp-window-dot" />

          <span className="mxp-window-dot" />

          <span className="mxp-window-dot" />

          <span className="mxp-window-title">agent · churn-bot · subscription canceled · 11:15</span>
        </div>

        <div className="mxp-window-body" style={{minHeight:'auto',padding:'14px 18px'}}>
          <div className="mxp-s1"><span className="mxp-stream-event">webhook · customer.subscription.deleted · sub\_7Tx…</span></div>
          <div className="mxp-stream-line mxp-s2"><span className="mxp-stream-time">11:15</span><span className="mxp-stream-text">Subscription <em>Pro Monthly</em> canceled — customer <em>cus\_Homebase</em>. Plan value: <em>\$299/mo</em>.</span></div>
          <div className="mxp-stream-line mxp-s3"><span className="mxp-stream-time">11:15</span><span className="mxp-stream-text">Issuing personalised win-back coupon — <em>30% off for 3 months</em>.</span></div>
          <div className="mxp-s4"><span className="mxp-stream-event">tool · stripe\_create\_coupon · homebase-winback-30</span></div>
          <div className="mxp-stream-line mxp-s5"><span className="mxp-stream-time">11:15</span><span className="mxp-stream-text">Coupon issued. Posting to <em>#churn-alerts</em> and booking CSM save call.</span></div>
          <div className="mxp-s6"><span className="mxp-stream-event">tool · calendar\_book · CSM · save-call · homebase</span></div>
          <div className="mxp-stream-line mxp-s7"><span className="mxp-stream-time">11:16</span><span className="mxp-stream-text">Save call booked. All actions complete in <em>under 60 seconds</em>.<span className="mxp-caret" /></span></div>
        </div>
      </div>

      <div className="mxs-match" style={{marginTop:10}}>
        <strong>Canceled Subscription</strong> fires on cancellation. The agent issues a coupon, posts to Slack, and books a renewal call on the CSM's calendar — all before the rep finishes reading the notification.
      </div>
    </div>

    {/* ── New Dispute ── */}

    <div className="xast-echo xast-e4">trigger · charge.dispute.created</div>

    <div className="xast-panel xast-p4">
      <div className="mxp-window" style={{marginTop:4}}>
        <div className="mxp-window-bar">
          <span className="mxp-window-dot" />

          <span className="mxp-window-dot" />

          <span className="mxp-window-dot" />

          <span className="mxp-window-title">agent · dispute-bot · new dispute · 08:03</span>
        </div>

        <div className="mxp-window-body" style={{minHeight:'auto',padding:'14px 18px'}}>
          <div className="mxp-s1"><span className="mxp-stream-event">webhook · charge.dispute.created · dp\_1P9m…</span></div>
          <div className="mxp-stream-line mxp-s2"><span className="mxp-stream-time">08:03</span><span className="mxp-stream-text">Dispute opened — <em>\$340</em> chargeback on <em>ch\_3Qx…</em>. Evidence deadline: <em>7 days</em>.</span></div>
          <div className="mxp-stream-line mxp-s3"><span className="mxp-stream-time">08:03</span><span className="mxp-stream-text">Retrieving original charge, order history, and delivery confirmation.</span></div>
          <div className="mxp-s4"><span className="mxp-stream-event">tool · stripe\_retrieve\_charge · ch\_3Qx…</span></div>
          <div className="mxp-stream-line mxp-s5"><span className="mxp-stream-time">08:04</span><span className="mxp-stream-text">Evidence package assembled. Alerting <em>#disputes</em> with summary and deadline.</span></div>
          <div className="mxp-s6"><span className="mxp-stream-event">tool · slack\_post\_message · #disputes</span></div>
          <div className="mxp-stream-line mxp-s7"><span className="mxp-stream-time">08:04</span><span className="mxp-stream-text">Alert sent. Evidence ready to submit. <em>7 days</em> on the clock.<span className="mxp-caret" /></span></div>
        </div>
      </div>

      <div className="mxs-match" style={{marginTop:10}}>
        <strong>New Dispute</strong> is time-sensitive — evidence windows are short. Route it to an agent that has the original charge context, assembles evidence, and alerts the right team immediately.
      </div>
    </div>
  </div>
</div>

<div className="w-full py-10 xc-rise">
  <div className="actionist-tight flex flex-col gap-2 mb-6">
    <span className="actionist-section-eyebrow">What changes</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">Every billing event handled before it becomes a problem.</h2>
  </div>

  <Columns cols={2}>
    <Card title="Zero-touch dunning" icon="rotate-ccw">
      A failed-payment webhook fires in real time. The agent detects the failure, sends a card-update email with a new Checkout Session link, and logs the attempt — before a human checks their inbox.
    </Card>

    <Card title="Billing in 30 seconds" icon="zap">
      A closed-deal message lands in Slack. The agent reads it, looks up the customer record, creates the subscription in Stripe, and logs the Stripe ID back to the CRM tracker.
    </Card>

    <Card title="Month-end in minutes" icon="file-check">
      A scheduled agent pulls all balance transactions, categorises them by type, matches against the GL, flags anything unmatched, and appends the reconciliation row to the finance tracker — overnight, every month.
    </Card>

    <Card title="Churn response under 60 seconds" icon="heart-handshake">
      A cancelled-subscription event fires. The agent issues a personalised win-back coupon, posts to Slack, and books a renewal call on the CSM's calendar — all before the rep finishes reading the notification.
    </Card>
  </Columns>
</div>

<div className="w-full py-10 xc-rise">
  <div className="actionist-tight flex flex-col gap-2 mb-6">
    <span className="actionist-section-eyebrow">Setup</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">Connect Stripe.</h2>

    <p className="text-base text-gray-600 dark:text-gray-400 max-w-3xl">
      Actionist offers two connection methods. MCP is recommended — it uses Stripe's own OAuth flow, scoped to exactly what your agent needs. API Token is the alternative if you prefer key-based access.
    </p>
  </div>

  <Tabs>
    <Tab title="MCP (recommended)" icon="plug">
      <Steps>
        <Step title="Open the Stripe app">
          In the Actionist sidebar click <strong>Apps</strong>, find Stripe in the catalog, and open its detail page.
        </Step>

        <Step title="Click Connect Stripe">
          In the hero, click <strong>Connect Stripe</strong>. The install sheet opens with MCP pre-selected and a <strong>Recommended</strong> badge.
        </Step>

        <Step title="Authorise via OAuth">
          Click <strong>Connect</strong> inside the install sheet. Your browser opens Stripe's OAuth consent screen. Sign in and grant the requested scopes — Actionist receives read/write access for the Stripe objects your workflows need.
        </Step>

        <Step title="Verify and install">
          Actionist runs a read-only verification call to confirm the handshake. Once the check passes, the <strong>Install</strong> button becomes active. Click it — the hero badge updates to <strong>Installed</strong> / <strong>Connected</strong>.
        </Step>
      </Steps>
    </Tab>

    <Tab title="API Token" icon="key">
      <Steps>
        <Step title="Open the Stripe app">
          In the Actionist sidebar click <strong>Apps</strong>, find Stripe, and open its detail page.
        </Step>

        <Step title="Open the install sheet and switch method">
          Click <strong>Connect Stripe</strong>. In the install sheet, select the <strong>API Token</strong> option (the Recommended badge is on MCP, not this path).
        </Step>

        <Step title="Copy your Stripe secret key">
          In a separate tab open the Stripe Dashboard. Go to <strong>Developers → API keys</strong> and copy the Secret key (<code>sk\_live\_…</code> for production, <code>sk\_test\_…</code> for test mode). Store it somewhere safe — Stripe shows it only once.
        </Step>

        <Step title="Paste the key and test">
          Paste the key into the <strong>API token</strong> field in Actionist. Click <strong>Test connection</strong> — the agent reads your account balance to verify the key is valid.
        </Step>

        <Step title="Install">
          Click <strong>Install</strong> to complete. The hero badge updates to <strong>Installed</strong> / <strong>Connected</strong>.
        </Step>
      </Steps>
    </Tab>
  </Tabs>

  <Warning>
    Use a <strong>restricted key</strong>, not your full secret key. In the Stripe Dashboard under <strong>Developers → API keys → Restricted keys</strong>, create a key scoped to only the Stripe objects your workflows actually touch (for example, Customers + Subscriptions + Invoices). The agent does not need access to objects it never calls — a narrower key limits blast radius if it is ever exposed.

    Test and live connections are fully isolated. A <code>sk\_test\_…</code> connection will never fire live-mode triggers, and vice versa. Build and verify automations in test mode before switching to <code>sk\_live\_…</code>.
  </Warning>

  {/* TODO(image): stripe-connect-flow — IMAGE SPEC: The AppInstallPlanSheet drawer open on the Stripe detail page. MCP method is selected with a 'Recommended' badge visible. The numbered setup steps are visible in the drawer body. The 'Connect' button is in an active/ready state. Dark background, Stripe icon visible in the drawer header. — replace this CSS mock with the real screenshot */}

  <div className="xast-mock-drawer">
    <div className="xast-mock-drawer-bar">
      <div className="xast-mock-drawer-icon">
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none">
          <rect width="24" height="24" rx="5" fill="#6772E5" />

          <path d="M13.3 8.3c0-.7.6-1 1.5-1 1.3 0 3 .4 4.2 1.1V4.6C17.7 4.2 16.3 4 14.8 4 11.4 4 9 5.8 9 8.6c0 4.4 6 3.7 6 5.6 0 .8-.7 1.1-1.7 1.1-1.5 0-3.3-.6-4.8-1.4v3.8c1.6.7 3.2 1 4.8 1 3.5 0 6-1.7 6-4.6-.1-4.7-6.1-3.9-6-5.8z" fill="#fff" />
        </svg>
      </div>

      <span className="xast-mock-drawer-title">Connect Stripe</span>
      <span className="xast-mock-drawer-close">✕</span>
    </div>

    <div className="xast-mock-drawer-body">
      <div className="xast-mock-method-row">
        <div className="xast-mock-method xast-mock-method-active">
          <span className="xast-mock-method-label">MCP</span>
          <span className="xast-mock-rec-badge">Recommended</span>
        </div>

        <div className="xast-mock-method">
          <span className="xast-mock-method-label">API Token</span>
        </div>
      </div>

      <p className="xast-mock-desc">Uses Stripe’s OAuth flow. Scoped to exactly what your agent needs.</p>

      <div className="xast-mock-steps">
        <div className="xast-mock-step">
          <span className="xast-mock-step-num">1</span>
          <span className="xast-mock-step-text">Actionist opens the Stripe OAuth consent screen in your browser</span>
        </div>

        <div className="xast-mock-step">
          <span className="xast-mock-step-num">2</span>
          <span className="xast-mock-step-text">Sign in and grant the requested scopes</span>
        </div>

        <div className="xast-mock-step">
          <span className="xast-mock-step-num">3</span>
          <span className="xast-mock-step-text">Actionist verifies the handshake with a read-only call</span>
        </div>

        <div className="xast-mock-step">
          <span className="xast-mock-step-num">4</span>
          <span className="xast-mock-step-text">Click Install — badge updates to Connected</span>
        </div>
      </div>

      <div className="xast-mock-footer">
        <span className="xast-mock-scope-row">Scopes: customers · subscriptions · invoices · balance</span>
        <button className="xast-mock-connect-btn">Connect</button>
      </div>
    </div>
  </div>
</div>

<div className="w-full py-10 xc-rise">
  <div className="actionist-tight flex flex-col gap-2 mb-6">
    <span className="actionist-section-eyebrow">Triggers</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">React to billing events in real time.</h2>

    <p className="text-base text-gray-600 dark:text-gray-400 max-w-3xl">
      Stripe exposes 10 webhook-backed triggers. When a billing event fires in Stripe, the connected agent wakes up immediately — no polling, no delay.
    </p>
  </div>

  <div className="xast-flow">
    <div className="xast-flow-row">
      <div className="xast-flow-icon">S</div>
      <div className="xast-flow-label">Stripe event (webhook)<span>invoice.payment\_succeeded, charge.failed, customer.subscription.deleted…</span></div>
    </div>

    <div className="xast-flow-arrow" />

    <div className="xast-flow-row">
      <div className="xast-flow-icon">T</div>
      <div className="xast-flow-label">Actionist trigger<span>Agent wakes immediately — no polling, no delay</span></div>
    </div>

    <div className="xast-flow-arrow d2" />

    <div className="xast-flow-row">
      <div className="xast-flow-icon">A</div>
      <div className="xast-flow-label">Agent acts<span>Email · Slack post · coupon · calendar booking · CRM update</span></div>
    </div>
  </div>

  <div className="mxs-tiers" style={{gridTemplateColumns:'repeat(auto-fill,minmax(210px,1fr))'}}>
    <div className="mxs-tier">
      <span className="xast-trigger-badge">webhook</span>
      <strong>Failed Payment</strong>
      <span>Fires when a charge or invoice payment fails. The most valuable trigger for dunning automation.</span>
    </div>

    <div className="mxs-tier">
      <span className="xast-trigger-badge">webhook</span>
      <strong>New Subscription</strong>
      <span>Fires when a customer subscribes to a new plan. Use it to trigger onboarding sequences or CRM updates.</span>
    </div>

    <div className="mxs-tier">
      <span className="xast-trigger-badge">webhook</span>
      <strong>Canceled Subscription</strong>
      <span>Fires on cancellation. Route to a win-back agent that issues coupons and books a save call.</span>
    </div>

    <div className="mxs-tier">
      <span className="xast-trigger-badge">webhook</span>
      <strong>New Dispute</strong>
      <span>Fires when a chargeback is opened. Time-sensitive — evidence deadlines are short.</span>
    </div>

    <div className="mxs-tier">
      <span className="xast-trigger-badge">webhook</span>
      <strong>Checkout Session Completed</strong>
      <span>Fires when a Payment Link or Checkout Session is completed. Use for post-purchase onboarding.</span>
    </div>

    <div className="mxs-tier">
      <span className="xast-trigger-badge">webhook</span>
      <strong>Invoice Paid</strong>
      <span>Fires on successful payment. Use for receipts, CRM updates, and renewal tracking.</span>
    </div>
  </div>

  <Note>
    Triggers are webhook-backed and fire only on events that occur <strong>after</strong> the trigger is activated. Stripe does not replay historical events. For reconciliation over past data, use a scheduled agent that calls the balance transactions actions with a date range — not a trigger.
  </Note>

  <Tip>
    Subscribe to <strong>Failed Payment</strong> and <strong>Canceled Subscription</strong> first. These two triggers unlock the highest-ROI automations: dunning recovery and churn win-back. Route <strong>New Dispute</strong> to an agent with the right context — original charge details, order history — not to a sales agent. Dispute evidence windows are short.
  </Tip>
</div>

<div className="w-full py-10 xc-rise">
  <div className="actionist-tight flex flex-col gap-2 mb-6">
    <span className="actionist-section-eyebrow">Actions</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">40 actions across the complete billing lifecycle.</h2>

    <p className="text-base text-gray-600 dark:text-gray-400 max-w-3xl">
      The Stripe app gives agents 12 read actions and 28 write actions, spanning every major Stripe object. One connection; no custom API wrappers.
    </p>
  </div>

  <div className="mxs-limits">
    <div className="mxs-limit"><b style={{fontSize:'26px'}}>40</b><span>total actions</span></div>
    <div className="mxs-limit"><b style={{fontSize:'26px'}}>12</b><span>read actions</span></div>
    <div className="mxs-limit"><b style={{fontSize:'26px'}}>28</b><span>write actions</span></div>
    <div className="mxs-limit"><b style={{fontSize:'26px'}}>10</b><span>webhook triggers</span></div>
  </div>

  <AccordionGroup>
    <Accordion title="Customers and subscriptions" icon="users" defaultOpen={true}>
      Read, create, update, and cancel customers and subscriptions. Search customers by email before creating — the idempotent lookup-then-create pattern prevents duplicate records that break dunning, subscription history, and CRM sync. Always chain <strong>Find Customer</strong> before <strong>Create Customer</strong>.
    </Accordion>

    <Accordion title="Payments and invoices" icon="credit-card">
      Create and retrieve charges, create and finalise invoices, add invoice items, create Payment Links and Prices, and work with PaymentIntents. Covers the full payment-collection lifecycle from quoting to collection.
    </Accordion>

    <Accordion title="Refunds, coupons, and disputes" icon="rotate-ccw">
      Issue refunds, create and apply coupons for win-back campaigns, and retrieve dispute details so an agent can assemble evidence packages. Refunds and subscription cancellations are non-reversible — set the agent's approval mode to require sign-off before these write actions execute.
    </Accordion>

    <Accordion title="Balance and reconciliation" icon="chart-column">
      Read balance transactions with date-range filters for scheduled reconciliation runs. Use a Finance Agent on a weekly or monthly schedule — not a trigger — for GL matching and MRR snapshots. Trigger-based reconciliation misses historical events; scheduled balance reads are always complete.
    </Accordion>
  </AccordionGroup>
</div>

<div className="w-full py-10 xc-rise">
  <div className="actionist-tight flex flex-col gap-2 mb-6">
    <span className="actionist-section-eyebrow">In practice</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">Three recipes finance teams run every week.</h2>

    <p className="text-base text-gray-600 dark:text-gray-400 max-w-3xl">
      Real workflows, concrete outputs — each one live in under 10 minutes.
    </p>
  </div>

  <div className="xc-recipes">
    <div className="xc-recipe">
      <div className="xc-recipe-who">
        <i style={{background:'linear-gradient(135deg,#FD840C,#E3008E)'}} />

        Felix · Finance and Ops
      </div>

      <div className="xc-recipe-flow">
        <em>invoice.payment\_succeeded</em> fires. Agent reads the invoice via <em>stripe\_retrieve\_invoice</em>, appends a reconciliation row to the finance tracker, then sends a personalised thank-you email to the customer — all before Felix checks his inbox. Typically covers <em>12 to 18 invoices</em> per day with zero manual entry.
      </div>

      <span className="xc-recipe-save">saves \~3 hrs/wk</span>
    </div>

    <div className="xc-recipe">
      <div className="xc-recipe-who">
        <i style={{background:'linear-gradient(135deg,#FD840C,#E3008E)'}} />

        Felix · Finance and Ops
      </div>

      <div className="xc-recipe-flow">
        <em>invoice.payment\_failed</em> fires. Agent checks the attempt count via <em>stripe\_retrieve\_invoice</em> — on attempt 2 or later it escalates: creates a new Checkout Session link and sends a personalised recovery email with the updated link. Attempt and outcome are logged to memory so follow-up emails do not repeat the same message.
      </div>

      <span className="xc-recipe-save">live in 10 min</span>
    </div>

    <div className="xc-recipe">
      <div className="xc-recipe-who">
        <i style={{background:'linear-gradient(135deg,#FD840C,#E3008E)'}} />

        Felix · Finance and Ops
      </div>

      <div className="xc-recipe-flow">
        Every Monday at 08:00, a scheduled agent reads <em>balance\_transactions:list</em> for the previous 7 days, groups by transaction type, calculates net movement, and posts a plain-text weekly revenue digest to <em>#finance</em> in Slack — typically covering <em>30 to 60 transactions</em>. Felix arrives to a ready-made summary instead of a spreadsheet.
      </div>

      <span className="xc-recipe-save">saves \~2 hrs/wk</span>
    </div>
  </div>
</div>

<div className="w-full py-10 xc-rise">
  <div className="actionist-tight flex flex-col gap-2 mb-6">
    <span className="actionist-section-eyebrow">Best practices</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">Tips before you go live.</h2>
  </div>

  <AccordionGroup>
    <Accordion title="Use a restricted key, not your full secret key" icon="lock" defaultOpen={true}>
      A full Stripe secret key grants access to every object in your account. Create a restricted key in the Stripe Dashboard under <strong>Developers → API keys → Restricted keys</strong>, scoped to only the resources your workflows touch. If the key is ever exposed, the blast radius is limited to the objects you explicitly granted.
    </Accordion>

    <Accordion title="Always run Find Customer before Create Customer" icon="search">
      Search by email first. If a Stripe Customer record already exists for that email, reuse the ID — do not create a new record. Duplicate customers break dunning sequences, subscription history, and CRM sync. The lookup-then-create pattern is idempotent and safe even if a trigger fires twice.
    </Accordion>

    <Accordion title="Test with sk_test_ before switching to live" icon="flask-conical">
      Connect a second Stripe integration in Actionist using your test-mode secret key (<code>sk\_test\_…</code>). Build and verify your automations end to end. Test and live connections are fully isolated — test webhooks will never fire live-mode triggers. Only switch to <code>sk\_live\_…</code> once you have confirmed the flows are correct.
    </Accordion>

    <Accordion title="Use scheduled balance reads for reconciliation, not triggers" icon="calendar-clock">
      Stripe triggers fire on future events only — they do not replay historical data. For month-end or weekly reconciliation, use a scheduled agent that calls the balance transactions actions with a specific date range. This guarantees a complete, ordered dataset regardless of when the agent was activated.
    </Accordion>

    <Accordion title="Dedicate a Finance Agent to billing and reconciliation" icon="landmark">
      Keep billing operations separate from customer-facing automations. Wire balance reads, invoice ageing, GL reconciliation, and MRR snapshots to a dedicated Finance Agent running on a fixed schedule. This prevents a customer-support agent's tool scope from accidentally overlapping with financial write actions.
    </Accordion>
  </AccordionGroup>
</div>

<div className="w-full py-10 xc-rise">
  <div className="actionist-cta-panel xc-border">
    <div className="relative z-10 flex flex-col items-center gap-5 max-w-2xl mx-auto">
      <span className="actionist-eyebrow">One connection</span>

      <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-white leading-tight">
        Your revenue ops, running on autopilot.
      </h2>

      <p className="text-base md:text-lg text-white/85">
        Connect Stripe once. Wire your triggers. Let Actionist handle failed payments, churned customers, and month-end reconciliation — while you focus on growth.
      </p>

      <div className="flex flex-wrap items-center justify-center gap-3 pt-2">
        <a className="actionist-cta-btn-primary" href="https://app.actionist.ai" target="_blank" rel="noreferrer">
          Open the Dashboard

          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
            <path d="M5 12h14" />

            <path d="m12 5 7 7-7 7" />
          </svg>
        </a>

        <a className="actionist-cta-btn-secondary" href="mailto:support@actionist.ai">
          Email the team
        </a>
      </div>
    </div>
  </div>
</div>

<div className="w-full pt-2 pb-6">
  <p className="actionist-trust-line">
    Webhook-backed triggers fire the instant an event lands in Stripe — no polling.<br />
    Restricted keys · Test mode isolated from live · Non-reversible writes require approval.
  </p>
</div>

<div className="w-full pb-16">
  <div className="actionist-tight flex flex-col gap-2 mb-6">
    <span className="actionist-section-eyebrow">Keep going</span>
    <h2 className="text-2xl md:text-3xl font-semibold tracking-tight text-gray-900 dark:text-gray-50">Related topics.</h2>
  </div>

  <Columns cols={4}>
    <Card title="Reactions" icon="zap" href="/Folders/reactions">
      How to wire Stripe webhook triggers to agents — filter rules, agent routing, and activation.
    </Card>

    <Card title="Schedules" icon="calendar-clock" href="/Folders/schedules">
      Set up recurring Finance Agent runs for balance reads, GL reconciliation, and MRR snapshots.
    </Card>

    <Card title="Credentials" icon="key" href="/Folders/credentials">
      Store and rotate Stripe API keys in the encrypted Credentials Vault without re-editing agents.
    </Card>

    <Card title="MCP" icon="plug" href="/Folders/mcp">
      Explore the official Stripe MCP server and other MCP integrations available in the catalog.
    </Card>
  </Columns>
</div>
