Stripe Integration
Sync your billing configuration to 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_
- Test key: starts with
2. Configure Environment Variables
Set the API keys as environment variables:
export STRIPE_SANDBOX_KEY=sk_test_...
export STRIPE_PRODUCTION_KEY=sk_live_...Never commit API keys to version control. Add .env to your .gitignore.
3. Add Stripe to Your Config
version: 1
providers:
- stripe
plans:
- 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: stripe
environment: sandbox
synced_at: "2026-01-28T10:30:00Z"
plans:
pro:
product_id: prod_ABC123
prices:
monthly: price_XYZ789
yearly: price_UVW012
addons:
extra_projects:
product_id: prod_DEF456
price_id: price_RST345
promotions:
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.
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 configurationraterunner/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:
- Import existing products first with
raterunner import - Archive the old product in Stripe Dashboard
- 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:
- Raterunner archives the old price
- Creates a new price with the new amount
- 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