August 5, 2026
New Features
Payment links in invoice webhooks
The invoice object sent byinvoice.created, invoice.paid, and invoice.payment_failed now includes payment_link. This signed URL takes the customer directly to the invoice payment page, so integrations can surface payment recovery without constructing a customer portal token themselves.payment_link is present when the invoice is open or payment has failed. If the invoice is already paid when it is created, payment_link is null because no payment action is required.Changes
Portal sessions require a customer email
POST /portal/session/ now returns 400 Bad Request when the selected customer does not have an email address. Portal session tokens are tied to the customer’s email, so add an email to the customer before creating a session.August 1, 2026
New Features
Subscription cancellation details
GET /subscriptions/ and GET /subscriptions/{subscriptionId}/ now return cancellation metadata:canceledAt— when the cancellation was recorded.cancellationReason— whether it was initiated by the customer, merchant, or provider.cancellationFeedback— structured feedback such asTOO_EXPENSIVE,MISSING_FEATURES, orUNUSED.cancellationComment— an optional free-form comment.
POST /subscriptions/{subscriptionId}/cancel/ now accepts the optional cancellationFeedback and cancellationComment fields. The cancellation endpoint records the merchant as the initiator; cancellations submitted through the customer portal record the customer as the initiator.Failed invoice webhook
You can now subscribe toinvoice.payment_failed. Kelviq sends this event when a subscription invoice payment fails or requires customer action. Its data.object uses the same invoice payload shape as invoice.created and invoice.paid.Refund webhook context
Therefund.created and refund.updated webhook objects now include:customer— the associated customer’s ID, name, email, customer identifier, and billing address.subscription_id— the associated subscription ID, ornullfor an order without a subscription.
Refunded order total
Order responses fromGET /orders/ and GET /orders/{id}/ now include refundedTotalUnits, the total amount refunded against the order in the sale currency’s minor units.July 29, 2026
Fixes
subscription.updated now fires when a cancellation is scheduled for period-end
Scheduling a subscription to cancel at the end of the current billing period (rather than immediately) previously sent no webhook at all — status stays active until the period actually ends, so nothing was detected as changed. This now correctly sends subscription.updated (with the new end_date and a previous_attributes.end_date of null) at the moment the cancellation is scheduled. subscription.cancelled still only fires once the subscription actually reaches cancelled status — for a period-end cancellation, that’s later, when the period ends.July 29, 2026
New Features
Checkout sessions and checkout session events
Three endpoints are now part of the public API:GET /checkout/sessions/— paginated list of checkout sessions for the authenticated organization.GET /checkout/sessions/{session_id}/— a single checkout session, including the order, subscription, and payment method it produced (if any).GET /checkout/sessions/{session_id}/events/— the session’s timeline events (session created, customer details updated, payment attempted, payment completed, etc.).
July 29, 2026
New Features
Orders, order events, and webhook delivery logs
Four endpoints are now part of the public API:GET /orders/— paginated list of orders.PENDINGorders (payment never attempted/completed) are never included. Acceptsstatus,billing_type(ONE_TIME/SUBSCRIPTION), andis_renewal(true/false) filters.GET /orders/{id}/— a single order.GET /orders/{id}/events/— the order’s timeline events (order created, order completed, order receipt sent, invoice paid, etc.). This returns events for every order tied to the same underlying subscription as{id}, not just that single order record.GET /webhook/logs/— one row per webhook delivery attempt, including retries.
GET /webhook/logs/ also accepts start_date/end_date query params. Results are always limited to the trailing 30 days — these params can narrow that window but can’t widen it beyond 30 days back. They filter against lastAttempt (when that specific delivery attempt happened), not createdOn (when the underlying event was first created) — the two can differ for retried deliveries.July 29, 2026
New Features
Filter subscriptions by status
GET /subscriptions/ now accepts a status query parameter. Pass a comma-separated list to match any of several statuses, e.g. ?status=active,trialing.status) call:- Without
status: exactly one row per subscription — its most recent state, with expired (end_datein the past) and superseded records excluded. - With
status: that deduplication and exclusion is skipped, and matching records are returned directly. A subscription that has passed through the requested status more than once, or whose only matching record has since expired or been superseded, can appear more than once or in a state you didn’t expect.
status for point-in-time queries (“show me everything currently active”); omit it for the current, deduplicated view of each subscription.Fixes
HTTPS pagination links
Paginated list responses’next and previous links now correctly use https:// when the request was made over HTTPS. Previously they were always rendered as http://, regardless of the request’s actual scheme.July 28, 2026
Changes
Itemized Merchant of Record fees
Transaction responses fromGET /transaction/ now include morFeeBreakdown, an array that itemizes the Merchant of Record fee charged for the transaction.Each component includes its name, percentage rate, amount in minor units (valueUnits), and currency. Fixed fees return null for percentage. Transactions without an applicable Merchant of Record fee return an empty array.base_fee, fixed_fee, international_fee, subscription_fee, and conversion_fee. A fee_adjustment component (also null percentage) is included when the calculated fee is raised to match a processor-fee floor.July 17, 2026
New Features
28-day subscription billing
Checkout and subscription creation now support a four-week billing period. PassTWENTY_EIGHT_DAYS as chargePeriod when creating an eligible checkout session or subscription.This is useful for products sold in fixed four-week cycles: renewals happen on the same weekday every four weeks, and metered usage can reset on the same schedule instead of following calendar months.EVERY_28_DAYS as their usage reset period.The new billing period works across renewals, orders, invoices, emails, and subscription reporting. Organizations must enable the 28-day period before using it on a plan.Subscription end dates in webhook payloads
Subscription webhook payloads now includeend_date inside data.object. The field contains an ISO 8601 date when the subscription has a known end date and null when no end date is set.Fixes
Reliable invoice.paid webhook delivery
Kelviq now emits invoice.paid when an invoice is created with a PAID status. Previously, these invoices could emit only invoice.created, which meant integrations waiting for invoice.paid did not receive confirmation that payment had been collected.The event payload has not changed. Continue to use data.object.status, data.object.paid_at, and data.object.subscription_id when processing the event.July 17, 2026
Changes
Multiple customers can use the same email
More than one customer record can now use the same email address. This removes the previous one-customer-per-email restriction.Each record must still have a uniquecustomerId. Archiving a customer does not release that ID, so it cannot be assigned to a new record.July 16, 2026
New Features
List, Create, and Retrieve Refunds
The Refunds API now supports the complete refund workflow:GET /refunds/— List refunds: Returns a paginated list of refunds for the authenticated organization, with search, status, date-range, and pagination filters.POST /refunds/— Create a refund: Creates a full or partial refund for an order. ProvideamountUnitsoramountfor a partial refund, or omit both to refund the remaining balance.GET /refunds/{refundId}/— Retrieve a refund: Returns a refund by its Kelviq UUID.
orderId to identify the order. List results, newly created refunds, and retrieved refunds share the same response format, including the refund amount, reason, status, failure details, internal note, and associated order.July 14, 2026
New Features
Subscription List, Create, and Retrieve APIs
The Subscriptions API now includes three new endpoints for reading and creating subscriptions:GET /subscriptions/— List subscriptions: Retrieves a paginated list for a customer. Thecustomer_idquery parameter is required.POST /subscriptions/create/— Create a subscription: Creates a subscription directly for a customer without requiring a checkout session.GET /subscriptions/{subscriptionId}/— Retrieve a subscription: Retrieves a subscription by its Kelviq UUID.
files— downloadable files attached to the subscription’s plan.links— external links attached to the plan.license— issued licenses associated with the subscription.
One-Time Charges
The newPOST /charges/ endpoint immediately charges a customer’s saved payment method without creating a checkout session. The chargePeriod must be ONE_TIME.May 7, 2026
New Features
Enhanced Checkout Configuration
You can now pass additional configuration parameters when creating a checkout session via the API. These new fields allow for tighter control over the customer experience:lockEmail: When set totrue, the email address field on the checkout page is disabled, preventing customers from changing the email associated with the session.discountsEnabled: A boolean to explicitly allow or disallow discount code application on the checkout page.defaultBillingCountry: Pre-fills the billing country field (e.g.,"IN").
May 7, 2026
New Features
Custom Dynamic Amount Support
Added support for custom dynamic amounts on the checkout page. You can now pass a specificcustom_amount directly via the checkout API, which is ideal for usage-based, variable, or custom-quoted pricing models.-
custom_amount: The specific numeric amount to be charged to the customer. This overrides static plan pricing and is ideal for usage-based, variable, or custom-quoted pricing models. -
tax_behavior: Specifies how taxes should be applied to the custom amount. For example, setting it to “INCLUSIVE” means the tax is already factored into the custom_amount, while “EXCLUSIVE” would add the tax on top of the base amount. -
currency_code: The three-letter ISO currency code (e.g., “INR”, “USD”) that defines the currency in which the custom_amount should be processed.