# Subscriptions

This document explains how the frontend integrates with the backend for subscription management via Stripe, including listing plans, checkout, payment confirmation, billing portal, and cancellation.

{% hint style="info" %}
To perform authenticated operations, you must be authenticated by means of one of the following methods: [BearerAuth](/support-reference/platform-api-reference/authentication.md#http-bearer-authentication). The **list subscriptions** endpoint is public.
{% endhint %}

## Subscriptions API Calls

| Method                                                                        | API Reference                                                                                                                                          | Description                                                   |
| ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------- |
| <mark style="color:green;">`GET`</mark>`/subscriptions`                       | [**get\_\_subscriptions**](/support-reference/platform-api-reference/subscriptions/get__subscriptions.md)                                              | List available subscription plans and periods.                |
| <mark style="color:green;">`GET`</mark>`/subscription/my`                     | [**get\_\_subscription\_my**](/support-reference/platform-api-reference/subscriptions/get__subscription_my.md)                                         | Get the current organization's active subscription status.    |
| <mark style="color:orange;">`POST`</mark>`/subscription/buy`                  | [**post\_\_subscription\_buy**](/support-reference/platform-api-reference/subscriptions/post_subscription_buy.md)                                      | Create a Stripe Checkout Session for a selected subscription. |
| <mark style="color:green;">`GET`</mark>`/subscriptions/checkout-session/{id}` | [**get\_\_subscriptions\_checkout-session\_{id}**](/support-reference/platform-api-reference/subscriptions/get__subscriptions_checkout-session_-id.md) | Get Checkout Session status after payment.                    |
| <mark style="color:orange;">`POST`</mark>`/subscriptions/portal`              | [**post\_\_subscriptions\_portal**](/support-reference/platform-api-reference/subscriptions/post__subscriptions_portal.md)                             | Create a Stripe Billing Portal session (returns URL).         |
| <mark style="color:green;">`GET`</mark>`/subscription/payments`               | [**get\_\_subscription\_payments**](/support-reference/platform-api-reference/subscriptions/get__subscription_payments.md)                             | List organization payments with optional date filters.        |
| <mark style="color:green;">`GET`</mark>`/subscription/pending-payment`        | [**get\_\_subscription\_pending-payment**](/support-reference/platform-api-reference/subscriptions/get__subscription_pending-payment.md)               | Get pending payment information for the organization.         |
| <mark style="color:red;">`DELETE`</mark>`/subscription/pending-payment`       | [**delete\_\_subscription\_pending-payment**](/support-reference/platform-api-reference/subscriptions/delete__subscription_pending-payment.md)         | Cancel a pending subscription payment.                        |
| <mark style="color:orange;">`POST`</mark>`/subscriptions/cancel`              | [**post\_\_subscriptions\_cancel**](/support-reference/platform-api-reference/subscriptions/post__subscriptions_cancel.md)                             | Cancel the current Stripe subscription.                       |

## Overview

This document explains how the frontend integrates with our backend to:

* List available plans and periods
* Start a checkout session (Stripe)
* Confirm payment completion
* Show current subscription status
* Manage billing (payment methods, invoices) via Stripe's Billing Portal
* List payments
* Cancel a subscription

Stripe handles payment capture and billing cycles. Our backend:

* Validates requested plan/period against DB and Stripe configuration
* Creates Stripe Checkout Sessions
* Receives Stripe Webhooks to mark payments as completed/failed/expired and record cancellations
* Exposes REST endpoints for frontend flows

## Terminology mapping

* `Subscription` (DB) \~ Stripe Product
* `SubscriptionPeriod` (DB) \~ Stripe Price
* `OrgSubscription` (DB) \~ Logical subscription status per org (we also infer live state from latest payment)
* `Organization` (DB) \~ Stripe Customer (linked via `stripeCustomerId`)
* `Payments` (DB) \~ Payment/Invoice/Cancellation events (tracked per Stripe events)

## Prerequisites for frontend

* User must be authenticated; tokens must be sent for protected routes.
* For paid checkouts:
  * Backend lazily creates a Stripe Customer (first purchase), then reuses it.
  * The backend returns `checkoutUrl` (direct hosted Checkout URL) and `sessionId`.
* External client lib types: use `SubscriptionTypes.*` DTOs for all request/response typing.

## Data you'll work with (from client lib)

* `SubscriptionTypes.SubscriptionResponse`
* `SubscriptionTypes.SubscriptionPeriodResponse`
* `SubscriptionTypes.BuySubscriptionRequest`
* `SubscriptionTypes.BuySubscriptionResponse`
* `SubscriptionTypes.OrgSubscriptionResponse`
* `SubscriptionTypes.MySubscriptionResponse`
* `SubscriptionTypes.GetSubscriptionsResponse`
* `SubscriptionTypes.PaymentResponse`
* `SubscriptionTypes.PaymentsListResponse`
* `SubscriptionTypes.PaymentsQueryParams`
* `SubscriptionTypes.CancelSubscriptionResponse`
* `SubscriptionTypes.CreateBillingPortalResponse`
* `SubscriptionTypes.GetCheckoutSessionStatusResponse`

## End-to-end flows

### 1) Show available plans (anonymous or authenticated)

* Call GET `subscriptions`.
* Render tier cards: name, description, and available `periods` with `periodType` (ALL\_TIME, MONTHLY, YEARLY, etc.) and `price`.

UI notes:

* Clearly indicate billing interval.
* Grey-out or badge the active plan if already subscribed (requires checking current subscription separately).

### 2) Start checkout for selected plan (Hosted Checkout - Redirect)

* User selects a `SubscriptionPeriodResponse.id`.
* Call POST `subscriptions/buy` with `{ subscriptionPeriodId }`.
* Response:
  * `success: true`
  * `sessionId` (string)
  * `checkoutUrl` (string) ← Use this to redirect the user to Stripe's Hosted Checkout

How to redirect (React):

* On success, immediately navigate the browser to `checkoutUrl`:
  * `window.location.assign(redirectUrl)` or `window.location.href = redirectUrl`
* No Stripe SDK is required in the frontend. The backend already created the Checkout Session and provides the URL.

Environment notes:

* The same backend endpoint is used in test and prod; which Stripe environment you hit is determined by the backend's configured Stripe API key. The `redirectUrl` returned by the backend always points to the correct environment (test or live). You don't need to branch logic in the frontend.

UI notes:

* Handle validation errors (mismatches, active sub, etc.).
* If the org has an active subscription, you'll receive a 409 with an informative error\_code/message.

### 3) Confirm purchase completion (client-side)

* After Hosted Checkout, Stripe redirects the user back to your return URL (`FRONTEND_URL + STRIPE_RETURN_PATH`) with `session_id` in the query string.
* Read `session_id` from the URL and call GET `subscriptions/checkout-session/:id`.
* Expect `status`, `payment_status`, and `subscriptionId` (if recurring).

UI notes:

* Hosted Checkout always redirects; use the provided `checkoutUrl` to start checkout.
* Stripe returns the user to `FRONTEND_URL + STRIPE_RETURN_PATH` with `session_id`; read it and confirm via the status endpoint.
* After checkout completes, poll GET `subscriptions/checkout-session/:id` 2–3 times over \~5–10 seconds before showing success. Webhook processing may complete milliseconds after the user returns.

### 4) Show current subscription status

* Call GET `subscriptions/my`.
* Returns either null or `OrgSubscriptionResponse` with:
  * `periodType`, `price`, `dateFrom`, `dateTo` (if recurring), `status` and `autoRenew`.

UI notes:

* If `status` is ACTIVE and `dateTo` present in the future, show next renewal/expiry.
* If `ALL_TIME`, `dateTo` is null; show "lifetime" badge.

### 5) Manage billing (payment methods, invoices)

* Call POST `subscriptions/portal`.
* Response: `{ success, url }`.
* Open `url` in a new tab to let the user manage card, invoices, and billing info.

UI notes:

* Portal returns to your `FRONTEND_URL` when done.

### 6) View payments

* Call GET `subscriptions/payments?startDate=&endDate=`.
* Response includes `PaymentResponse` items with `status`, `currency`, `amount`, `timestamp`.

UI notes:

* Sort by time desc; show badges for `COMPLETED`, `FAILED`, `EXPIRED`, `CANCELLED`.

### 7) Cancel subscription

* Call POST `subscriptions/cancel`.
* Backend validates and cancels the Stripe subscription.
* You get `{ success: true }` or an error\_code if cancellation isn't allowed (e.g., already canceled).

UI notes:

* On success, you may still show benefits until `dateTo` (period-end cancellations).
* For immediate cancellations, reflect `CANCELLED` status and remove auto-renew badges.

## Error handling

* All endpoints return `{ success: false, error_code, message }` on error.
* Common error codes include: USER\_NOT\_FOUND, NO\_ORGANIZATION, SUBSCRIPTION\_PERIOD\_NOT\_FOUND, SUBSCRIPTION\_ALREADY\_ACTIVE, STRIPE\_PRICE\_\* mismatches, STRIPE\_CANCELLATION\_FAILED, INVALID\_SESSION.
* Show human-friendly messages derived from `message`.

## Webhooks (FYI)

* The backend processes Stripe webhooks and:
  * Marks session payments as COMPLETED/FAILED/EXPIRED in `Payments`
  * Records cancellation events as CANCELLED payments
  * (Planned) Maintains `OrgSubscription` lifecycle
* Frontend does not call webhooks. Instead, it:
  * Polls `subscriptions/checkout-session/:id` post-checkout
  * Calls `subscriptions/my` to display current status

## Typical UI sequence examples

* New paid subscription:
  1. GET `subscriptions`
  2. POST `subscriptions/buy` (with selected `subscriptionPeriodId`)
  3. Redirect to `checkoutUrl`
  4. On return (with `session_id`): GET `subscriptions/checkout-session/:id`
  5. GET `subscriptions/my` to show status
* Manage payment method:
  1. POST `subscriptions/portal` → open returned `url`
* Show billing history:
  1. GET `subscriptions/payments` (with optional date filters)
* Cancel:
  1. POST `subscriptions/cancel`
  2. GET `subscriptions/my` to refresh the status

## Client wrappers (examples)

Assuming your API client has `makeRequest<T>(path, method, body)`:

```ts
public getSubscriptions = async (): Promise<SubscriptionTypes.GetSubscriptionsResponse> => {
  return this.makeRequest<SubscriptionTypes.GetSubscriptionsResponse>('subscriptions', 'GET', null);
};

public getMySubscription = async (): Promise<SubscriptionTypes.MySubscriptionResponse> => {
  return this.makeRequest<SubscriptionTypes.MySubscriptionResponse>('subscriptions/my', 'GET', null);
};

public buySubscription = async (data: SubscriptionTypes.BuySubscriptionRequest): Promise<SubscriptionTypes.BuySubscriptionResponse> => {
  return this.makeRequest<SubscriptionTypes.BuySubscriptionResponse>('subscriptions/buy', 'POST', data);
};

public getCheckoutSessionStatus = async (id: string): Promise<GetCheckoutSessionStatusResponse> => {
  return this.makeRequest<GetCheckoutSessionStatusResponse>(`subscriptions/checkout-session/${id}`, 'GET', null);
};

public createBillingPortal = async (): Promise<CreateBillingPortalResponse> => {
  return this.makeRequest<CreateBillingPortalResponse>('subscriptions/portal', 'POST', null);
};

public getPayments = async (params?: SubscriptionTypes.PaymentsQueryParams): Promise<SubscriptionTypes.PaymentsListResponse> => {
  const queryParams = new URLSearchParams();
  if (params?.startDate) queryParams.append('startDate', params.startDate);
  if (params?.endDate) queryParams.append('endDate', params.endDate);
  return this.makeRequest<SubscriptionTypes.PaymentsListResponse>(
    `subscriptions/payments${queryParams.toString() ? `?${queryParams.toString()}` : ''}`,
    'GET',
    null,
  );
};

public cancelSubscription = async (): Promise<SubscriptionTypes.CancelSubscriptionResponse> => {
  return this.makeRequest<SubscriptionTypes.CancelSubscriptionResponse>('subscriptions/cancel', 'POST', null);
};
```

## Testing checklist (sandbox)

* Plans loaded from GET `subscriptions`.
* Checkout succeeds for each period type; `Payments` show COMPLETED; `subscriptions/my` reflects status and dates.
* Failure paths (use Stripe test cards) show FAILED/EXPIRED.
* Portal opens and returns correctly.
* Cancellation sets appropriate state; immediate vs period-end behaves as expected.

## Notes and caveats

* Embedded checkout uses `ui_mode=embedded` and `redirect_on_completion=if_required`.
* For recurring periods, metadata is passed so renewals can be tracked reliably.
* If you ever see an active subscription blocking new purchases, the backend will respond with 409 and an explanatory message.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.flashback.tech/support-reference/platform-api-reference/subscriptions.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
