Docs / integrations/stripe

Stripe Integration

Raterunner fully supports Stripe, syncing your plans to Products and Prices, and promotions to Coupons and Promotion Codes.

Setup

1. Get Your API Keys

  1. Go to Stripe Dashboard
  2. Copy your Secret keys:
  • Test key: starts with sk_test_
  • Live key: starts with sk_live_

2. Configure Environment Variables

Set the API keys as environment variables:

bash
export STRIPE_SANDBOX_KEY=sk_test_...export STRIPE_PRODUCTION_KEY=sk_live_...
Warning: Never commit API keys to version control. Add .env to your .gitignore.

3. Add Stripe to Your Config

yaml
version: 1providers:  - stripeplans:  - id: pro    name: Pro Plan    prices:      monthly: { amount: 2900 }

4. Test the Connection

bash
raterunner apply --env sandbox --dry-run raterunner/billing.yaml

How It Maps

RaterunnerStripe
PlanProduct
Flat PricePrice (recurring)
Per-unit PricePrice (per_unit, recurring)
Tiered PricePrice (tiered, recurring)
AddonProduct + Price
PromotionCoupon + Promotion Code

Syncing Plans

Flat Pricing

yaml
plans:  - id: pro    name: Pro Plan    description: For professional teams    prices:      monthly: { amount: 2900 }   # $29/month      yearly: { amount: 29000 }   # $290/year

Syncs to Stripe as: - 1 Product (pro) - 2 Prices (monthly and yearly recurring)

Per-Unit Pricing (Seats)

yaml
plans:  - id: team    name: Team Plan    prices:      monthly:        per_unit: 1200          # $12/seat/month        unit: seat        min: 1        included: 1             # First seat free

Syncs to Stripe as: - 1 Product - 1 Price with billing_scheme: per_unit

Tiered Pricing

yaml
plans:  - id: api    name: API Plan    prices:      monthly:        tiers:          - up_to: 10            amount: 2000        # $20/unit for 1-10          - up_to: 50            amount: 1500        # $15/unit for 11-50          - up_to: unlimited            amount: 1000        # $10/unit for 51+        mode: graduated

Syncs to Stripe as: - 1 Product - 1 Price with billing_scheme: tiered

Promotions and Coupons

yaml
promotions:  - code: LAUNCH50    description: 50% off first 3 months    discount: { percent: 50 }    duration: { months: 3 }    new_customers_only: true    active: true

Syncs to Stripe as: - 1 Coupon (50% off, 3 months duration) - 1 Promotion Code (LAUNCH50)

Fixed Amount Discount

yaml
promotions:  - code: SAVE10    discount: { fixed: 1000 }   # $10 off    duration: once

Forever Discount

yaml
promotions:  - code: PARTNER20    discount: { percent: 20 }    duration: forever

Addons

yaml
addons:  - id: extra_projects    name: Extra Projects Pack    price: { amount: 1000 }    grants:      projects: "+10"

Syncs to Stripe as: - 1 Product - 1 Price

Commands

Preview Changes (Dry Run)

bash
raterunner apply --env sandbox --dry-run raterunner/billing.yaml

Output shows what will be created/updated:

text
+ Create Product: pro+ Create Price: pro_monthly ($29/month)+ Create Price: pro_yearly ($290/year)

Apply Changes

bash
raterunner apply --env sandbox raterunner/billing.yaml

JSON Output

bash
raterunner apply --env sandbox --dry-run --json raterunner/billing.yaml

Provider ID Files

After syncing, Raterunner creates a provider ID file:

yaml
# raterunner/stripe_sandbox.yaml (auto-generated)provider: stripeenvironment: sandboxsynced_at: "2026-01-28T10:30:00Z"plans:  pro:    product_id: prod_ABC123    prices:      monthly: price_XYZ789      yearly: price_UVW012addons:  extra_projects:    product_id: prod_DEF456    price_id: price_RST345promotions:  LAUNCH50:    coupon_id: LAUNCH50    promotion_code_id: promo_GHI678

Why commit this file? - Track which Stripe objects correspond to your plans - Debug issues by finding the exact Stripe object - Maintain history of when syncs happened

Environments

Sandbox (Test Mode)

Use test API keys for development:

bash
export STRIPE_SANDBOX_KEY=sk_test_...raterunner apply --env sandbox raterunner/billing.yaml

Creates raterunner/stripe_sandbox.yaml.

Production (Live Mode)

Use live API keys for production:

bash
export STRIPE_PRODUCTION_KEY=sk_live_...raterunner apply --env production raterunner/billing.yaml

Creates raterunner/stripe_production.yaml.

Error: Always test in sandbox before syncing to production!

Import Existing Stripe Setup

If you already have products in Stripe, import them:

bash
raterunner import --env sandbox --output raterunner/billing.yaml

Creates: - raterunner/billing.yaml — your billing configuration - raterunner/stripe_sandbox.yaml — provider ID mappings

Reset Sandbox

To start fresh in sandbox (archive all products/prices):

bash
raterunner truncate --confirm

Sandbox only — refuses to run against production.

API Operations

The CLI uses these Stripe APIs:

OperationStripe API
Create productPOST /v1/products
Create pricePOST /v1/prices
Create couponPOST /v1/coupons
Create promo codePOST /v1/promotion_codes
Archive pricePOST /v1/prices/{id} (active=false)
Archive productPOST /v1/products/{id} (active=false)
Delete couponDELETE /v1/coupons/{id}

Troubleshooting

"Product already exists"

The product ID conflicts with an existing product. Options: 1. Import existing products first with raterunner import 2. Archive the old product in Stripe Dashboard 3. Use a different plan ID

"Invalid API key"

  • Check the key starts with sk_test_ or sk_live_
  • Ensure no extra whitespace
  • Verify the key hasn't been revoked

"Rate limited"

Raterunner batches API calls, but large syncs may hit limits. The CLI automatically retries with exponential backoff.

Price changes not syncing

Stripe prices are immutable. When you change a price amount: 1. Raterunner archives the old price 2. Creates a new price with the new amount 3. Updates the provider ID file

Existing subscriptions remain on the old price until renewed or updated.

Best Practices

  1. Test first — always sync to sandbox before production
  2. Commit provider files — keep track of Stripe IDs in Git
  3. Use dry-run — preview changes before applying
  4. Automate in CI — validate configs on PR, sync on merge