Checkout sessions validate against the platform's own products and coupons and stream that catalog data through to Stripe, removing runtime price lookups.
15 May 2026
Feature
Checkout
Catalog
Subscriptions
Stripe
Checkout now resolves products, prices, and coupons against the local catalog introduced in v1.0.1 instead of looking them up in Stripe at request time. Sessions are validated up-front, pricing is sent inline to Stripe, and every checkout, subscription, and invoice is linked back to the catalog records that produced it.
What changed
- Catalog-validated checkout sessions —
POST /checkout/sessions now resolves every submitted product and coupon code against the client's local catalog before a session is created. Unknown, soft-deleted, or non-applicable entries are rejected with a 422 response carrying machine-readable codes (UnknownProduct, DeletedProduct, UnknownCoupon, DeletedCoupon, CouponNotApplicable).
- Inline pricing to Stripe — Stripe subscription and one-off charge calls now send
price_data/product_data built from the local catalog, including trial days and price overrides. Stripe no longer needs a pre-existing Price for each checkout item.
- Persistent checkout-to-catalog links — New
checkout_product and checkout_coupon records capture which catalog entries were used for each session. Resulting subscription and invoice rows are populated with the corresponding product_id and coupon_id, including from incoming Stripe webhooks.
- Coupon guarantor — Stripe coupons are retrieved-or-created on demand per currency from the local coupon definition, with race handling for concurrent creates.
Why it matters
Merchants get a single source of truth for what they sell. Pricing, trial windows, and discount rules live in the platform catalog and are enforced consistently at checkout, on the resulting Stripe charge, and on the persisted invoice and subscription — which makes reporting, refunds, and reconciliation line up cleanly across the lifecycle.
Developer notes
- Checkout request bodies must reference product and coupon
code values that exist (and are not soft-deleted) in the local catalog for the authenticated client. Invalid references now return 422 with a typed error code instead of being passed through to the gateway.
New gateway-independent APIs for managing products, prices, coupons, and collections directly on the platform.
14 May 2026
Feature
Catalog
Products
Coupons
Collections
API
Merchants can now manage their own products, prices, coupons, and collections through the platform API without relying on a payment gateway's catalog. This release adds the data layer and CRUD endpoints that future checkout and subscription flows will build on.
What changed
- Products — Create, list, retrieve, update, and soft-delete products scoped to the authenticated client. Each product supports one-time or recurring pricing with multiple currencies via nested
prices.
- Coupons — Manage percentage or fixed-amount discounts with duration controls (once, repeating, forever), per-currency amounts, and optional product associations.
- Collections — Group products into named collections for catalog organization, with associations managed in the same create or update request.
- Consistent list queries — All new list endpoints (
GET /products, GET /coupons, GET /collections) accept the standard page, limit, sort, filter, and relation-inclusion parameters introduced in v1.0.0.
- Unique codes — Product, coupon, and collection
code values are enforced as unique per client at the database level.
Why it matters
This is the catalog foundation that lets merchants define their offerings once and reuse them across checkout, subscriptions, and reporting — independent of which payment gateway ultimately processes a transaction. Soft-delete semantics preserve historical references on existing invoices and subscriptions even after a product or coupon is retired.
Developer notes
- All catalog endpoints are guarded by client authentication;
client_id is derived from the authenticated client and is never read from the request body.
- Nested prices and product associations are upserted in the same request, so a single
POST or PATCH call is sufficient to persist a product with its prices or a coupon with its applicable products.
- No checkout or Stripe flows change in this release. Wiring the catalog into checkout and subscription creation will follow in subsequent releases.
Payments, invoices, and webhook event listing endpoints now support pagination, sorting, filtering, and related-record expansion through a unified query contract.
13 May 2026
Improvement
Payments
Invoices
Webhooks
API
List endpoints across the API now accept a consistent set of query parameters for pagination, sorting, filtering, and relation inclusion. This replaces previous per-endpoint, ad-hoc query handling with a single shared contract, giving developers a predictable and documented interface for all list operations.
What changed
- Payments, invoices, and webhook events listing endpoints accept standardized
page, limit, sort and filter query parameters.
- Filtering supports typed, operator-driven expressions (e.g. equality, range) so results can be narrowed without custom endpoints.
- Relation inclusion allows callers to request parent and original-delivery records alongside webhook events in a single response.
- Malformed or unsupported query parameters now return a clear
400 Bad Request response rather than silently ignoring or mishandling the input.
- OpenAPI / Swagger documentation reflects the new query contract; docs now derive the API version and title from the package version automatically.
Why it matters
Developers building merchant dashboards, reconciliation tools, or operational integrations can now paginate and filter results reliably across all major list endpoints using the same parameter names and semantics — reducing the need for client-side post-processing and extra round trips.
Developer notes
- The per-endpoint query DTOs for payments (
PaymentsQueryDto), invoices (InvoiceListQueryDto), and webhook events (ListClientWebhookEventsQueryDto) have been replaced by the shared list-query parser. Update any code that constructed or validated those DTOs directly.
- Unsupported or malformed
filter/sort expressions that were previously silently ignored will now return 400. Review any existing queries that relied on lenient handling.
- No database migrations are required.
- API documents are available from here.