Skip to content
← Community packages

Read and manage Stripe customers, payments, invoices, subscriptions, and refunds with dry-run mutations.

Browse files

  • Integrations
  • stripe
  • payments
  • billing
  • invoices
  • subscriptions
  • refunds
  • webhooks
  • finance
License
MIT
Published
August 23, 2026
Pinned commit
adef0e4
Rating
No ratings yet
Forks
3
Stars
0
Adaptation effort

README

@kody/stripe

Intent

Reusable Stripe helpers so Kody agents can read and manage customers, payments, invoices, subscriptions, refunds, products, and webhook events on the caller's Stripe account — not a shared platform store. Auth is a saved API key, not OAuth. Reads are free-form; mutations support dryRun: true, and money-moving or destructive calls also require confirm: true.

This listing is meant to be forked. After you fork, save your own stripeApiKey and call the helpers in your account.

This official API-key package is the preferred invoke path. Setup is harder: save a Stripe secret or restricted key. For a faster first win, connect Stripe MCP in Get started and use @kody/stripe-mcp.

Auth

API key (secret-backed). There is no Stripe OAuth integration and no bot token. Do not open /connect/oauth for Stripe.

SecretPurpose
stripeApiKeySecret key (sk_live_… / sk_test_…) or restricted key (rk_…)
stripeWebhookSecretEndpoint signing secret (whsec_…) for HMAC verify

Required setup

  1. Create a key at dashboard.stripe.com/apikeys. Prefer a restricted key with only the permissions you need.
  2. Save it in Kody (do not paste the value in chat):

https://kody.codes/account/secrets/new?name=stripeApiKey&description=Stripe%20secret%20API%20key%20(sk_live_%20or%20rk_live_)%20for%20customers%2C%20payments%2C%20invoices%2C%20and%20subscriptions&allowedHosts=api.stripe.com,files.stripe.com&scope=user

  1. In the account secrets UI, approve hosts api.stripe.com and files.stripe.com.
  2. Optional webhook signing secret (Developers → Webhooks → endpoint signing secret):

https://kody.codes/account/secrets/new?name=stripeWebhookSecret&description=Stripe%20webhook%20signing%20secret%20(whsec_)%20from%20Developers%20%E2%86%92%20Webhooks&scope=user

stripeWebhookSecret is used only for local HMAC verification. It does not need Stripe API hosts. Inbound deliveries still need a URL you control (after a fork, a package-declared Kody webhook is one option).

Hosts

  • api.stripe.com — all REST calls
  • files.stripe.com — file uploads (stripeUploadFile)

Restricted-key permissions

A full secret key (sk_…) can call everything this package exposes. A restricted key must include the permission for the endpoint. Typical set:

HelperPermission
getAccountrak_account_read
getBalance, listBalanceTransactions, listPayoutsrak_balance_read
customersrak_customer_read / rak_customer_write
charges, payment intents, refundsrak_charge_read / rak_charge_write, rak_payment_intent_read
invoicesrak_invoice_read / rak_invoice_write
subscriptionsrak_subscription_read / rak_subscription_write
products, prices, payment linksrak_product_read / rak_product_write
events / loadVerifiedEventrak_event_read
listWebhookEndpointsrak_webhook_read

If Stripe returns 403 / insufficient permissions, this package throws StripeApiError naming the missing rak_… permission (when Stripe includes it) and the next setup step: add that permission at https://dashboard.stripe.com/apikeys then update stripeApiKey at the secrets URL above.

HTTP 401 means the key is missing or invalid — save stripeApiKey at the prefilled URL.

Multi-account

Pass account: "work" to use secret stripeApiKey-work (and stripeWebhookSecret-work for HMAC). Or pass secretName: "stripeApiKey-live". There are no hard-coded account aliases.

https://kody.codes/account/secrets/new?name=stripeApiKey-work&description=Stripe%20API%20key%20for%20the%20work%20account&allowedHosts=api.stripe.com,files.stripe.com&scope=user

Webhook signature verify

Stripe signs ${timestamp}.${rawBody} with HMAC-SHA256 and sends Stripe-Signature: t=…,v1=…. Two lanes:

  1. HMACverifyWebhookSignature({ payload, signatureHeader, webhookSecret }) when the handler already has whsec_… (never paste it in chat).
  2. API retrieveloadVerifiedEvent({ eventId }) re-fetches evt_… through stripeApiKey. Prefer this from Kody when you do not want to hold the signing secret in the handler.
import { verifyWebhookSignature, loadVerifiedEvent } from 'kody:@kody/stripe/webhooks'

await verifyWebhookSignature({
	payload: rawBody,
	signatureHeader: stripeSignatureHeader,
	webhookSecret: 'whsec_…', // from your webhook handler, not from chat
})

await loadVerifiedEvent({ eventId: 'evt_123' })

Register the endpoint in Stripe webhooks pointing at your inbound URL. This official listing does not mint a shared ingress URL.

Exports

  • kody:@kody/stripe — action dispatcher (defaults to smoke-test); also re-exports every helper below
  • kody:@kody/stripe/accountgetAccount, getBalance, listBalanceTransactions, listPayouts, listEvents
  • kody:@kody/stripe/customerslistCustomers, searchCustomers, getCustomer, createCustomer, updateCustomer, deleteCustomer
  • kody:@kody/stripe/paymentslistPaymentIntents, getPaymentIntent, searchPaymentIntents, listCharges, getCharge, searchCharges, listRefunds, createRefund
  • kody:@kody/stripe/invoiceslistInvoices, getInvoice, searchInvoices, createInvoice, finalizeInvoice, sendInvoice, voidInvoice, deleteDraftInvoice
  • kody:@kody/stripe/subscriptionslistSubscriptions, getSubscription, searchSubscriptions, createSubscription, cancelSubscription
  • kody:@kody/stripe/productslistProducts, getProduct, createProduct, archiveProduct, listPrices, createPrice, listPaymentLinks, createPaymentLink, deactivatePaymentLink
  • kody:@kody/stripe/webhooksverifyWebhookSignature, loadVerifiedEvent, listWebhookEndpoints, getWebhookEndpoint
  • kody:@kody/stripe/smoke-test — HMAC + dry-run self-check, then a live account/balance read when stripeApiKey exists

Low-level transport (stripeRequest, stripeList, stripeSearch, stripeParams, stripeUploadFile, StripeApiError) stays pinned to https://api.stripe.com/v1.

Mutation safety

  • Pass dryRun: true on any mutation to return { dryRun: true, method, path, body } without contacting Stripe.
  • createRefund, createSubscription, cancelSubscription, finalizeInvoice, sendInvoice, voidInvoice, deleteDraftInvoice, deleteCustomer, archiveProduct, and deactivatePaymentLink also throw unless confirm: true.
  • POST helpers accept optional idempotencyKey and only retry automatically when one is provided.
  • Amounts are Stripe integer amounts in the smallest currency unit (cents for USD); summaries include a display string.
import { createRefund } from 'kody:@kody/stripe/payments'

const preview = await createRefund({
	chargeId: 'ch_123',
	amount: 500,
	dryRun: true,
})

const refund = await createRefund({
	chargeId: 'ch_123',
	amount: 500,
	confirm: true,
})

Smoke test

import { packages } from 'kody:runtime'

export default async function main() {
	return await packages.invoke("kody:@kody/stripe", {
		exportName: './smoke-test',
	})
}

Without stripeApiKey this still returns { ok: true, live: false } plus the setup URL. With the secret saved it reads account, balance, and one customer page — no writes.

Example

import stripe from 'kody:@kody/stripe'

export default async function main() {
	return await stripe({
		action: 'search-charges',
		searchQuery: "billing_details.email:'ada@example.com'",
		maxItems: 10,
	})
}

Branding

community-icon.svg is Stripe's official "S" glyph (Simple Icons, CC0), on Stripe purple #635BFF. Stripe® is a trademark of Stripe, Inc. This package is not affiliated with or endorsed by Stripe.

Docs

Report this listing

Log in to report this listing.