From c945d22a0359233711156163fc7693ccf52fcade Mon Sep 17 00:00:00 2001 From: "Panche I." Date: Tue, 18 Aug 2026 14:40:41 +0200 Subject: [PATCH 1/2] feat(pay): subscription invoices + plan id on Subscription Add subscriptions.invoices(id) for billing history. Surface paymentLinkId and cancel fields on Subscription so integrators can match a plan and drive status/cancel. Copy link ID on the product page is paymentLinks.id. --- .changeset/pay-subscription-invoices.md | 5 +++++ packages/pay/src/index.ts | 1 + packages/pay/src/resources/resources.test.ts | 13 +++++++++++++ packages/pay/src/resources/subscriptions.ts | 6 ++++++ packages/pay/src/types.ts | 20 +++++++++++++++++++- 5 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 .changeset/pay-subscription-invoices.md diff --git a/.changeset/pay-subscription-invoices.md b/.changeset/pay-subscription-invoices.md new file mode 100644 index 0000000..15c66ed --- /dev/null +++ b/.changeset/pay-subscription-invoices.md @@ -0,0 +1,5 @@ +--- +"@agentaos/pay": minor +--- + +Add `subscriptions.invoices(id)` and expose `paymentLinkId` / cancel fields on `Subscription` so a logged-in SaaS can match a plan, list billing history, and cancel. diff --git a/packages/pay/src/index.ts b/packages/pay/src/index.ts index 7be31db..4ccc161 100644 --- a/packages/pay/src/index.ts +++ b/packages/pay/src/index.ts @@ -14,6 +14,7 @@ export type { Invoice, ListInvoiceParams, Subscription, + SubscriptionInvoice, SubscriptionStatus, CancelSubscriptionParams, CancelSubscriptionResult, diff --git a/packages/pay/src/resources/resources.test.ts b/packages/pay/src/resources/resources.test.ts index 207999c..3e657b5 100644 --- a/packages/pay/src/resources/resources.test.ts +++ b/packages/pay/src/resources/resources.test.ts @@ -267,6 +267,19 @@ describe('subscriptions', () => { await client().subscriptions.cancel('sub_1', { atPeriodEnd: false }); expect(JSON.parse(calls[0]?.body ?? '{}')).toEqual({ atPeriodEnd: false }); }); + + it('invoices → GET /api/v1/gateway/subscriptions/:id/invoices', async () => { + const calls = stubRoutes([ + { id: 'inv_1', invoice_number: 'INV-2026-0001', issued_at: '2026-08-18T00:00:00Z' }, + ]); + const rows = await client().subscriptions.invoices('sub_1'); + expect(calls[0]?.method).toBe('GET'); + expect(pathOf(calls[0])).toBe('/api/v1/gateway/subscriptions/sub_1/invoices'); + expect(rows[0]).toMatchObject({ + invoiceNumber: 'INV-2026-0001', + issuedAt: '2026-08-18T00:00:00Z', + }); + }); }); describe('customers', () => { diff --git a/packages/pay/src/resources/subscriptions.ts b/packages/pay/src/resources/subscriptions.ts index f8e9a5d..1e1d316 100644 --- a/packages/pay/src/resources/subscriptions.ts +++ b/packages/pay/src/resources/subscriptions.ts @@ -4,6 +4,7 @@ import type { ListParams, PaginatedList, Subscription, + SubscriptionInvoice, } from '../types.js'; import { BaseResource } from './base.js'; @@ -34,4 +35,9 @@ export class SubscriptionsResource extends BaseResource { atPeriodEnd: params?.atPeriodEnd ?? true, }); } + + /** Per-cycle invoices for one subscription, newest first. */ + async invoices(id: string): Promise { + return this.get(`${BASE_PATH}/${id}/invoices`); + } } diff --git a/packages/pay/src/types.ts b/packages/pay/src/types.ts index 9c6a428..ffff393 100644 --- a/packages/pay/src/types.ts +++ b/packages/pay/src/types.ts @@ -96,6 +96,7 @@ export interface CreatePaymentLinkParams { } export interface PaymentLink { + /** Same value as `checkouts.create({ linkId })`. On the product page: Copy link ID. */ id: string; orgId: string; amount: number; @@ -130,7 +131,7 @@ export interface PaymentLink { // --------------------------------------------------------------------------- export interface CreateCheckoutParams { - /** Link ID to create checkout from. Optional — omit to create a standalone checkout. */ + /** `paymentLinks.id`. On the product page this is Copy link ID. Omit for a standalone checkout. */ linkId?: string; /** Amount in currency units (e.g. 10.00). Required if no linkId. */ amount?: number; @@ -292,6 +293,8 @@ export interface Subscription { customerName: string | null; /** The plan (subscription payment-link) name or description. */ planName: string | null; + /** Plan id. Same as `paymentLinks.id` / product page Copy link ID. Your metadata stays on the checkout. */ + paymentLinkId: string; billingInterval: 'month' | 'year' | null; status: SubscriptionStatus; /** Per-cycle amount in integer minor units (e.g. 1999 = €19.99). */ @@ -300,6 +303,21 @@ export interface Subscription { /** ISO 8601 end of the current paid period; null before the first cycle books. */ currentPeriodEnd: string | null; stripeSubscriptionId: string | null; + cancelAtPeriodEnd: boolean; + canceledAt: string | null; + effectiveCancelDate: string | null; +} + +/** One cycle invoice from GET /gateway/subscriptions/:id/invoices. */ +export interface SubscriptionInvoice { + id: string; + invoiceNumber: string; + status: string; + issuedAt: string; + amount: number; + currency: string; + disputed: boolean; + chargedBack: boolean; } export interface CancelSubscriptionParams { From a3e7d4d7f322c91bd90637f5f4d483ee47e34a0b Mon Sep 17 00:00:00 2001 From: "Panche I." Date: Tue, 18 Aug 2026 16:14:54 +0200 Subject: [PATCH 2/2] fix(pay): Subscription.linkId matches checkouts.create Rename Subscription.paymentLinkId to linkId. Checkout.paymentLinkId is unchanged (that is the session column camelCase). --- .changeset/pay-subscription-invoices.md | 2 +- packages/pay/src/types.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.changeset/pay-subscription-invoices.md b/.changeset/pay-subscription-invoices.md index 15c66ed..5e36b5a 100644 --- a/.changeset/pay-subscription-invoices.md +++ b/.changeset/pay-subscription-invoices.md @@ -2,4 +2,4 @@ "@agentaos/pay": minor --- -Add `subscriptions.invoices(id)` and expose `paymentLinkId` / cancel fields on `Subscription` so a logged-in SaaS can match a plan, list billing history, and cancel. +Add `subscriptions.invoices(id)` and expose `linkId` / cancel fields on `Subscription` so a logged-in SaaS can match a product, list billing history, and cancel. diff --git a/packages/pay/src/types.ts b/packages/pay/src/types.ts index ffff393..3173a10 100644 --- a/packages/pay/src/types.ts +++ b/packages/pay/src/types.ts @@ -293,8 +293,8 @@ export interface Subscription { customerName: string | null; /** The plan (subscription payment-link) name or description. */ planName: string | null; - /** Plan id. Same as `paymentLinks.id` / product page Copy link ID. Your metadata stays on the checkout. */ - paymentLinkId: string; + /** Same UUID as `checkouts.create({ linkId })` / product page Copy link ID. */ + linkId: string; billingInterval: 'month' | 'year' | null; status: SubscriptionStatus; /** Per-cycle amount in integer minor units (e.g. 1999 = €19.99). */