- DATE:
- AUTHOR:
- The Kinde team
Sell more than subscriptions
Sell one-time charges alongside your plans
Kinde billing now supports one-time charges, so you can sell things that do not fit a recurring subscription — setup fees, credit top-ups, add-on packs, and other buy-once items. When editing a plan, add a one-time charge alongside your recurring features: each charge can be a flat price or package-priced (for example, $20 per 1,000 credits), metered or unmetered, and can either never expire or expire at the end of the current billing cycle. You can also cap the maximum units a customer can hold, and publishing the plan syncs everything to Stripe automatically.
Your customers buy them in the self-serve portal (for both B2C and B2B), choosing a quantity, seeing an itemized quote, and paying with their saved card or a new one. Free (zero-amount) items are granted instantly without a payment step, and purchase history and expiry dates are shown right on the plan details page. You can also assign a one-time purchase to a customer directly from their billing record in the admin area, charging their stored payment method automatically — useful for sales-led deals and support scenarios. When a metered one-time charge is purchased, the customer is granted the corresponding usage allowance, and usage you report via the API draws down against it. Plan changes and cancellations are handled safely too: customers with unexpired one-time purchases are clearly warned and must acknowledge that those purchases will be forfeited, and any in-flight (unpaid) purchases are voided rather than charged.
Report on purchases and usage via the Management API
Two new Management API endpoints round out one-time charges. GET /api/v1/billing/one_time_purchases lists a customer's one-time purchases (requiring the read:billing_one_time_purchases scope), and GET /api/v1/billing/meter_usage lists meter usage records (read:meter_usage) — handy for reconciling granted allowances against reported usage. Both support pagination and filtering by customer, agreement, or feature code.
Founder MCP tool hints
Admins can now override tool annotation hints (read-only, destructive, idempotent, open world) per connection and per tool for the founder proxy MCP server. For example, you can mark a specific DELETE tool as non-destructive or a POST search tool as read-only. Overrides are stored with the connection, and the runtime cache refreshes when they change.
SCIM and directory sync improvements
Directory sync is more reliable and harder to misconfigure this release. Linking a SCIM group to a role no longer returns a 500 error, editing a predefined attribute mapping now works, and saving a mapping backfills values for existing SCIM users. To prevent bad configurations, text attributes can no longer be mapped to boolean user properties, and any existing invalid mappings are now flagged directly in the dialog.
We've also tightened how directory-synced users are managed, so changes can't be made out of band and then overwritten by the next sync. These users no longer show Delete, Remove from org, Suspend, or Reset password in the user list menu (matching their profile page), and they can no longer be added to other organizations. Every path that could previously do this — import, admin add-user, the create-user API, SCIM, and access requests — now returns a clear blocked message, and the bulk organization users endpoints include a new users_blocked field so you can see when this happens programmatically.
Billing and self-serve plan fixes
B2C subscribers can now cancel their own plan from the self-serve portal under My Account → Plan → Cancel plan. If you've attached a cancellation request workflow, the button instead reads Request to cancel.
Plans assigned through the Management API or by admin manual assignment now charge the customer's default payment method automatically, matching self-serve signup — previously these were invoiced. If you rely on invoicing for manually assigned plans, this is a behaviour change worth noting.
We also fixed a range of cancellation bugs: denied workflows with no description now open the denied dialog, malformed agreement ids no longer cause a 500, expired plans no longer show a false "Plan cancelled" toast, and tightened authorization on plan cancellation.
OAuth2 response caching
All OAuth2 responses are now marked no-store, so CDNs and other caches no longer keep or serve one user's profile or authorization details to another caller. The user profile endpoints also send Vary: Origin, Authorization as a secondary safeguard.
Minor fixes and improvements
The sign-up confirmation code page now documents the
${email_address_obfuscated}and${email_address_unobfuscated}placeholders${email_address}stays obfuscated by default, and you can opt in to showing the full email with${email_address_unobfuscated}Kinde domains are now capped at 50 characters, so business and environment domains no longer exceed the 63-character DNS label limit and silently fail to resolve.
SDKs
Here's some other changes to SDKs:
PKCE JS SDK: Fixed token refresh issues from lingering tab-sync and visibility listeners, restored legacy
org_codemapping in login, register and create-org, and updatedjs-yamlfor securityNode Express SDK: Security fix upgrading qs to resolve a reported vulnerability, plus updated Kinde TypeScript SDK dependency (v2.15.1)
Android SDK: Added in-code configuration with KindeConfig, enabling apps to connect to different Kinde environments, such as one per region, without using AndroidManifest meta-data
SvelteKit SDK: Added configurable session cookie expiry via KINDE_SESSION_MAX_AGE, plus dependency updates
JWT Decoder SDK: Security update to vitest 4.1.11, plus routine tooling and dependency updates
JS Utils SDK: Updated dependencies including eslint, @types/chrome, pnpm, and vite
Expo SDK: Fixed an issue where tokens could be lost to the keychain while the device was locked, and updated dependencies