This skill should be used when working on Polar billing system, Stripe integration, subscription lifecycle, checkout flows, or benefit provisioning.
npx skills add https://github.com/fcakyon/claude-codex-settings --skill polar-billing
Comprehensive guide to Polar's billing infrastructure, covering entities, flows, Stripe integration, and benefit provisioning.
Checkout → Payment → Order → Transaction → Benefits
↓
Subscription (if recurring)
↓
Subscription Cycle → Order → ...
10. Transaction Ledger
11. Key File Locations
File: server/polar/models/checkout.py
Shopping cart/payment session before order confirmation.
| Field | Type | Description |
|-------|------|-------------|
| status | CheckoutStatus | open, expired, confirmed, succeeded, failed |
| payment_processor | PaymentProcessor | stripe, manual |
| client_secret | str | Unique identifier for frontend |
| amount, currency | int, str | Price in cents |
| tax_amount, discount_amount | int | Calculated amounts |
| allow_trial, trial_end | bool, datetime | Trial configuration |
| seats | int | For seat-based products |
Relationships: organization, customer, product, product_price, discount, subscription (for upgrades)
File: server/polar/models/checkout_link.py
Persistent URL that creates Checkout Sessions on visit.
| Field | Type | Description |
|-------|------|-------------|
| client_secret | str | Unique identifier for the URL |
| seats | int \| None | Preconfigured seat count for seat-based pricing |
| discount_id | UUID \| None | Preset discount to apply |
| trial_interval, trial_interval_count | Trial config | Override product trial settings |
Relationships: organization, products, discount
File: server/polar/models/order.py
Represents a billing event (one-time purchase or subscription cycle).
| Field | Type | Description |
|-------|------|-------------|
| status | OrderStatus | pending, paid, refunded, partially_refunded |
| billing_reason | OrderBillingReason | purchase, subscription_create, subscription_cycle, subscription_update |
| subtotal_amount | int | Amount before discount/tax |
| discount_amount | int | Discount applied |
| tax_amount | int | Tax collected |
| applied_balance_amount | int | Account balance applied |
| platform_fee_amount | int | Polar's fee |
| refunded_amount | int | Already refunded |
| next_payment_attempt_at | datetime | Dunning retry time |
Computed Properties:
net_amount = subtotal - discounttotal_amount = net + taxdue_amount = max(0, total + applied_balance)payout_amount = net - platform_fee - refundedFile: server/polar/models/subscription.py
Recurring billing relationship.
| Field | Type | Description |
|-------|------|-------------|
| status | SubscriptionStatus | incomplete, trialing, active, past_due, canceled, unpaid |
| amount, currency | int, str | Subscription gross price |
| net_amount | int | Net amount (gross minus inclusive tax, equal to gross if tax-exclusive) |
| tax_behavior | TaxBehavior \| None | Inclusive, exclusive, or null (set at creation) |
| recurring_interval | Interval | month, year |
| current_period_start/end | datetime | Billing period |
| trial_start/end | datetime | Trial period |
| cancel_at_period_end | bool | Scheduled cancellation |
| canceled_at, ended_at | datetime | Lifecycle timestamps |
| past_due_at | datetime | When payment failed |
| seats | int | For seat-based pricing |
Relationships: organization, customer, product, payment_method, discount, meters, grants (benefits)
File: server/polar/models/transaction.py
All money flows in the system.
| Field | Type | Description |
|-------|------|-------------|
| type | TransactionType | payment, processor_fee, refund, dispute, balance, payout |
| processor | Processor | stripe, manual |
| amount, currency | int, str | Transaction amount |
| tax_amount | int | Tax portion |
Self-referential relationships: payment_transaction, balance_transactions, incurred_transactions
File: server/polar/models/payment.py
Individual payment transaction.
| Field | Type | Description |
|-------|------|-------------|
| status | PaymentStatus | pending, succeeded, failed |
| processor_id | str | Stripe charge ID |
| method | str | card, bank_transfer, etc. |
| trigger | PaymentTrigger \| None | What initiated payment: purchase, subscription_cycle, retry_dunning, retry_customer, retry_payment_method_update, retry_admin |
| decline_reason | str | Why payment failed |
| risk_level, risk_score | str, int | Fraud assessment |
File: server/polar/models/refund.py
| Field | Type | Description |
|-------|------|-------------|
| status | RefundStatus | pending, succeeded, failed, canceled |
| reason | RefundReason | duplicate, fraudulent, customer_request, etc. |
| amount, tax_amount | int | Refund amounts |
| revoke_benefits | bool | Whether to revoke customer benefits |
File: server/polar/models/customer.py
| Field | Type | Description |
|-------|------|-------------|
| email, name | str | Contact info |
| billing_name | str | Name for invoices (falls back to name) |
| stripe_customer_id | str | Stripe link |
| billing_address | Address | Stored address |
| tax_id | str | For tax compliance |
Files: server/polar/models/product.py, server/polar/models/product_price.py
| ProductPrice Types | Description |
|-------------------|-------------|
| ProductPriceFixed | Fixed amount (set price_amount=0 for free) |
| ProductPriceCustom | Merchant sets at checkout |
| ProductPriceMeteredUnit | Pay-per-unit |
| ProductPriceSeatUnit | Per-seat with tiers |
File: server/polar/models/billing_entry.py
Audit log for billing calculations.
| Field | Type | Description |
|-------|------|-------------|
| type | BillingEntryType | cycle, proration, metered, seats_increase, seats_decrease |
| direction | Direction | debit, credit |
| amount | int | Entry amount |
Organization
├── Product
│ ├── ProductPrice (multiple per product)
│ └── ProductBenefit → Benefit
├── Customer
│ ├── Subscription → Organization, Product, Discount
│ │ ├── SubscriptionProductPrice
│ │ ├── SubscriptionMeter
│ │ └── BenefitGrant
│ ├── Order → Product, Subscription
│ │ └── OrderItem
│ ├── PaymentMethod
│ └── Wallet
├── Checkout → Customer, Product
├── Discount
│ └── DiscountRedemption
└── Account (for payouts)
└── Payout → Transaction
Transaction (ledger)
├── payment → Order, Customer
├── refund → Refund, Order
├── dispute → Dispute, Order
├── processor_fee → parent payment
└── payout → Account
File: server/polar/subscription/service.py
Core subscription operations:
# Creation
create_or_update_from_checkout(checkout, payment_method) → (Subscription, created)
# Updates
update_product(subscription, product_id, proration_behavior, discount=None)
update_seats(subscription, seats, proration_behavior)
update_discount(subscription, discount) # discount: UUID | Literal["unset"]
update_trial(subscription, trial_end)
# Lifecycle
cycle(subscription) # Period renewal
cancel(subscription) # At period end
revoke(subscription) # Immediately
uncancel(subscription)
# Benefits
enqueue_benefits_grants(task="grant"|"revoke", customer, product)
File: server/polar/order/service.py
create_from_checkout(checkout) # One-time purchase
create_subscription_order(subscription, billing_reason) # Recurring
trigger_payment(order) # Charge customer
create_order_balance(order) # Ledger entries
File: server/polar/checkout/service.py
create(product, customer_data, discount_code)
confirm(checkout) # Lock checkout for payment
handle_stripe_success(checkout, charge)
handle_free_success(checkout) # No payment needed
File: server/polar/payment/service.py
upsert_from_stripe_charge(charge, checkout, order)
handle_success(payment) # Complete order
handle_failure(payment) # Update order status
File: server/polar/refund/service.py
create(order, amount, reason, revoke_benefits)
upsert_from_stripe(stripe_refund)
# Also enqueues chargeback prevention notice for dispute_prevention refunds
File: server/polar/benefit/grant/service.py
enqueue_benefits_grants(task, customer, product, order=None, subscription=None)
grant_benefit(customer, benefit)
revoke_benefit(customer, benefit)
File: server/polar/subscription/tasks.py
| Task | Trigger | Action |
|------|---------|--------|
| subscription.cycle | Scheduler at period end | Renew subscription, create order |
| subscription.update_product_benefits_grants | Product benefits changed | Update all grants |
| subscription.cancel_customer | Customer deleted | Cancel all billable subscriptions (trialing, active, past_due) |
File: server/polar/order/tasks.py
| Task | Trigger | Action |
|------|---------|--------|
| order.create_subscription_order | Subscription cycle | Create billing order |
| order.trigger_payment | Order ready | Charge payment method |
| order.balance | Payment success | Create ledger entries |
| order.invoice | Order created | Generate PDF invoice |
| order.process_dunning | Hourly cron | Find orders for retry |
| order.process_dunning_order | Individual retry | Retry single payment |
File: server/polar/integrations/stripe/tasks.py
| Task | Stripe Event | Action |
|------|--------------|--------|
| charge.succeeded | Payment complete | Create order, provision benefits |
| charge.failed | Payment failed | Mark order failed |
| charge.updated | Charge settled | Create ledger transaction |
| refund.created/updated | Refund processed | Update refund record |
| charge.dispute.created | Chargeback | Create dispute, revoke benefits |
| payout.paid | Payout complete | Update payout status |
File: server/polar/benefit/tasks.py
| Task | Trigger | Action |
|------|---------|--------|
| benefit.enqueue_benefits_grants | Order/subscription | Queue individual grants |
| benefit.grant | Individual benefit | Provision access (GitHub, Discord, etc.) |
| benefit.revoke | Cancellation/refund | Remove access |
| benefit.cycle | Subscription renewal | Reset credits with rollover |
File: server/polar/checkout/tasks.py
| Task | Trigger | Action |
|------|---------|--------|
| checkout.handle_free_success | Free product | Complete without payment |
| checkout.expire_open_checkouts | Every 15 min | Mark expired checkouts |
File: server/polar/payout/tasks.py
| Task | Trigger | Action |
|------|---------|--------|
| payout.trigger_stripe_payouts | Daily 00:15 UTC | Initiate pending payouts |
| payout.created | Payout created | Event hook (fires for held payouts too) |
| payout.transfer | After payout.created | Stripe transfer (skipped for held) |
| payout.release_held_payouts | Org approved | Move held → pending, enqueue transfers |
| payout.cancel_account_payouts | Org denied/blocked/offboarding | Cancel held+pending payouts |
| payout.cancel_held_payouts | Payout account swap | Cancel only held payouts on old account |
File: server/polar/refund/tasks.py
| Task | Trigger | Action |
|------|---------|--------|
| refund.send_chargeback_prevention_notice | Dispute prevention refund created | Email org owners/admins about refund |
File: server/polar/integrations/stripe/endpoints.py
/v1/integrations/stripe/webhook - Direct webhooks/v1/integrations/stripe/webhook-connect - Connect account webhooksPayment Flow:
payment_intent.succeeded - Payment completepayment_intent.payment_failed - Payment failedsetup_intent.succeeded - Card savedcharge.pending/failed/succeeded/updated - Charge lifecycleRefunds:
refund.created/updated/failedDisputes:
charge.dispute.created/updated/closedConnect:
account.updated - Account info changedpayout.updated/paid - Payout lifecycleStripe POST → Verify signature → ExternalEvent.enqueue()
↓
Store in external_events table
↓
Enqueue Dramatiq task
↓
Worker processes async
↓
Mark handled_at on success
File: server/polar/integrations/stripe/service.py
Key methods:
create_payment_intent(), create_setup_intent()create_refund(), get_refund()create_tax_calculation(), create_tax_transaction()transfer(), create_payout()1. Checkout created (status=open)
2. Customer completes payment
3. Stripe charge.succeeded webhook
4. payment.handle_success() called
5. checkout_service.handle_stripe_success()
6. subscription_service.create_or_update_from_checkout()
- Creates Subscription (status=active or trialing)
- Sets billing period
- Applies discount
- Resets meters
7. Enqueue benefit grants
8. Send confirmation email
1. APScheduler triggers at period end
2. subscription.cycle task runs
3. subscription_service.cycle()
- Check cancel_at_period_end
- If true: set status=canceled, revoke benefits
- If false: advance period dates, check discount expiry
4. Create billing entry (type=cycle)
5. Enqueue order.create_subscription_order
6. Order created with billing_reason=subscription_cycle
7. Enqueue order.trigger_payment
8. Stripe charges payment method
9. charge.succeeded → ledger entries → benefits renewed
At Period End:
subscription_service.cancel(subscription)
# Sets cancel_at_period_end=True, ends_at=current_period_end
# Benefits remain until period ends
# On next cycle: status=canceled, benefits revoked
Immediately:
subscription_service.revoke(subscription)
# Sets status=canceled, ended_at=now
# Benefits revoked immediately
# Seats canceled if seat-based
1. Checkout with trial_end set
2. Subscription created with status=trialing
3. No payment during trial
4. At trial_end, cycle task runs
5. Status transitions to active
6. Order created with billing_reason=subscription_cycle_after_trial
7. First payment charged
# Calculate time remaining in period
pct_remaining = (period_end - now) / (period_end - period_start)
# Old product credit (what they paid but won't use)
old_credit = old_price * old_pct_remaining
# New product debit (what they owe for remainder)
new_debit = new_price * new_pct_remaining
# Net proration
net = new_debit - old_credit
| Behavior | Action |
|----------|--------|
| prorate | Add to next invoice |
| invoice | Create order immediately |
# Credit entry (old product)
BillingEntry(
type=BillingEntryType.proration,
direction=BillingEntryDirection.credit,
amount=prorated_old_amount
)
# Debit entry (new product)
BillingEntry(
type=BillingEntryType.proration,
direction=BillingEntryDirection.debit,
amount=prorated_new_amount
)
# Adding 2 seats at $10/seat with 50% time remaining
delta_amount = 2 * $10 * 0.5 = $10
BillingEntry(
type=BillingEntryType.subscription_seats_increase,
direction=BillingEntryDirection.debit,
amount=1000 # cents
)
| Type | Description | Grant Action |
|------|-------------|--------------|
| meter_credit | Usage allowances | Create meter_credited event |
| github_repository | Repo access | Add to GitHub team |
| discord | Server role | Assign Discord role |
| license_keys | License distribution | Generate key |
| downloadables | File access | Grant download permission |
| slack_shared_channel | Slack Connect channel | Create/invite to shared channel |
| feature_flag | Feature toggle (API-only) | None — merchant reads via API |
| custom | Customer-visible note | None — displayed in customer portal |
1. Order/Subscription created
2. enqueue_benefits_grants(task="grant")
3. For each benefit in product:
- Skip if already granted
- Enqueue benefit.grant task
4. benefit.grant task:
- Get/create BenefitGrant record
- Call strategy.grant() (type-specific)
- Set granted_at
- Store properties
- Send webhook
1. Subscription canceled or order refunded
2. enqueue_benefits_grants(task="revoke")
3. For each granted benefit:
- Enqueue benefit.revoke task
4. benefit.revoke task:
- Call strategy.revoke() (type-specific)
- Set revoked_at
- Send webhook
Grant:
# Create event with units
Event(type="meter_credited", units=100)
# Update CustomerMeter
Cycle (renewal):
# Calculate rollover
rollover = min(remaining_units, rollover_limit)
# Reset meter
Event(type="meter_reset")
# Credit new period + rollover
Event(type="meter_credited", units=base_units + rollover)
Revoke:
# Negative credit event
Event(type="meter_credited", units=-remaining_units)
Organizations can configure benefit_revocation_grace_period (days) to delay benefit revocation for past_due subscriptions.
1. order.process_dunning runs hourly
2. Finds orders where next_payment_attempt_at <= now
3. For each order:
- Enqueue order.process_dunning_order
4. process_dunning_order:
- Get customer's payment method
- Attempt payment via Stripe
- On success: mark order paid
- On failure: schedule next attempt
Configured in organization settings. Typical pattern:
payment fails → status=past_due, past_due_at=now
↓
benefits may continue (grace period)
↓
retry succeeds → status=active
↓
retry fails → status=unpaid, benefits revoked
| Type | Description |
|------|-------------|
| payment | Customer payment received |
| processor_fee | Stripe fees |
| refund | Money returned to customer |
| refund_reversal | Refund failed/reversed |
| dispute | Chargeback loss |
| dispute_reversal | Won dispute |
| balance | Internal balance transfer |
| payout | Money sent to creator |
1. charge.updated webhook (charge settled)
2. Get balance_transaction from Stripe
3. Extract settlement amount and fees
4. Create Transaction(type=payment)
5. Enqueue processor_fee.create_payment_fees
6. Create Transaction(type=processor_fee)
1. Creator has balance from transactions
2. payout.trigger_stripe_payouts (daily)
3. Calculate available balance
4. Create Payout record
- ACTIVE/OFFBOARDED org: status=pending, enqueue payout.created + payout.transfer
- REVIEW/SNOOZED org: status=held, enqueue payout.created only
5. stripe_service.transfer() to Connect account (skipped for held)
6. stripe_service.create_payout() to bank
7. payout.paid webhook → update status
Held payout lifecycle:
- When org approved: payout.release_held_payouts → status=pending, enqueue transfer
- When org denied/blocked/offboarding: payout.cancel_account_payouts → cancel + refund
- When payout account swapped: payout.cancel_held_payouts (old account only)
server/polar/models/
├── checkout.py
├── order.py
├── order_item.py
├── subscription.py
├── subscription_product_price.py
├── transaction.py
├── payment.py
├── refund.py
├── dispute.py
├── payout.py
├── customer.py
├── product.py
├── product_price.py
├── discount.py
├── benefit.py
├── benefit_grant.py
└── billing_entry.py
server/polar/
├── subscription/service.py
├── order/service.py
├── checkout/service.py
├── payment/service.py
├── refund/service.py
├── dispute/service.py
├── payout/service.py
├── benefit/
│ ├── service.py
│ ├── grant/service.py
│ └── strategies/
│ ├── meter_credit/service.py
│ ├── github_repository/service.py
│ ├── discord/service.py
│ └── ...
└── transaction/service/
├── payment.py
├── refund.py
└── dispute.py
server/polar/
├── subscription/tasks.py
├── order/tasks.py
├── checkout/tasks.py
├── benefit/tasks.py
├── payout/tasks.py
├── refund/tasks.py
└── integrations/stripe/tasks.py
server/polar/integrations/stripe/
├── endpoints.py # Webhook handlers
├── service.py # Stripe API wrapper
├── tasks.py # Webhook processing tasks
└── payment.py # Payment resolution helpers
Payment record for decline_reasonOrder.status and next_payment_attempt_atBenefitGrant record for errorsBillingEntry records for subscriptionscheduler_locked_at on subscriptionAutomatically organizes invoices and receipts for tax preparation by reading messy files, extracting key information, renaming them consistently, and sorting them into logical folders. Turns hours of manual bookkeeping into minutes of automated organization.
Expert guidance for systematic backtesting of trading strategies. Use when developing, testing, stress-testing, or validating quantitative trading strategies. Covers "beating ideas to death" methodology, parameter robustness testing, slippage modeling, bias prevention, and interpreting backtest results. Applicable when user asks about backtesting, strategy validation, robustness testing, avoiding overfitting, or systematic trading development.
This skill calculates key financial ratios and metrics from financial statement data for investment analysis
This skill provides an advanced financial modeling suite with DCF analysis, sensitivity testing, Monte Carlo simulations, and scenario planning for investment decisions
This skill retrieves upcoming earnings announcements for US stocks using the Financial Modeling Prep (FMP) API. Use this when the user requests earnings calendar data, wants to know which companies are reporting earnings in the upcoming week, or needs a weekly earnings review. The skill focuses on mid-cap and above companies (over $2B market cap) that have significant market impact, organizing the data by date and timing in a clean markdown table format. Supports multiple environments (CLI, Desktop, Web) with flexible API key management.
Crypto wallet operations via the awal CLI — sign in, check balances, send USDC/ETH/POL/SOL, trade tokens, fund the wallet, and use the x402 payment protocol to discover paid services, pay for API calls, monetize an API, or query onchain data. Use whenever the user mentions signing in, login, authentication, wallet status, balance, address, sending money, paying someone, transferring tokens, ENS names, swapping/trading/converting tokens, funding/topping up/onramp, USDC, ETH, POL, SOL, the x402 bazaar, paid APIs, monetizing an endpoint, or querying onchain data on Base.
Access real-time and historical stock market data, forex rates, cryptocurrency prices, commodities, economic indicators, and 50+ technical indicators via the Alpha Vantage API. Use when fetching stock prices (OHLCV), company fundamentals (income statement, balance sheet, cash flow), earnings, options data, market news/sentiment, insider transactions, GDP, CPI, treasury yields, gold/silver/oil prices, Bitcoin/crypto prices, forex exchange rates, or calculating technical indicators (SMA, EMA, MACD, RSI, Bollinger Bands). Requires a free API key from alphavantage.co.
Braintree Automation: manage payment processing via Stripe-compatible tools for customers, subscriptions, payment methods, and transactions
Take fcakyon/polar-billing from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.