dj-stripe 2.11.0 (2026-06-26)
IMPORTANT: Migrations have been reset. You MUST upgrade to dj-stripe 2.10.x before upgrading to dj-stripe 2.11.x.
Version support
- Support for Django versions older than 5.2 has been dropped.
- The minimum supported Stripe SDK version is now 15.0.1.
- Migrations have been fully reset. You MUST upgrade to dj-stripe 2.10.x before upgrading to dj-stripe 2.11.x.
- The default Stripe API version is now
2026-05-27.dahlia(was2020-08-27).
Breaking Changes
InvoiceOrLineItemForeignKeyhas been removed (deprecated in 2.10)- Remove
PlanTiersModeandPlanUsageTypeenums - Remove
Customer.retry_unpaid_invoices - The
Planmodel has been removed. The Stripe Plans API was deprecated in favour of the Prices API years ago; use thePricemodel instead. This also removes theInvoiceItem.planandSubscriptionItem.planforeign keys (use.price), thesubscription_planargument ofInvoice.upcoming(), theplanargument ofSubscription.update(), and support for{"plan": ...}items inCustomer.subscribe()(use{"price": ...}). - Legacy customer payment sources have been removed. The
CardandBankAccountmodels now only represent external accounts on Connect accounts; theircustomerforeign key — and theCustomer.legacy_cardsandCustomer.bank_accountrelations — are gone, along with theLegacySourceMixinclass (renamed toExternalAccountMixin) andCustomer._sync_cards(). Connect external-account support is unchanged. UsePaymentMethodfor customer payment instruments. PaymentsContextMixinandSubscriptionMixinnow exposepricesandis_prices_pluralin the template context (sourced fromPrice) instead ofplansandis_plans_plural.- The
djstripe_update_invoiceitem_idsmanagement command has been removed. It was a one-time migration for the pre-2019-12-03 invoice item id format.
Deprecations
- The
Sourcemodel is now officially deprecated and emits aDeprecationWarningwhen synced. The Stripe Sources API has been deprecated in favour of the PaymentMethods API; use thePaymentMethodmodel instead.Sourcewill be removed in a future release.
New features
- Add the
AccountV2model for the Stripe Accounts v2 / Organizations API (/v2/core/accounts). It is served by Stripe's service-based v2 Core API, so itsapi_*methods route throughStripeClient(...).v2.core.accounts(retrieve/list useinclude,closereplaces delete, and the RFC 3339createdtimestamp is parsed to a datetime). It is synced bydjstripe_sync_modelslike other models. v2 thin-event webhooks are not yet handled. - Add
ProductFeaturemodel and automatic sync of product features - Add
currency_optionstoPrice.expand_fields - Stripe API keys may now be configured entirely via Django settings /
environment variables, without having to store them in the database. The
djstripe_sync_modelscommand now syncs the keys defined in settings in addition to those in the database, so environment-variable-only and admin-less deployments work out of the box (#2100, #2055). Customer.create()andCustomer.get_or_create()now accept ametadatadict and arbitrary keyword arguments, which are forwarded to the Stripe Customer create call (saving a round-trip versus creating and then updating). TheSUBSCRIBER_CUSTOMER_KEYmetadata is still always set to the subscriber pk and takes precedence, so the customer-to-subscriber link cannot be broken by caller-supplied metadata (#795).- WebhookEndpoint URLs entered in the admin are now validated, with a hint
pointing at the
stripe_listencommand for local development.
Bugfixes
- Webhook processing errors now persist their
WebhookEventTriggerrecord (with the exception and traceback) even whenATOMIC_REQUESTSis enabled. The webhook view is now exempt fromATOMIC_REQUESTS, andfrom_requestwraps event processing in its own transaction, so a failure rolls back the partial event sync while still committing the error record before re-raising for Django's logging (#833). Customer.valid_subscriptionsnow also excludesincompletesubscriptions (in addition tocanceledandincomplete_expired). Anincompletesubscription's initial payment has not succeeded yet — eg. one created withpayment_behavior="default_incomplete"— so the customer is not paying for it. This also affects theCustomer.subscriptionshortcut, which is built onvalid_subscriptions(#1721).- Fix
djstripe_sync_modelsaborting with "You don't have any API Keys in the database" when keys are configured only via settings / environment variables. The command now falls back to the settings keys, and--api-keysaccepts keys that are not stored in the database (#2100). - Raise a clearer error when no Stripe API key is configured anywhere, instead
of the cryptic
InvalidStripeAPIKey: Invalid API key: ''(#2055). - Add support for the Stripe subscription status
pausedviaSubscriptionStatus.paused. - Fix Django 5 template validation by replacing a parent-relative admin template path in webhook endpoint admin views.
- Fix Connect account webhook sync failures when account branding points to platform-owned file uploads by retrying file retrieval in platform context.
- Fix
djstripe_sync_models Customerfailures caused by sending unsupportedidparameters to Stripelist_sourcesrequests. - Restore compatibility with stripe-python 14 and 15. In stripe 15,
StripeObjectstopped inheriting fromdictand lost the mapping-style methods (get,items,keys,values,pop,setdefault) that dj-stripe relies on across its sync paths. A small compatibility shim restores them on stripe >=15 and is a no-op on earlier versions. - Fix
Charge._calculate_refund_amountmixing dollars and cents, which caused negative results on subsequent partial refunds. - Fix
Customer.purge()crashing withAttributeError: property 'default_source' has no setterafterdefault_sourcewas refactored into a read-only property overstripe_data. - Stop hard-deleting
SubscriptionItemrows when items are removed from aSubscriptionupstream, and gracefully returnNonewhen a referencedSubscriptionItemis no longer retrievable from Stripe. Together these keepinvoice.*webhooks from crashing on invoices that referenceSubscriptionItemids removed by aSubscriptionSchedulephase change or a mid-period item removal (#2025, #2105). Note:subscription.items.all()will now include items that were removed upstream. - Fix
FieldError: Cannot resolve keyword 'status' into fieldand similar errors raised bySubscriptionManager,TransferManager, andChargeManagermethods. The 2.10 refactor moved fields likestatus,start_date,canceled_at,paid,refunded, etc. from concrete columns intostripe_data, but the manager methods kept filtering on them as if they were still columns. The manager methods now usestripe_data__<key>JSON-path lookups, withCast()for numeric aggregations (#2197). - Fix
update_customer_helperlooking up the subscriber byidinstead ofpk, which broke linking customers to subscribers on custom user models whose primary key is not namedid(#2203). - Fix the
stripe_listenmanagement command generating a forward URL with a double slash (e.g..../stripe//webhook/<uuid>) by no longer rebuilding the URL via string replacement (#2195). - Fix
IntegrityErrorcrash (duplicate key value violates unique constraint "djstripe_event_stripe_id_key") when Stripe delivers the same webhook event more than once and two deliveries race past the existence check.Event.processnow treats the duplicate as already-processed and returns the existing event instead of crashing (#1239). - Mark
ProcessWebhookViewwithlogin_not_requiredso incoming Stripe webhooks are no longer redirected to the login page when Django'sLoginRequiredMiddlewareis enabled (#2137). - Strip a trailing port number from the client address parsed out of the
X-Forwarded-Forheader when recording aWebhookEventTrigger. Some proxies (eg. Azure) append:portto the address, which is not a validinetvalue and causedDataError: invalid input syntax for type ineton PostgreSQL. IPv6 addresses (bare or bracketed) are handled correctly (#1843). - Fix syncing
WebhookEndpointobjects that were created outside dj-stripe (eg. directly on the Stripe dashboard). These have nodjstripe_uuidin their metadata, which was written straight onto the unique, non-nulldjstripe_uuidfield and aborted the sync with a misleadingWebhookEndpoint matching query does not exist. dj-stripe now keeps the auto-generated uuid when none is present in the metadata (#2146). - Stop webhooks from crashing when a platform-account event references an object
that only exists on a connected account (eg. a destination charge's
application_fee, or thatApplicationFee'scharge). These are not retrievable from the platform, so the foreign key is now skipped gracefully instead of raisingNo such charge/No such application fee(#2010). - Stop
payment_method.detachedwebhooks anddjstripe_sync_modelsfrom crashing on detached legacy sources. A detachedsrc_…object is wrapped as a payment method but 404s on the payment_methods endpoint with "A source must be attached to a customer to be used as apayment_method". The detach webhook now syncs from the event payload instead of re-retrieving, and the foreign-key sync path skips the unretrievable payment method gracefully (#1068). - Stop
*.created/*.updatedwebhooks from crashing when the object was deleted on Stripe's side before the webhook was processed (eg. an object created and deleted in quick succession with the webhook retried in between). The retrieve now 404s gracefully and the event is skipped instead of raisingNo such …(#1218). - Fix
Transfer.during()andCharge.during()computing month boundaries inconsistently; the start and end of the selected month are now derived in UTC.
Other changes
- The handling of "the referenced Stripe object is gone" errors during sync is
now centralised in
djstripe._stripe_errors.object_is_absent, replacing the per-object-type message-substring branches that had accumulated across the sync and webhook code paths. As a side effect, the foreign-key sync path now skips any object that 404s asresource_missing, not just the handful of types that were previously hardcoded. djstripe_sync_modelsnow exits with a non-zero status code when one or more models fail to sync, so failures are detectable in CI and scripts.- The API key admin now displays a redacted secret instead of the plaintext key.