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
- Go to Stripe Dashboard
- 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:
export STRIPE_SANDBOX_KEY=sk_test_...export STRIPE_PRODUCTION_KEY=sk_live_...Warning: Never commit API keys to version control. Add.envto your.gitignore.
3. Add Stripe to Your Config
version: 1providers: - stripeplans: - id: pro name: Pro Plan prices: monthly: { amount: 2900 }4. Test the Connection
raterunner apply --env sandbox --dry-run raterunner/billing.yamlHow It Maps
| Raterunner | Stripe |
|---|---|
| Plan | Product |
| Flat Price | Price (recurring) |
| Per-unit Price | Price (per_unit, recurring) |
| Tiered Price | Price (tiered, recurring) |
| Addon | Product + Price |
| Promotion | Coupon + Promotion Code |
Syncing Plans
Flat Pricing
plans: - id: pro name: Pro Plan description: For professional teams prices: monthly: { amount: 2900 } # $29/month yearly: { amount: 29000 } # $290/yearSyncs to Stripe as: - 1 Product (pro) - 2 Prices (monthly and yearly recurring)
Per-Unit Pricing (Seats)
plans: - id: team name: Team Plan prices: monthly: per_unit: 1200 # $12/seat/month unit: seat min: 1 included: 1 # First seat freeSyncs to Stripe as: - 1 Product - 1 Price with billing_scheme: per_unit
Tiered Pricing
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: graduatedSyncs to Stripe as: - 1 Product - 1 Price with billing_scheme: tiered
Promotions and Coupons
promotions: - code: LAUNCH50 description: 50% off first 3 months discount: { percent: 50 } duration: { months: 3 } new_customers_only: true active: trueSyncs to Stripe as: - 1 Coupon (50% off, 3 months duration) - 1 Promotion Code (LAUNCH50)
Fixed Amount Discount
promotions: - code: SAVE10 discount: { fixed: 1000 } # $10 off duration: onceForever Discount
promotions: - code: PARTNER20 discount: { percent: 20 } duration: foreverAddons
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)
raterunner apply --env sandbox --dry-run raterunner/billing.yamlOutput shows what will be created/updated:
+ Create Product: pro+ Create Price: pro_monthly ($29/month)+ Create Price: pro_yearly ($290/year)Apply Changes
raterunner apply --env sandbox raterunner/billing.yamlJSON Output
raterunner apply --env sandbox --dry-run --json raterunner/billing.yamlProvider ID Files
After syncing, Raterunner creates a provider ID file:
# 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_GHI678Why 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:
export STRIPE_SANDBOX_KEY=sk_test_...raterunner apply --env sandbox raterunner/billing.yamlCreates raterunner/stripe_sandbox.yaml.
Production (Live Mode)
Use live API keys for production:
export STRIPE_PRODUCTION_KEY=sk_live_...raterunner apply --env production raterunner/billing.yamlCreates 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:
raterunner import --env sandbox --output raterunner/billing.yamlCreates: - raterunner/billing.yaml — your billing configuration - raterunner/stripe_sandbox.yaml — provider ID mappings
Reset Sandbox
To start fresh in sandbox (archive all products/prices):
raterunner truncate --confirmSandbox only — refuses to run against production.
API Operations
The CLI uses these Stripe APIs:
| Operation | Stripe API |
|---|---|
| Create product | POST /v1/products |
| Create price | POST /v1/prices |
| Create coupon | POST /v1/coupons |
| Create promo code | POST /v1/promotion_codes |
| Archive price | POST /v1/prices/{id} (active=false) |
| Archive product | POST /v1/products/{id} (active=false) |
| Delete coupon | DELETE /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_orsk_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
- Test first — always sync to sandbox before production
- Commit provider files — keep track of Stripe IDs in Git
- Use dry-run — preview changes before applying
- Automate in CI — validate configs on PR, sync on merge