More Stripe documentation
Stripe ASC 606 Revenue Recognition for SaaS
How ERPClaw handles Stripe ASC 606 revenue recognition. Deferred revenue, monthly recognition, plan changes, cancellations, and the journal entries behind each.
ASC 606 is the accounting standard for revenue recognition. It says you cannot count an annual subscription as revenue when the customer pays it. You have to recognize it monthly over the subscription period.
This page documents how ERPClaw implements ASC 606 for Stripe subscriptions, with the actual journal entries.
The five steps
ASC 606 defines a five-step framework for revenue recognition. For Stripe subscriptions, the steps map as follows:
- Identify the contract: a Stripe subscription = a contract.
- Identify performance obligations: the obligation is to deliver software access for the subscription period.
- Determine the transaction price: the subscription’s recurring amount.
- Allocate the transaction price: for single-product subscriptions, all of it goes to the one obligation.
- Recognize revenue when (or as) the obligation is satisfied: monthly, over the subscription period.
Multi-product subscriptions and bundles need step 4 to allocate, which gets complicated. The Stripe bridge creates one contract with one performance obligation per subscription, priced from the subscription’s plan amount. Bundles that need an allocation across several obligations are set up with the core revenue contract actions (performance obligations, variable consideration) instead.
How it runs
Recognition is two explicit steps, not a background job:
- Create the schedule for a subscription with
stripe-create-rev-rec-schedule. ERPClaw creates the revenue contract, one obligation, and twelve monthly schedule entries starting from the subscription’s current period start. An annual plan is spread as one twelfth per month; a monthly plan as its plan amount each month. - Recognize each month with
stripe-recognize-subscription-revenuefor the period. For every scheduled entry in that month it posts Deferred Revenue to your revenue account and marks the entry recognized.
Once a subscription has a schedule, its charges post to Deferred Revenue instead of revenue.
The journal entries
Customer pays $1,200 for an annual subscription
When the charge posts:
| Account | Debit | Credit |
|---|---|---|
| Stripe Clearing | $1,165 | |
| Stripe Processing Fees | $35 | |
| Deferred Revenue | $1,200 |
Note: the Stripe fee is an immediate expense, not deferred.
End of month 1 (recognize 1/12)
| Account | Debit | Credit |
|---|---|---|
| Deferred Revenue | $100 | |
| Subscription Revenue | $100 |
Repeat each month.
End of month 12 (final recognition)
| Account | Debit | Credit |
|---|---|---|
| Deferred Revenue | $100 | |
| Subscription Revenue | $100 |
After this, Deferred Revenue for this subscription is $0.
Customer cancels mid-year (after 4 months)
Eight months unused at $100/month = $800 unrecognized.
Record the cancellation with
stripe-handle-subscription-change --change-type cancel. ERPClaw
marks the revenue contract terminated and reports what is still unrecognized: eight entries, $800. What
happens to that $800 is posted as its own entry:
- If refunded, the refund posts from the synced Stripe refund
(
stripe-post-refund-gl) against Stripe Clearing. - If not refunded (e.g. cancellation effective end of period), post a journal entry that recognizes the remainder:
| Account | Debit | Credit |
|---|---|---|
| Deferred Revenue | $800 | |
| Subscription Revenue | $800 |
Mid-cycle upgrades and downgrades
If a customer upgrades from $100/mo to $200/mo, record it with
stripe-handle-subscription-change --change-type upgrade --new-plan-amount 200.
ERPClaw keeps every month already recognized
as it was and reprices every month not yet recognized at the new
monthly amount. The contract total is updated to match.
Recognition is monthly, not daily. A proration charge that Stripe raises for the change posts like any other charge.
You can audit the result by reading the schedule
(advacct_revenue_schedule) for that subscription’s contract.
Annual subscriptions paid with discount
If a customer pays $1,000 for a $1,200 annual plan (Stripe Coupon applied), the charge reflects the actual cash:
| Account | Debit | Credit |
|---|---|---|
| Stripe Clearing | $1,000 | |
| Deferred Revenue | $1,000 |
The schedule is built from the plan price ($1,200, so $100 a month).
For a discounted plan, reprice it to the cash actually collected
(--change-type downgrade --new-plan-amount 1000) before the first
recognition, so each month recognizes $83.33 and Deferred Revenue ends
at $0.
Failed payment then re-attempted successfully
Stripe attempts to charge, fails, retries, succeeds. Bulk posting
picks up only succeeded charges. The failed attempt is stored as a
stripe_charge row with status='failed' for audit purposes, with no
GL impact.
Subscriptions on Stripe trial
Trial periods do not collect payment, so no charge posts during a trial. If the customer cancels during trial, no journal entry, no Deferred Revenue.
A schedule created while the subscription is still trialing starts from the current period start. If you want recognition to start with the first paid period, create the schedule once that period begins.
Multi-currency subscriptions
ERPClaw v1 supports USD-denominated subscriptions only. Other currencies are recorded but not auto-converted to USD for GL posting. Multi-currency runs payment-side across 7 currencies (USD, EUR, GBP, CAD, INR, SGD, AED): an invoice settles in the currency it was raised in, with no conversion inside a transaction.
Audit trail
For an auditor reviewing your books, ERPClaw provides:
advacct_revenue_contractandadvacct_revenue_schedule: the contract behind each subscription and its monthly schedule, planned and recognizedstripe-rev-rec-status: per subscription, the plan, total contract value, revenue recognized to date, and the deferred balance remainingrevenue-waterfall-report: the schedule laid out by period- The audit log: every schedule creation, recognition run, and subscription change is written with a timestamp
Your agent can save any of these as a file for a CPA or auditor.
What the bridge handles
- Annual and monthly plans, spread over twelve months
- Upgrades and downgrades, repricing the months not yet recognized
- Cancellation, with the unrecognized remainder reported
- Discounted plans, by repricing to the cash collected
- Failed payments (no GL impact) and trials (no charge, no entry)
Edge cases NOT handled in v1
- Multi-currency conversions
- Billing intervals other than month or year (weekly, daily, every N months)
- Day-level proration inside a month
- Multi-element subscriptions with manual allocation
- Variable consideration adjustments (price changes mid-cycle by usage)
If you hit one of these, the recognition will need a manual journal
entry. Email [email protected] if you have a regular case that
isn’t covered.
ASC 606 in plain English
You are not paying for “access to a SaaS tool.” You are paying for 12 months of access. The vendor cannot count your money as revenue until they have actually given you access for the period they promised. ASC 606 makes this rule formal.
The accounting effect is straightforward but easy to get wrong by hand. ERPClaw builds the schedule and posts each month’s entry for you, for any size book.
Source
- ASC 606 standard: fasb.org
- Stripe docs on revenue recognition: stripe.com/docs/billing/revenue-recognition
- ERPClaw recognition engine source: github.com/avansaber/erpclaw-addons