What Stripe's Basil release broke in every CRM connector written before March 2025
If a Stripe™-to-HubSpot integration started quietly returning blank or undefined values sometime after March 2025, that timing is not a coincidence. Stripe's major API version released that month removed several fields from the Invoice object outright and relocated others off the Subscription object entirely. A connector pinned to an older API version, or one with field paths hardcoded before that date, keeps reading fields Stripe no longer returns — with no error, just a silent gap where a number used to be. None of this requires anyone's account to be misconfigured. It is what changed in Stripe's own object shapes, and it is checkable directly against Stripe's own API reference in under a minute.
What actually changed
Stripe's major API versions are allowed to make breaking changes to request parameters and response shapes — that is the documented difference between a major version and the monthly versions, which only ever add fields. The March 2025 major version did exactly that to two objects that reconciliation work depends on most.
On the Invoice object, several fields that used to point at a single charge or payment stopped existing:
| Field a connector might still read | What happened | What to read instead |
|---|---|---|
invoice.charge |
No longer present | invoice.payments, a list — an invoice can now carry more than one payment |
invoice.payment_intent |
No longer present | The relevant PaymentIntent lives under invoice.payments |
invoice.subscription |
Moved | invoice.parent — Stripe's own field description calls it "the parent that generated this invoice" |
invoice.tax |
No longer present | invoice.total_taxes, an array rather than a single number |
invoice.total_tax_amounts |
No longer present | invoice.total_taxes |
On the Subscription object, the two fields almost every MRR calculation reads moved entirely off the subscription itself. current_period_start and current_period_end no longer exist at the top level — each Subscription Item now carries its own period, because a single subscription can hold several items with different billing cycles. Code that reads the old top-level fields doesn't throw; it reads undefined, and a naive fallback (today's date, or the subscription's creation date) can silently misreport an entire billing period.
A third, easy-to-miss detail: invoice period_start and period_end still exist, but Stripe's own object reference is explicit that they are not the service period — the line item's own period is. A connector that reports a revenue period from the invoice dates rather than the line item gets the wrong period on any proration, upgrade or downgrade.
What to do about it today
- Check your pinned API version. Every Stripe request carries one, set at the account level or per request. If yours predates March 2025 and nobody has deliberately moved it since, the integration is running old response shapes on purpose — which delays the problem rather than avoiding it.
- Search your own code, Zapier zaps or Make scenarios for the old field paths —
invoice.charge,invoice.subscription,subscription.current_period_end, and the others in the table above. A field path baked into a no-code automation's field mapping is exactly as broken as one in source code, and considerably easier to miss. - Paste your own object or field list into our free Basil field checker. It runs entirely in your browser — nothing you paste is sent anywhere — and flags every field in the table above (and several more) that your data still depends on.
- Re-map each flagged field to its replacement, using the table above as a starting point; Stripe's own object reference has the complete, current field list for both objects.
- Pin your API version deliberately going forward, rather than letting it inherit whatever your account's rolling default happens to be, so the next major version doesn't repeat this silently.
Where this breaks down
A paste-in checker only catches what you paste. It can't discover every field path buried across a codebase, a year of Zapier zaps, or a pile of ad hoc scripts — it tells you whether a specific field you already suspect is a problem actually is one.
Fixing the field path is necessary, not sufficient. invoice.payments is a list because an invoice can now have more than one payment; code that naively reads the first entry can still misreport a partially refunded or multi-attempt invoice even after the field path itself is corrected.
This is not the last breaking version Stripe will ship. Basil is one major version; nothing stops a future one from moving fields again. A connector that reads dozens of hardcoded field paths, with no record of which API version it was written against, will hit exactly this problem again with no way to tell what changed.
Some fixes need real data re-checked, not just a corrected path. A period calculation that was silently wrong for a year of prorated invoices needs those invoices re-checked against the new fields, not just the code corrected going forward.
What Trueness does about it
Trueness pins Stripe API version 2026-08-26.dahlia and reads the objects Stripe returns under that version — not a snapshot of what the Invoice or Subscription object looked like before March 2025. The free Drift Report records the exact Stripe and HubSpot versions it used to produce each report, so a finding from today can still be explained later, even after Stripe ships another major version.