> ## Documentation Index
> Fetch the complete documentation index at: https://docs.opigno.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Purchasing a Learning Path with Stripe

## Overview

Opigno Enterprise API allows learners to purchase access to a Learning Path through **Stripe Checkout**.
A Learning Path becomes purchasable once it is enabled for commercial use in the backoffice and has an associated Stripe product.

<Note>
  Currently, `LearningPath` is the only entity type that can be purchased through Stripe. Other purchasable
  entity types may be added in the future — the API exposes this as the `PurchasableEntity` union.
</Note>

The purchase flow is built around two objects:

* **`StripeProduct`** — describes the product being sold (name, description, images, price, currency) and the entity it unlocks.
* **`StripeCheckoutSession`** — represents a single checkout attempt: it holds the hosted Stripe checkout URL and tracks both the session and payment status.

At a high level, the flow looks like this:

<Steps>
  <Step title="Fetch the product information">
    Call `getLearningPathProductInfo` to display the price, currency, name and description of the Learning Path to the learner before checkout.
  </Step>

  <Step title="Create a checkout session">
    Call `createLearningPathStripeCheckoutSession` to obtain a `checkoutUrl`, then redirect the learner to it.
  </Step>

  <Step title="Redirect to Stripe">
    The learner completes (or abandons) the payment on the Stripe-hosted checkout page.
  </Step>

  <Step title="Confirm the result">
    After Stripe redirects the learner back to `successRedirectUrl`, call `getLearningPathStripeCheckoutSession` (or rely on your own webhook/backoffice flow) to confirm that `sessionStatus` is `COMPLETED` and `paymentStatus` is `PAID` before granting access.
  </Step>
</Steps>

## Learning Path CTA

When Stripe integration is enabled and a Learning Path has an associated Stripe product, the [Learning Path CTAs](/OpignoEnterpriseAPI/LearningPathCTA) returned by the API change to reflect that the Learning Path must be purchased before it can be accessed:

| CTA action ID           | Returned for        | Corresponding query/mutation                                            | Description                                                                                                                                                      |
| :---------------------- | :------------------ | :---------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `PURCHASE_LP`           | Authenticated users | [`createLearningPathStripeCheckoutSession`](#create-a-checkout-session) | Returned instead of `ENROLL_LP`. Indicates that the learner must complete a Stripe payment before being enrolled into the Learning Path.                         |
| `LOGIN_AND_PURCHASE_LP` | Anonymous users     | [`createLearningPathStripeCheckoutSession`](#create-a-checkout-session) | Returned instead of `LOGIN_AND_ENROLL_LP`. Indicates that the learner must authenticate first, then complete the Stripe payment. **Authentication is required.** |

<Note>
  These CTAs replace `ENROLL_LP` / `LOGIN_AND_ENROLL_LP` only for Learning Paths that have a Stripe product ID configured.
  Learning Paths without Stripe integration keep the standard enrollment CTAs described in the
  [Learning Path CTA reference](/OpignoEnterpriseAPI/LearningPathCTA).
</Note>

## Enrollment access with Stripe

For Learning Paths with Stripe integration enabled, [enrollment](/OpignoEnterpriseAPI/LearningPathRegistration) gets an additional access layer on top of the standard rules:

* The learner is **automatically enrolled** into the Learning Path once their Stripe checkout session reaches `sessionStatus: COMPLETED` and `paymentStatus: PAID`. There's no need to call `createLpIndividualMembership` after a successful payment — the membership is created automatically.
* Enrollment into a commercial Learning Path is available **only for authenticated user contexts**. Anonymous user contexts can no longer be enrolled into a Learning Path that requires a Stripe payment; the learner must authenticate before purchasing, as reflected by the `LOGIN_AND_PURCHASE_LP` CTA above.

<Warning>
  This is a change compared to standard (non-commercial) Learning Paths, where anonymous self-enrollment may be allowed
  depending on the training visibility settings (see the `LOGIN_AND_ENROLL_LP` CTA in the
  [Learning Path CTA reference](/OpignoEnterpriseAPI/LearningPathCTA)). Once a Learning Path is configured for Stripe payments,
  anonymous enrollment is no longer available for it.
</Warning>

## Retrieve product information

Use the `getLearningPathProductInfo` query to fetch the Stripe product details attached to a Learning Path,
so pricing information can be displayed to the learner ahead of the checkout.

**Access Policy:**

* The API user context must be present, be valid, not blocked and associated with an authenticated scope.
* The requested Learning Path should exist, be published and have a Stripe product ID.
* The API user must have permission to view the specified Learning Path; otherwise, access is denied.

The query accepts the following arguments:

| Argument | Type  | Description                                          |
| :------- | :---- | :--------------------------------------------------- |
| `lpId`   | `ID!` | Required; ID of the associated Learning Path entity. |

As a result, a `StripeProduct` object will be returned:

| Property      | Type                 | Description                                                                    |
| :------------ | :------------------- | :----------------------------------------------------------------------------- |
| `id`          | `ID!`                | Stripe product identifier.                                                     |
| `name`        | `String!`            | Stripe product name.                                                           |
| `description` | `String`             | Stripe product description.                                                    |
| `images`      | `[String!]`          | List of Stripe product image URLs.                                             |
| `currency`    | `String!`            | Three-letter ISO currency code, in lowercase (e.g. `usd`).                     |
| `price`       | `String!`            | The singular unit price of the product.                                        |
| `node`        | `PurchasableEntity!` | The purchasable entity the product unlocks. Currently always a `LearningPath`. |

<CodeGroup>
  ```graphql GraphQL theme={null}
  query getLearningPathProductInfo {
    getLearningPathProductInfo(lpId: 40) {
      id
      name
      description
      images
      currency
      price
      node {
        ... on LearningPath {
          id
          training {
            title
          }
        }
      }
    }
  }
  ```

  ```json Query result theme={null}
  {
    "data": {
      "getLearningPathProductInfo": {
        "id": "prod_QhZ1example",
        "training": {
          "title": "Advanced Cloud Architecture"
        },
        "description": "Full access to the Advanced Cloud Architecture learning path.",
        "images": [
          "https://files.stripe.com/links/example-product-image.png"
        ],
        "currency": "usd",
        "price": "49.99",
        "node": {
          "id": "40",
          "title": "Advanced Cloud Architecture"
        }
      }
    }
  }
  ```
</CodeGroup>

## Retrieve an existing checkout session

Use the `getLearningPathStripeCheckoutSession` query to retrieve the current Stripe checkout session for a Learning Path,
for example to resume checking a payment status after the learner returns from Stripe, or to check whether a session already exists.

**Access Policy:**

* The API user context must be present, be valid and not blocked.
* The API user must have permission to view the specified Learning Path; otherwise, access is denied.
* The requested Learning Path should exist, be published and have a Stripe product ID.

The query accepts the following arguments:

| Argument          | Type  | Description                                                                                                             |
| :---------------- | :---- | :---------------------------------------------------------------------------------------------------------------------- |
| `lpId`            | `ID!` | Required; ID of the associated Learning Path entity.                                                                    |
| `userContextUuid` | `ID`  | The UUID of the user context associated with the Stripe session. If not set, the context is retrieved from the request. |

If no checkout session exists yet for the given Learning Path and user context, the query returns `null`.

<CodeGroup>
  ```graphql GraphQL theme={null}
  query getLearningPathStripeCheckoutSession {
    getLearningPathStripeCheckoutSession(lpId: 40, userContextUuid: "a1b2c3d4-e5f6-7890-abcd-ef1234567890") {
      id
      sessionStatus
      paymentStatus
      checkoutUrl
      successRedirectUrl
    }
  }
  ```

  ```json Query result theme={null}
  {
    "data": {
      "getLearningPathStripeCheckoutSession": {
        "id": "cs_test_a1b2c3example",
        "sessionStatus": "PENDING",
        "paymentStatus": "UNPAID",
        "checkoutUrl": "https://checkout.stripe.com/c/pay/cs_test_a1b2c3example",
        "successRedirectUrl": "https://example.com/learning-path/40/thank-you"
      }
    }
  }
  ```
</CodeGroup>

## Create a checkout session

Once the learner is ready to pay, use the `createLearningPathStripeCheckoutSession` mutation to create a Stripe checkout session and
redirect the learner to the returned `checkoutUrl`.

**Access Policy:**

* The API user context must be present, be valid and not blocked.
* Stripe checkout session creation is only available for Learning Paths enabled for commercial use.
* The API user must have permission to view the specified Learning Path; otherwise, access is denied.

The mutation accepts the following arguments:

| Argument             | Type      | Description                                                                                                                                              |
| :------------------- | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `lpId`               | `ID!`     | Required; ID of the Learning Path to purchase.                                                                                                           |
| `userContextUuid`    | `ID`      | The UUID of the user context associated with the Stripe session. If not set, the context is retrieved from the request.                                  |
| `forceNew`           | `Boolean` | Whether a new Stripe session should be forcibly created, even if a session already exists. Defaults to `false`.                                          |
| `successRedirectUrl` | `String`  | Optional URL the customer is redirected to after a successful payment. If a session already exists, its `successRedirectUrl` is updated with this value. |

<Note>
  If a non-expired checkout session already exists for the given Learning Path and user context, the mutation returns
  that existing session instead of creating a new one, unless `forceNew` is set to `true`.
</Note>

As a result, a `CreateStripeCheckoutSessionResponse` object will be returned:

| Property   | Type                     | Description                                               |
| :--------- | :----------------------- | :-------------------------------------------------------- |
| `errors`   | `[Violation]`            | Contains the list of validation errors, if there are any. |
| `response` | `StripeCheckoutSession!` | The created (or existing) Stripe checkout session object. |

**`StripeCheckoutSession` object**

| Property             | Type                           | Description                                                                                          |
| :------------------- | :----------------------------- | :--------------------------------------------------------------------------------------------------- |
| `id`                 | `ID!`                          | The checkout session ID.                                                                             |
| `userContext`        | `UserContext!`                 | The user context associated with the session.                                                        |
| `product`            | `StripeProduct!`               | The purchased product, see [Retrieve product information](#retrieve-product-information).            |
| `sessionStatus`      | `StripeCheckoutSessionStatus!` | The status of the checkout session, see below.                                                       |
| `paymentStatus`      | `StripePaymentStatus!`         | The status of the payment, see below.                                                                |
| `checkoutUrl`        | `String!`                      | The Stripe-hosted checkout URL the learner should be redirected to in order to complete the payment. |
| `successRedirectUrl` | `String`                       | Optional URL the customer is redirected to after a successful payment.                               |

`StripeCheckoutSessionStatus` can be one of:

| Value       | Description                                                |
| :---------- | :--------------------------------------------------------- |
| `PENDING`   | The checkout is waiting for evaluation.                    |
| `COMPLETED` | The checkout was completed.                                |
| `EXPIRED`   | The checkout wasn't completed and the session has expired. |
| `FAILED`    | The payment has failed.                                    |

`StripePaymentStatus` can be one of:

| Value    | Description                               |
| :------- | :---------------------------------------- |
| `PAID`   | The payment was successfully transferred. |
| `UNPAID` | The payment isn't accomplished yet.       |

Below is an example of creating a checkout session for the Learning Path with ID 40:

<CodeGroup>
  ```graphql GraphQL theme={null}
  mutation createLearningPathStripeCheckoutSession {
    createLearningPathStripeCheckoutSession(
      lpId: 40
      userContextUuid: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
      successRedirectUrl: "https://example.com/learning-path/40/thank-you"
    ) {
      errors
      response {
        id
        sessionStatus
        paymentStatus
        checkoutUrl
        successRedirectUrl
      }
    }
  }
  ```

  ```json Query result theme={null}
  {
    "data": {
      "createLearningPathStripeCheckoutSession": {
        "errors": [],
        "response": {
          "id": "cs_test_a1b2c3example",
          "sessionStatus": "PENDING",
          "paymentStatus": "UNPAID",
          "checkoutUrl": "https://checkout.stripe.com/c/pay/cs_test_a1b2c3example",
          "successRedirectUrl": "https://example.com/learning-path/40/thank-you"
        }
      }
    }
  }
  ```
</CodeGroup>

<Warning>
  Redirect the learner to `checkoutUrl` right after the mutation completes. Stripe checkout sessions are time-limited
  and will move to the `EXPIRED` status if the payment isn't completed in time.
</Warning>
