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

# Orders & Payments

> Integrate payment collection with orders using your own payment provider or managed payment sessions

Orders and payment collection work together to handle purchases in the Connect API. Orders track what a customer is buying, while payments -- collected through your own provider or via managed payment sessions -- fulfill the payment requirement before the order can be submitted.

## Core Concept

Every order has **requirements** that must be met before submission:

* **requiresPayment**: Whether the order needs payment before it can be fulfilled
* **requiresPaymentProfile**: Whether a stored payment method is needed for future billing
* **requiresSigning**: Whether the order requires a digital signature

Each requirement can be `NOT_REQUIRED`, `OPTIONAL`, or `REQUIRED`. Check these after calculating the price to determine the correct submission flow.

<Note>
  Zero-total orders may not require payment at all. Always check the order
  requirements rather than assuming payment is needed.
</Note>

## Quick Path

<Steps>
  <Step title="Create Order" icon="cart-shopping">
    Create an order and add line items for the products the customer wants to buy.
  </Step>

  <Step title="Calculate Price" icon="calculator">
    Calculate taxes and totals to determine the amount due.
  </Step>

  <Step title="Check Requirements" icon="clipboard-check">
    Inspect the order requirements to determine if payment, a payment profile, or signing is needed.
  </Step>

  <Step title="Collect Payment" icon="credit-card">
    Collect payment through your own provider or use a managed payment session.
  </Step>

  <Step title="Submit Order" icon="circle-check">
    Submit the order with the payment reference to begin fulfillment.
  </Step>
</Steps>

## Choosing a Payment Approach

The Connect API gives you full flexibility in how you collect payments. You can use your own payment infrastructure or leverage managed payment sessions depending on your needs.

<Columns cols={3}>
  <Card title="Your Own Provider (Recommended)" icon="building-columns">
    Collect payment through your existing payment stack (Stripe, Adyen, Braintree, etc.) and pass the reference when submitting the order. Full control over the checkout experience, payment methods, and provider relationship.
  </Card>

  <Card title="Hosted Payment Page" icon="browser">
    Use a managed payment session with `hosted: true` to get a provider-hosted checkout URL. Redirect customers to a pre-built payment page with no frontend payment UI to build.
  </Card>

  <Card title="Embedded Payment Widget" icon="code">
    Use a managed payment session with `hosted: false` to get provider credentials for rendering a payment form directly in your UI using the provider's SDK.
  </Card>
</Columns>

### When to Use Each Approach

| Approach                | Best for                                                                                                                               |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| **Your own provider**   | Teams with an existing payment infrastructure who want full control over the payment experience, provider selection, and checkout flow |
| **Hosted payment page** | Quick integrations where you want a turnkey payment UI without building frontend payment components                                    |
| **Embedded widget**     | Teams who want a managed payment backend but need to customize the payment UI within their application                                 |

<Info>
  Most integrations use the external payment approach because it lets you keep your
  existing payment provider, maintain a single payment relationship, and have
  complete control over the customer checkout experience.
</Info>

## 1. Create an Order and Add Line Items

Create an order for a customer and include the products they want to purchase.

```javascript theme={null}
const response = await fetch("https://connect.telnesstech.com/api/v2/orders", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.CONNECT_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    customer: {
      customerId: "123e4567-e89b-12d3-a456-426614174000",
    },
    lineItems: [
      {
        type: "SUBSCRIPTION",
        lineItemId: "sub-1",
        productOfferingId: "offering-id",
        subscriber: {
          name: "Jane Doe",
          email: "jane@example.com",
        },
      },
    ],
  }),
});

const order = await response.json();
const orderId = order.orderId;
```

You can also add line items to an existing order separately:

```javascript theme={null}
await fetch(
  `https://connect.telnesstech.com/api/v2/orders/${orderId}/line-items`,
  {
    method: "POST",
    headers: {
      "X-API-Key": process.env.CONNECT_API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      type: "ADDON",
      lineItemId: "addon-1",
      productOfferingId: "addon-offering-id",
      parentLineItemId: "sub-1",
    }),
  },
);
```

See [Create Order](/api-reference/orders/create-order) and [Add Line Items](/api-reference/orders/add-line-items-to-order)

## 2. Calculate the Price

Calculate taxes and totals before collecting payment.

```javascript theme={null}
const priceResponse = await fetch(
  `https://connect.telnesstech.com/api/v2/orders/${orderId}/calculate-price`,
  {
    method: "POST",
    headers: {
      "X-API-Key": process.env.CONNECT_API_KEY,
      "Content-Type": "application/json",
    },
  },
);

const pricedOrder = await priceResponse.json();
console.log("Total:", pricedOrder.pricing.total);
console.log("Currency:", pricedOrder.pricing.currency);
```

See [Calculate Order Price](/api-reference/orders/calculate-order-price)

## 3. Check Order Requirements

After calculating the price, inspect the order to determine what is needed before submission.

```javascript theme={null}
const orderResponse = await fetch(
  `https://connect.telnesstech.com/api/v2/orders/${orderId}`,
  {
    headers: {
      "X-API-Key": process.env.CONNECT_API_KEY,
    },
  },
);

const orderDetails = await orderResponse.json();

const { requiresPayment, requiresPaymentProfile, requiresSigning } =
  orderDetails.requirements;

if (requiresPayment === "REQUIRED") {
  // Collect payment through your provider or via a payment session
}

if (requiresPaymentProfile === "REQUIRED") {
  // Set up a payment profile session for recurring billing
}

if (requiresSigning === "REQUIRED") {
  // Create a signing session for digital signature
}
```

See [Get Order](/api-reference/orders/get-order)

## 4. Collect Payment

Once you know the order requires payment, choose one of the following approaches.

### Option A: Your Own Payment Provider (Recommended)

Collect payment through your existing payment provider (Stripe, Adyen, Braintree, or any other provider). This approach gives you full control over the checkout experience and lets you use your existing payment infrastructure without any additional dependencies.

After collecting payment on your side, submit the order with an `externalPayment` reference:

```javascript theme={null}
// Step 1: Collect payment through your own provider
// (This happens in your existing payment flow)

// Step 2: Submit the order with the payment reference
const submitResponse = await fetch(
  `https://connect.telnesstech.com/api/v2/orders/${orderId}/submit`,
  {
    method: "POST",
    headers: {
      "X-API-Key": process.env.CONNECT_API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      externalPayment: {
        reference: "pi_3ABC123def456",
        receiptDescription: "Subscription activation payment",
        receiptUrl: "https://yourapp.com/receipts/abc123",
      },
    }),
  },
);

const submittedOrder = await submitResponse.json();
console.log("Order state:", submittedOrder.state);
```

The `externalPayment` object accepts:

| Field                | Required | Description                                                |
| -------------------- | -------- | ---------------------------------------------------------- |
| `reference`          | Yes      | The payment reference or transaction ID from your provider |
| `receiptDescription` | No       | A human-readable description of the payment                |
| `receiptUrl`         | No       | A URL to the payment receipt or confirmation page          |

<Note>
  When using external payments, you are responsible for collecting the correct
  amount and handling refunds through your payment provider.
</Note>

See [Submit Order](/api-reference/orders/submit-order)

### Option B: Hosted Payment Page

If you prefer a managed payment flow, create a payment session with `hosted: true` to get a checkout URL. Redirect the customer to the provider-hosted payment page.

```javascript theme={null}
const sessionResponse = await fetch(
  "https://connect.telnesstech.com/api/v2/payment-sessions",
  {
    method: "POST",
    headers: {
      "X-API-Key": process.env.CONNECT_API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      orderId: orderId,
      paymentProvider: "STRIPE",
      hosted: true,
      returnUrl: "https://yourapp.com/payment/success",
      cancelUrl: "https://yourapp.com/payment/cancel",
    }),
  },
);

const session = await sessionResponse.json();

// Redirect the customer to the hosted payment page
window.location.href = session.provider.checkoutUrl;
```

After the customer completes payment, they are redirected to your `returnUrl`. Poll the payment session to confirm the status before submitting the order.

```javascript theme={null}
const statusResponse = await fetch(
  `https://connect.telnesstech.com/api/v2/payment-sessions/${session.paymentSessionId}`,
  {
    headers: {
      "X-API-Key": process.env.CONNECT_API_KEY,
    },
  },
);

const sessionStatus = await statusResponse.json();

if (sessionStatus.status === "COMPLETED") {
  // Submit the order with the payment session reference
  await fetch(
    `https://connect.telnesstech.com/api/v2/orders/${orderId}/submit`,
    {
      method: "POST",
      headers: {
        "X-API-Key": process.env.CONNECT_API_KEY,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        paymentSessionId: session.paymentSessionId,
      }),
    },
  );
}
```

See [Create Payment Session](/api-reference/payment-sessions/create-payment-session) and [Get Payment Session](/api-reference/payment-sessions/get-payment-session)

### Option C: Embedded Payment Widget

Create a payment session with `hosted: false` (or omit the field) to get provider credentials for rendering a payment form directly in your UI.

```javascript theme={null}
const sessionResponse = await fetch(
  "https://connect.telnesstech.com/api/v2/payment-sessions",
  {
    method: "POST",
    headers: {
      "X-API-Key": process.env.CONNECT_API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      orderId: orderId,
      paymentProvider: "STRIPE",
    }),
  },
);

const session = await sessionResponse.json();

// Use the provider credentials to render a payment widget
const { clientSecret, publishableKey } = session.provider;
```

Use the returned credentials with the provider's client SDK. For example, with Stripe Elements:

```javascript theme={null}
const stripe = Stripe(publishableKey);
const elements = stripe.elements({ clientSecret });

const paymentElement = elements.create("payment");
paymentElement.mount("#payment-element");

// When the customer submits the form:
const { error } = await stripe.confirmPayment({
  elements,
  confirmParams: {
    return_url: "https://yourapp.com/payment/success",
  },
});
```

After the payment completes, submit the order with the payment session ID:

```javascript theme={null}
await fetch(
  `https://connect.telnesstech.com/api/v2/orders/${orderId}/submit`,
  {
    method: "POST",
    headers: {
      "X-API-Key": process.env.CONNECT_API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      paymentSessionId: session.paymentSessionId,
    }),
  },
);
```

See [Create Payment Session](/api-reference/payment-sessions/create-payment-session)

## Zero-Total Orders with Payment Profile

For orders with a zero total that still require a stored payment method (e.g., trial subscriptions), submit with a payment profile session ID instead.

```javascript theme={null}
const submitResponse = await fetch(
  `https://connect.telnesstech.com/api/v2/orders/${orderId}/submit`,
  {
    method: "POST",
    headers: {
      "X-API-Key": process.env.CONNECT_API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      paymentProfileSessionId: "profile-session-id",
    }),
  },
);
```

## Order States

| State              | Description                                     |
| ------------------ | ----------------------------------------------- |
| `PENDING`          | Order is in cart state, can be modified         |
| `PENDING_PAYMENT`  | Order is locked and awaiting payment completion |
| `SUBMITTED`        | Order has been submitted for processing         |
| `PENDING_APPROVAL` | Order is pending approval                       |
| `PROCESSING`       | Order is being fulfilled                        |
| `COMPLETED`        | Order has been successfully fulfilled           |
| `CANCELLED`        | Order was cancelled before completion           |
| `EXPIRED`          | Order expired due to inactivity                 |
| `FAILED`           | Order fulfillment failed                        |

## Payment Session Statuses

| Status            | Description                                                  |
| ----------------- | ------------------------------------------------------------ |
| `PENDING`         | Session created, awaiting customer payment                   |
| `REQUIRES_ACTION` | Additional action needed from the customer (e.g., 3D Secure) |
| `COMPLETED`       | Payment successfully collected                               |
| `FAILED`          | Payment failed                                               |

## Requirements Reference

When you retrieve an order after calculating the price, the `requirements` object tells you what is needed before submission.

| Requirement              | Values                                 | Description                               |
| ------------------------ | -------------------------------------- | ----------------------------------------- |
| `requiresPayment`        | `NOT_REQUIRED`, `OPTIONAL`, `REQUIRED` | Whether payment must be collected         |
| `requiresPaymentProfile` | `NOT_REQUIRED`, `OPTIONAL`, `REQUIRED` | Whether a stored payment method is needed |
| `requiresSigning`        | `NOT_REQUIRED`, `OPTIONAL`, `REQUIRED` | Whether a digital signature is needed     |

## Next Steps

<CardGroup cols={2}>
  <Card title="Orders" icon="cart-shopping" href="/api-reference/orders">
    Full order management API reference
  </Card>

  <Card title="Payment Sessions" icon="money-check-dollar" href="/api-reference/payment-sessions">
    Managed payment session creation and management
  </Card>

  <Card title="Payment Profiles" icon="wallet" href="/api-reference/payment-profiles">
    Stored payment methods for recurring billing
  </Card>

  <Card title="Webhooks" icon="rss" href="/api-reference/webhooks">
    Set up notifications for order and payment events
  </Card>
</CardGroup>
