Severity: 🔴 Critical (out of date)
The metered / pay-per-request path calls Stripe APIs that Stripe removed in API version 2025-03-31.basil (legacy usage-based billing).
Affected calls
- Metered price creation without
recurring[meter]:
PaymentClient.scala:325-333 and :355-356 (recurring[usage_type]=metered + recurring[aggregate_usage]=sum).
- Usage reporting via the legacy endpoint:
PaymentClient.scala:634-636 (POST /v1/subscription_items/{id}/usage_records).
Why it breaks
No Stripe-Version header is pinned — stripeClient only sets content-type + Basic Auth (PaymentClient.scala:38-50). Behaviour therefore follows the account default API version. Any account at/after 2025-02-24.acacia rejects metered price creation (a meter is now required) and the usage_records endpoint. The flat-subscription path (costPerMonth only) is unaffected.
Fix
- Migrate to the Billing Meters API: create a
meter, link prices with recurring[meter], replace usage_records with POST /v1/billing/meter_events.
- Pin an explicit
Stripe-Version header to freeze behaviour going forward.
References
How to verify
On a recent Stripe account, configure a plan with costPerRequest and run setupPayment → observe the rejected POST /v1/prices (metered price without a meter).
Severity: 🔴 Critical (out of date)
The metered / pay-per-request path calls Stripe APIs that Stripe removed in API version
2025-03-31.basil(legacy usage-based billing).Affected calls
recurring[meter]:PaymentClient.scala:325-333and:355-356(recurring[usage_type]=metered+recurring[aggregate_usage]=sum).PaymentClient.scala:634-636(POST /v1/subscription_items/{id}/usage_records).Why it breaks
No
Stripe-Versionheader is pinned —stripeClientonly setscontent-type+ Basic Auth (PaymentClient.scala:38-50). Behaviour therefore follows the account default API version. Any account at/after2025-02-24.acaciarejects metered price creation (ameteris now required) and theusage_recordsendpoint. The flat-subscription path (costPerMonthonly) is unaffected.Fix
meter, link prices withrecurring[meter], replaceusage_recordswithPOST /v1/billing/meter_events.Stripe-Versionheader to freeze behaviour going forward.References
How to verify
On a recent Stripe account, configure a plan with
costPerRequestand runsetupPayment→ observe the rejectedPOST /v1/prices(metered price without a meter).