# User & Subscriptions

In **Limio Self-Service**, authenticated users can view and manage their subscriptions through a self-service portal. The SDK provides hooks that retrieve real-time data about the current user, their subscriptions, addresses, and payment methods.

These hooks power pages like:

* Account overview and profile display
* Subscription management (upgrade, downgrade, cancel)
* Contact details and address management

## `useUser()`

Returns the authenticated user's identity, login status, and token.

```typescript
import { useUser } from "@limio/sdk"

const user = useUser()
```

**Returns:**

| Field         | Type                          | Description                                                                     |
| ------------- | ----------------------------- | ------------------------------------------------------------------------------- |
| `attributes`  | `object`                      | User profile attributes from the identity provider (email, name, custom claims) |
| `loginStatus` | `"logged-in" \| "logged-out"` | Current authentication state                                                    |
| `loaded`      | `boolean`                     | Always `true` once the hook resolves                                            |
| `token`       | `string`                      | The current session access token                                                |

**Example — display the logged-in user's email:**

```tsx
import React from "react"
import { useUser } from "@limio/sdk"

const AccountHeader = () => {
  const { attributes, loginStatus } = useUser()

  if (loginStatus !== "logged-in") {
    return <p>Please sign in to view your account.</p>
  }

  return (
    <header>
      <p>Signed in as {attributes.email}</p>
    </header>
  )
}
```

<details>

<summary>Example <code>user</code> object</summary>

```javascript
{
  attributes: {
    sub: "d183e0ec-8baf-4320-b847-c78fad0b1df8",
    email: "jane@leemeeo.com",
    email_verified: true,
    given_name: "Jane",
    family_name: "Smith",
    "cognito:username": "jane.smith",
    crm_id: "001Sv00000M0XsKIAV",  // custom claim from identity federation
    aud: "3kde1g4qurqbdmf7p81n6568m0",
    iss: "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_ExamplePool",
    token_use: "id"
  },
  loginStatus: "logged-in",
  loaded: true
}
```

</details>

{% hint style="info" %}
Custom claims (like `crm_id` above) come from your federated identity provider. See [Authentication Integrations](https://docs.limio.com/product/authentication) for setup.
{% endhint %}

***

## `getFederatedSignIn()`

Triggers the federated sign-in flow, redirecting the user to the configured identity provider. Once authenticated, the user is redirected back to the originating page with an active session.

This is useful in components that need to programmatically initiate login — for example, gating an action behind authentication or building a custom sign-in button.

```typescript
import { getFederatedSignIn } from "@limio/sdk"

await getFederatedSignIn()
```

**Returns:** `Promise<void>` — triggers a full-page redirect; does not resolve in the current page context.

**Example — require sign-in before a protected action:**

```tsx
import React from "react"
import { useUser, getFederatedSignIn } from "@limio/sdk"

const ProtectedAction = () => {
  const { loginStatus } = useUser()

  const handleClick = async () => {
    if (loginStatus !== "logged-in") {
      await getFederatedSignIn()
      return
    }
    // user is authenticated — proceed
  }

  return <button onClick={handleClick}>Continue</button>
}
```

### Session expiry

Once signed in, the session token's expiry is available via `useUser()`. The `attributes` object includes standard JWT claims `iat` (issued at) and `exp` (expiry), both as Unix timestamps in seconds. Use these to determine session length or show time-remaining UI:

```tsx
import { useUser } from "@limio/sdk"

const { attributes } = useUser()
const sessionExpiresAt = new Date(attributes.exp * 1000)
const sessionLength = attributes.exp - attributes.iat // seconds
```

{% hint style="info" %}
`getFederatedSignIn` is typically called automatically by the Limio `Authenticator` when a page requires authentication. You only need to call it directly when building custom sign-in flows or gating specific actions behind authentication.
{% endhint %}

***

## `useSubscriptions()`

Returns the list of subscriptions for the authenticated user.

```typescript
import { useSubscriptions } from "@limio/sdk"

const { subscriptions } = useSubscriptions()
```

**Options:**

| Field     | Type                | Description                                                                                             |
| --------- | ------------------- | ------------------------------------------------------------------------------------------------------- |
| `ownerId` | `string` (optional) | Filter subscriptions by owner ID — used in B2B partner portals where one user manages multiple accounts |

**Example — list subscriptions with status:**

```tsx
import React from "react"
import { useSubscriptions } from "@limio/sdk"

const SubscriptionList = () => {
  const { subscriptions } = useSubscriptions()

  return (
    <section>
      <h2>Your Subscriptions</h2>
      {subscriptions.map((sub) => (
        <div key={sub.id}>
          <h3>{sub.data?.offer?.data?.attributes?.display_name__limio || sub.name}</h3>
          <span>{sub.status}</span>
        </div>
      ))}
    </section>
  )
}
```

**Example — B2B partner portal with `ownerId`:**

```tsx
import React from "react"
import { useSubscriptions } from "@limio/sdk"

const PartnerSubscriptions = () => {
  const ownerId = new URLSearchParams(window.location.search).get("ownerId")
  const { subscriptions } = useSubscriptions({ ownerId })

  return (
    <section>
      {subscriptions.map((sub) => (
        <div key={sub.id}>
          <h3>{sub.name}</h3>
          <span>{sub.status}</span>
        </div>
      ))}
    </section>
  )
}
```

<details>

<summary>Example subscription object</summary>

```javascript
{
  name: "Leemeeo Premium Monthly",
  status: "active",
  id: "sub-34cb9ce9a3777a164bb1ad471f20a83b",
  record_type: "subscription",
  owner: "id-hfmd3qJIYU8XZZo-5JI2UOkdacXd0JXBYlptgRGcLMM",
  customer: "cus-VsmB6KhU_PTTTGzgvY51Vk2dy5Hf6dLnIX4NitMaK4I",
  service: "limio",
  reference: "1KPEEEJ8RNF8",
  created: "2025-06-09T12:44:38.771Z",
  mode: "production",
  data: {
    offer: {
      data: {
        attributes: {
          display_name__limio: "Leemeeo Premium Monthly",
          display_price__limio: "$29/mo",
          autoRenew__limio: true,
          price__limio: [
            {
              name: "charge_1",
              type: "recurring",
              value: "29.00",
              currencyCode: "USD",
              repeat_interval: 1,
              repeat_interval_type: "months"
            }
          ]
        },
        products: [
          {
            name: "Leemeeo Premium",
            path: "/products/Leemeeo Premium",
            attributes: {
              product_code__limio: "LEEMEEO-PREM-001"
            }
          }
        ]
      }
    },
    price: {
      summary: { headline: "$29/mo" },
      currency: "USD",
      amount: 29
    },
    startDate: "2025-06-09T12:44:38.771Z",
    termEndDate: "2026-06-09T12:44:38.771Z"
  },
  offers: [
    {
      name: "Leemeeo Premium Monthly",
      quantity: 1,
      data: {
        offer: {
          data: {
            attributes: {
              display_name__limio: "Leemeeo Premium Monthly",
              autoRenew__limio: true
            }
          }
        }
      }
    }
  ],
  schedule: [
    {
      data: {
        date: "2025-06-09T12:44:38.771Z",
        schedule_date: "2025-06-09T12:44:38.771Z",
        description: "Leemeeo Premium Monthly",
        amount: "29.00",
        currency: "USD",
        type: "payment"
      },
      status: "processed",
      id: "schedule-46f188d94a8b0b1ef39ee1afbbebfb99"
    },
    {
      data: {
        date: "2025-07-09T12:44:38.771Z",
        schedule_date: "2025-07-09T12:44:38.771Z",
        description: "Leemeeo Premium Monthly",
        amount: "29.00",
        currency: "USD",
        type: "payment"
      },
      status: "pending",
      id: "schedule-f0899162c4c161a0f8c2535dd1526334"
    }
  ]
}
```

</details>

***

## `claimSubscriptionOwnership()`

Transfers ownership of an anonymously-created subscription to the currently authenticated user. This is used when a subscriber completes a purchase without an account (guest checkout) and later signs in — calling this function links the existing subscription to their authenticated identity.

```typescript
import { claimSubscriptionOwnership } from "@limio/sdk"

const result = await claimSubscriptionOwnership(subscriptionName)
```

**Parameters:**

| Param              | Type     | Description                                                                                             |
| ------------------ | -------- | ------------------------------------------------------------------------------------------------------- |
| `subscriptionName` | `string` | The subscription reference (e.g. `"A-S00012345"`). Max 64 alphanumeric chars, hyphens, and underscores. |

**Returns:** `Promise<{ id: string, name: string }>`

| Field  | Type     | Description                          |
| ------ | -------- | ------------------------------------ |
| `id`   | `string` | The subscription ID                  |
| `name` | `string` | The subscription reference passed in |

**Behaviour:**

* The authenticated user's email must match the email on the subscription's customer record (case-insensitive).
* Only subscriptions owned by anonymous users (guest checkout) can be claimed. Subscriptions already owned by another authenticated user cannot be claimed.
* Idempotent — calling it on a subscription the user already owns returns success without side effects.
* On success, all related objects (orders, offers, add-ons, payment methods, addresses, schedules) are transferred to the authenticated user.
* On failure, throws with HTTP 404 regardless of the reason (subscription not found, email mismatch, already claimed by another user).

{% hint style="info" %}
`claimSubscriptionOwnership` requires an authenticated session. The session token is used automatically.
{% endhint %}

**Example — claim a subscription after sign-in:**

```tsx
import React, { useState } from "react"
import { useSubscriptions, claimSubscriptionOwnership } from "@limio/sdk"

const ClaimSubscription = ({ subscriptionName }) => {
  const { subscriptions } = useSubscriptions()
  const [claiming, setClaiming] = useState(false)
  const [error, setError] = useState(null)

  const alreadyOwned = subscriptions.some((sub) => sub.reference === subscriptionName)

  const handleClaim = async () => {
    setClaiming(true)
    setError(null)

    try {
      await claimSubscriptionOwnership(subscriptionName)
    } catch (err) {
      setError("Unable to claim this subscription. Please contact support.")
    } finally {
      setClaiming(false)
    }
  }

  if (alreadyOwned) {
    return <p>This subscription is already linked to your account.</p>
  }

  return (
    <div>
      <p>You have a subscription that isn't linked to your account yet.</p>
      <button onClick={handleClaim} disabled={claiming}>
        {claiming ? "Claiming..." : "Link subscription to my account"}
      </button>
      {error && <p>{error}</p>}
    </div>
  )
}
```

***

## Displaying subscription details

### `getCurrentOffer`

Returns the current active offer from a subscription. Useful for showing the plan name and pricing on subscription management pages.

```typescript
import { getCurrentOffer } from "@limio/sdk/offers"

const offer = getCurrentOffer(subscription)
const displayName = offer?.data?.attributes?.display_name__limio
```

### Reading schedule data

Each subscription includes a `schedule` array with past and future payment entries. To find the next upcoming payment, filter by date and status:

```typescript
import { formatDate, formatCurrency, getCookie, LimioAppSettings } from "@limio/sdk"

const locale = getCookie("limio-country")
const dateFormat = LimioAppSettings?.getDateFormat()

// Find the next pending schedule entry
function getNextSchedule(schedules = []) {
  const now = new Date().toISOString()
  const sorted = [...schedules].sort(
    (a, b) => new Date(a.data.date).getTime() - new Date(b.data.date).getTime()
  )
  return sorted.find(
    (s) => s.data.date > now && ["active", "pending", "pending-external"].includes(s.status)
  )
}

const nextSchedule = getNextSchedule(subscription.schedule)
const nextDate = formatDate(nextSchedule?.data?.date, dateFormat)
const nextAmount = formatCurrency(nextSchedule?.data?.amount, nextSchedule?.data?.currency, locale)
```

{% hint style="info" %}
`formatDate` and `formatCurrency` are exported from `@limio/sdk` and use the app's configured locale and date format.
{% endhint %}

### `useSubInfo`

A convenience hook that extracts key metadata from a subscription object.

```typescript
import { useSubInfo } from "@limio/sdk/subscription"

const { status, isGift, quantity, hasLapsed, hasPendingChange } = useSubInfo(subscription)
```

**Returns:**

| Field              | Type                   | Description                                 |
| ------------------ | ---------------------- | ------------------------------------------- |
| `status`           | `string`               | Current subscription status                 |
| `isGift`           | `boolean`              | Whether the subscription is a gift          |
| `quantity`         | `number`               | Quantity on the subscription                |
| `hasLapsed`        | `boolean \| undefined` | Whether the subscription has lapsed         |
| `hasPendingChange` | `boolean`              | Whether there is a scheduled change pending |

### `useSchedule`

A convenience hook that returns formatted schedule data for a subscription. Handles date formatting, currency formatting, and renewal price calculation.

```typescript
import { useSchedule } from "@limio/sdk/subscription"

const schedule = useSchedule(subscription)
// schedule = {
//   nextSchedule,          // The next schedule entry object
//   termStartDate,         // e.g. "9 Jun 2025"
//   termEndDate,           // e.g. "9 Jun 2026"
//   nextPaymentAmount,     // e.g. "$29.00"
//   renewalPrice           // e.g. "$29.00"
// }
```

### Other subscription helpers

These helpers are available from `@limio/sdk/subscription` and `@limio/sdk/offers`:

| Helper                                     | Import                    | Description                                                                         |
| ------------------------------------------ | ------------------------- | ----------------------------------------------------------------------------------- |
| `getPeriodForOffer(offer)`                 | `@limio/sdk/offers`       | Returns the billing period string (e.g. `"1 month"`) or `"N/A"` for one-off charges |
| `checkCurrentSchedule(schedules)`          | `@limio/sdk/subscription` | Returns the next applicable schedule from an array                                  |
| `getRenewalDateForUserSubscription(sub)`   | `@limio/sdk/subscription` | Returns the formatted renewal date, or `"N/A"` if cancelled                         |
| `getPriceForUserSubscription(sub)`         | `@limio/sdk/subscription` | Returns `{ value, currencyCode }` for the next payment                              |
| `getPriceFromSchedule(schedule, country?)` | `@limio/sdk/subscription` | Extracts `{ value, currencyCode }` from a schedule item                             |

***

## Addresses and payment methods

### `useLimioUserSubscriptionAddresses`

Fetch billing and delivery addresses for a subscription. Returns an array of address objects with a `revalidate` function to refresh the data.

```typescript
import { useLimioUserSubscriptionAddresses } from "@limio/internal-checkout-sdk"

const { addresses, revalidate } = useLimioUserSubscriptionAddresses(subscriptionId)
```

### `getCurrentAddress`

Extract the active billing or delivery address from the addresses array.

```typescript
import { getCurrentAddress } from "@limio/sdk/address"

const { data: billingAddress } = getCurrentAddress("billing", addresses)
const { data: shippingAddress } = getCurrentAddress("delivery", addresses)
```

**Parameters:**

| Param       | Type                      | Description                                                  |
| ----------- | ------------------------- | ------------------------------------------------------------ |
| `type`      | `"billing" \| "delivery"` | The address type to retrieve                                 |
| `addresses` | `LimioAddressObject[]`    | The addresses array from `useLimioUserSubscriptionAddresses` |

**Example — display billing and delivery addresses:**

```tsx
import React from "react"
import { useSubscriptions } from "@limio/sdk"
import { useLimioUserSubscriptionAddresses } from "@limio/internal-checkout-sdk"
import { getCurrentAddress } from "@limio/sdk/address"

const ContactDetails = () => {
  const { subscriptions } = useSubscriptions()
  const { addresses } = useLimioUserSubscriptionAddresses(subscriptions[0]?.id)

  const { data: billingAddress } = getCurrentAddress("billing", addresses)
  const { data: shippingAddress } = getCurrentAddress("delivery", addresses)

  return (
    <section>
      <div>
        <h3>Billing Address</h3>
        <p>{billingAddress.firstName} {billingAddress.lastName}</p>
        <p>{billingAddress.address1}</p>
        <p>{billingAddress.city}, {billingAddress.state} {billingAddress.zipCode}</p>
        <p>{billingAddress.country}</p>
      </div>
      {Object.keys(shippingAddress).length > 0 && (
        <div>
          <h3>Delivery Address</h3>
          <p>{shippingAddress.firstName} {shippingAddress.lastName}</p>
          <p>{shippingAddress.address1}</p>
          <p>{shippingAddress.city}, {shippingAddress.state} {shippingAddress.zipCode}</p>
          <p>{shippingAddress.country}</p>
        </div>
      )}
    </section>
  )
}
```

<details>

<summary>Example address object</summary>

```javascript
{
  firstName: "Jane",
  lastName: "Smith",
  country: "US",
  city: "San Francisco",
  state: "CA",
  address1: "123 Main St",
  zipCode: "94102"
}
```

</details>

### `useLimioUserSubscriptionPaymentMethods`

Fetch stored payment methods for a subscription. Returns payment method details and a `revalidate` function.

```typescript
import { useLimioUserSubscriptionPaymentMethods } from "@limio/internal-checkout-sdk"

const { payment_methods, revalidate } = useLimioUserSubscriptionPaymentMethods(subscriptionId)
```

The `payment_methods` array contains objects with card type, last four digits, and expiry information from the billing provider.

***

## See also

* [Billing & Account Information](/developers/limio-sdk/billing-account.md) — Zuora-specific hooks for account details, invoices, and billing statements
* [Subscription Update Checkout](/developers/limio-sdk/subscription-update-checkout.md) — How to build plan change flows
* [Basket (Cart)](/developers/limio-sdk/basket.md) — Basket management for new purchases


---

# 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.limio.com/developers/limio-sdk/user.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.
