Providers
Stripe
Uses the Ahena CLI (beta). Install it with npm install -g @ahena/cli, or prefix commands with npx @ahena/cli. See Installation. The dashboard covers projects, connections, Doctor, the Stack Graph, plans and approvals without it.
Overview
Ahena checks your Stripe account is ready to take payments, keeps test and live modes in the right environments, sets up webhooks and your product catalog, and generates checkout, billing portal, Connect and webhook code. Your app talks to Stripe directly. Ahena is never in the payment path.
Package: @ahena/provider-stripe · Category: payments · Pinned API version: 2026-09-30.endive
Capabilities: payments, subscriptions, webhooks, connect, test-live-verification
Connection
STRIPE_SECRET_KEY: a secret (sk_…) or restricted (rk_…) key. Restricted keys are
recommended. Ahena needs Account read, Webhook Endpoints write, and Products and Prices
write. Production refuses test-mode keys before contacting Stripe.
STRIPE_SECRET_KEY=rk_live_… ahena connect stripe -e production
Permissions
Use a restricted key with only:
| Permission | Needed for |
|---|---|
| Account: Read | validate, Doctor (charges, payouts, requirements) |
| Webhook Endpoints: Write | creating the webhook endpoint |
| Products: Write, Prices: Write | the catalog from payments.products |
| Connect: Read | Connect checks (connect: true only) |
Ahena never needs Charges, Customers, Payment Intents or Payouts permissions and never creates a charge.
Capabilities
| Capability | What Ahena does |
|---|---|
payments |
Checks readiness; generates Checkout and billing portal code. |
subscriptions |
Creates products and prices from config; ahena add subscriptions syncs subscriptions into your database. |
webhooks |
Creates the endpoint, stores its signing secret, probes your route with an unsigned request. |
connect |
Checks Connect is enabled; generates Express onboarding and destination-charge helpers. |
test-live-verification |
Keeps test keys out of production and live keys out of other environments. |
Network: only api.stripe.com (enforced). Your webhook route is probed through Ahena's
credential-free probe. ahena lock tracks key mode, charges/payouts enabled and webhook
endpoints for drift.
Configure
payments: {
provider: "stripe",
webhook: { production: { endpoint: "https://example.com/api/webhooks/stripe" } },
products: [
{ key: "pro", name: "Pro", prices: [
{ lookupKey: "pro_monthly", currency: "usd", unitAmount: 1900, interval: "month" },
{ lookupKey: "pro_yearly", currency: "usd", unitAmount: 19000, interval: "year" },
] },
],
connect: true, // marketplaces: check Connect and generate Connect helpers
},
| Change | Classification | Notes |
|---|---|---|
| Create the webhook endpoint | CONFIRMATION_REQUIRED | Signing secret returned once and stored encrypted as STRIPE_WEBHOOK_SECRET. |
Create a product (ahena_<key>) |
CONFIRMATION_REQUIRED | Idempotent: fixed product id plus idempotency keys. |
Create a price (by lookupKey) |
CONFIRMATION_REQUIRED | Creating a price charges no one. |
Stripe prices are immutable. If an existing lookupKey has a different amount, Ahena
refuses and asks for a new key, so customers are never moved silently. Test-mode and
live-mode catalogs are separate, as in Stripe.
Generate
ahena generate stripe [--framework nextjs]:
src/ahena/payments/index.ts:payments.checkout({ priceLookupKey, successUrl, cancelUrl, customerEmail }),payments.portal(customerId, returnUrl),payments.rawsrc/ahena/payments/connect.ts(withconnect: true): Express accounts, onboarding links, destination charges with a platform feesrc/app/api/webhooks/stripe/route.ts(Next.js): verifiesstripe-signatureagainst the raw body withconstructEventAsync(400 for unsigned or tampered requests), then callshandleStripeEventinsrc/ahena/payments/events.ts, where feature packs and your own code handle events
Limitations
- Customers, subscriptions, saved cards and payment history aren't moved or managed by Ahena.
- Prices are immutable in Stripe: a changed amount needs a new
lookupKey. - Test-mode and live-mode catalogs are separate; configure each environment.
- Tax, invoicing, branding and payout schedules aren't managed.
Manual steps
- Activate the account (business details and bank account) before live payments; Doctor lists outstanding requirements.
- Marketplaces: enable Connect and complete the platform profile in the Stripe dashboard.
- Put a live restricted key in production and a test key everywhere else.
Doctor checks
| Id | Severity | Meaning |
|---|---|---|
stripe.mode |
PASS / WARNING / FAIL | Test key in production (FAIL), live key elsewhere (WARNING). |
stripe.key_kind |
INFO | A full secret key in production; a restricted key would limit exposure. |
stripe.account / .verification |
PASS / WARNING / FAIL | Charges enabled and no outstanding requirements; otherwise the onboarding steps. |
stripe.account.payouts |
WARNING | Charges on, payouts off. |
stripe.webhook |
PASS / WARNING / FAIL | Endpoint exists, enabled, with the needed events. |
stripe.webhook.endpoint |
PASS / WARNING / FAIL | Unsigned-request probe (route missing → SAFE generate fix). |
stripe.secret.stripe_webhook_secret |
PASS / FAIL | Signing secret stored in this environment (checked by name). |
stripe.prices / .mismatch |
PASS / WARNING / FAIL | Configured prices exist and match. |
stripe.connect |
PASS / FAIL | Account is a Connect platform. |
Core also flags sk_test_ values stored in production and sk_live_ values elsewhere,
including keys held by connections.
Disconnect behavior
Removes the connection and the key Ahena stored. Roll or delete the key at https://dashboard.stripe.com/apikeys. Products, prices, webhooks, customers and payments are untouched.