Skip to content

[api] [user] Add more secure endpoint for downloading invoice of user…#8

Merged
swashata merged 2 commits intomainfrom
feature/swas/vibe-coding-improvements
Mar 1, 2026
Merged

[api] [user] Add more secure endpoint for downloading invoice of user…#8
swashata merged 2 commits intomainfrom
feature/swas/vibe-coding-improvements

Conversation

@swashata
Copy link
Collaborator

… + Add sample codes for vibe code platform integrations

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds SDK support for a more secure “download invoice for a user’s payment” API endpoint and includes a manual integration example showcasing pricing/portal flows (including invoice download).

Changes:

  • Added a new OpenAPI path + operation for /users/{user_id}/payments/{payment_id}/invoice.pdf (PDF invoice download).
  • Added User.retrieveInvoice(userId, paymentId) to fetch the invoice PDF.
  • Added a new manual example script for “vibe code platform” integrations and invoice retrieval.

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 1 comment.

File Description
packages/sdk/src/api/schema.d.ts Updates generated OpenAPI typings to include the new secure invoice download endpoint.
packages/sdk/src/api/User.ts Adds retrieveInvoice() method on the User API.
packages/sdk/src/__tests__/manual/vibe-code-platform-integration.ts Adds a manual integration/example script including invoice retrieval usage.
Comments suppressed due to low confidence (2)

packages/sdk/src/tests/manual/vibe-code-platform-integration.ts:34

  • With exactOptionalPropertyTypes: true, passing planId: planId where planId is string | undefined is a real type error (hence the @ts-expect-error). Instead of suppressing types, build the options object so planId is omitted when undefined (or narrow planId before passing it). This keeps the example type-safe and avoids relying on compiler suppression.
async function createFreemiusCheckout(
    user: { email: string; firstName?: string; lastName?: string },
    planId?: string
): Promise<Checkout> {
    // @ts-expect-error - The planId can be undefined and depending on some TS config it can cause error, but in practice this is fine.
    const checkout = await freemius.checkout.create({
        user,
        planId: planId,
        isSandbox: SANDBOX,
    });

packages/sdk/src/tests/manual/vibe-code-platform-integration.ts:49

  • const hasActiveSubscription = subscription?.canceled_at == null evaluates to true when subscription is null/undefined (because undefined == null), which can incorrectly treat a missing/failed subscription fetch as an active subscription. Use a strict check that only returns true when a subscription exists and is not cancelled (e.g. subscription?.canceled_at === null).
    const subscription = entitlement ? await freemius.api.license.retrieveSubscription(entitlement.fsLicenseId) : null;
    const hasActiveSubscription = subscription?.canceled_at == null;

payment_id: this.getIdForPath(paymentId),
},
},
responseType: 'blob',
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

openapi-fetch client options use parseAs: 'blob' for binary/PDF responses (see Payment.retrieveInvoice). responseType: 'blob' is not part of the openapi-fetch API, so this likely won’t typecheck and may not parse the PDF correctly at runtime. Switch this call to use parseAs: 'blob' (and remove responseType).

Suggested change
responseType: 'blob',
parseAs: 'blob',

Copilot uses AI. Check for mistakes.
@swashata swashata requested a review from Copilot February 26, 2026 10:07
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (4)

packages/sdk/src/tests/manual/vibe-code-platform-integration.ts:208

  • These commented-out test invocations with hardcoded production credentials should be removed before committing. Leaving commented-out code with real credentials in the repository poses a security risk and reduces code maintainability. If these are needed for testing, they should be in a separate local file that's gitignored, or use environment variables for credentials.
// getSubscriptionAndPayments({ fsLicenseId: '1868256', fsUserId: '5723112' }).then((data) => {
//     console.log(data);
// });

async function cancelSubscription(entitlement: Pick<PurchaseEntitlementData, 'fsLicenseId'>): Promise<boolean> {
    const subscription = await freemius.api.license.retrieveSubscription(entitlement.fsLicenseId);

    if (!subscription || subscription.canceled_at != null) {
        return false;
    }

    await freemius.api.subscription.cancel(subscription.id!);

    return true;
}

// cancelSubscription({ fsLicenseId: '1867816' }).then((result) => {
//     console.log('Cancellation result:', result);
// });

async function getInvoice(userId: string, paymentId: string): Promise<Blob | null> {
    const invoice = await freemius.api.user.retrieveInvoice(userId, paymentId);

    return invoice;
}

// getInvoice('5723112', '1917010').then((invoice) => {
//     if (invoice) {
//         console.log('Invoice retrieved successfully:', invoice);
//     } else {
//         console.log('Failed to retrieve invoice.');
//     }
// });

packages/sdk/src/tests/manual/vibe-code-platform-integration.ts:34

  • The @ts-expect-error directive is suppressing a type error for potentially undefined planId. According to the TypeScript best practice and the minimalist philosophy mentioned in the coding guidelines, this should be handled explicitly. Either make planId optional in the checkout.create() signature or handle the undefined case properly without suppressing the error.
    // @ts-expect-error - The planId can be undefined and depending on some TS config it can cause error, but in practice this is fine.
    const checkout = await freemius.checkout.create({
        user,
        planId: planId,
        isSandbox: SANDBOX,
    });

packages/sdk/src/api/User.ts:257

  • The return type is inconsistent with the similar method in Payment.ts. The Payment.retrieveInvoice method explicitly casts the response to Blob (line 58 in Payment.ts), but this method returns response.data directly. For consistency and type safety, consider explicitly typing or casting the return value to Blob, similar to the existing Payment.retrieveInvoice implementation.
        return response.data;

packages/sdk/src/tests/manual/vibe-code-platform-integration.ts:119

  • This sample code contains hardcoded production credentials (email and license/plan IDs). For a manual test/example file that may be committed to the repository, these should be replaced with placeholder values or environment variables to avoid exposing real user data.
getPricingData({ email: 'swas@freemius.com' }, { fsLicenseId: '1868448', fsPlanId: '40918' }).then((data) => {
    console.log(data);
});

… + Add sample codes for vibe code platform integrations

[api] Use a different endpoint

[fix] Per feedback

[test] Improve the data structure of the vibe code UI

[changeset]
@swashata swashata force-pushed the feature/swas/vibe-coding-improvements branch from ac3a5e4 to afd82c3 Compare March 1, 2026 07:13
@swashata swashata merged commit fea93c4 into main Mar 1, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants