> For the complete documentation index, see [llms.txt](https://developer.firmhouse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.firmhouse.com/sdks/firmhouse-sdk/getting-started.md).

# Getting Started

You can install the package using your favorite package manager.

```bash
npm install @firmhouse/firmhouse-sdk
# or
yarn add @firmhouse/firmhouse-sdk
```

To get started, you need to create a new instance of the `FirmhouseClient` and provide it with an API token.

```typescript
import { FirmhouseClient } from '@firmhouse/firmhouse-sdk';

const client = new FirmhouseClient({
  apiToken: "<your-api-token>"
});
```

You can use both Storefront and Write access tokens to interact with the Firmhouse API. Depending on the access type, you can perform different operations. If you try to perform an operation that is not allowed by the access type, you will receive an error.

## Storefront Access

This access type is used for Storefront operations such as fetching products, creating carts, adding products to carts etc.

```typescript
import { FirmhouseClient } from '@firmhouse/firmhouse-sdk';

const client = new FirmhouseClient({
 apiToken: "<storefront-access-token>",
});

const { results } = await client.products.fetchAll();
const cart = await client.carts.create();
const { orderedProduct, subscription } = await client.carts.addProduct(cart.token, { productId: results[0].id, quantity: 1 });
```

### Available Resources

* `client.carts`: [CartsResource](/sdks/firmhouse-sdk/reference/resources/carts.md)
* `client.products`: [ProductsResource](/sdks/firmhouse-sdk/reference/resources/products.md)
* `client.plans`: [PlansResource](/sdks/firmhouse-sdk/reference/resources/plans.md)
* `client.selfServiceCenterToken`: [SelfServiceCenterTokenResource](/sdks/firmhouse-sdk/reference/resources/self-service-center-token.md)

## Write Access

This access type has access to all resources and operations available in the Firmhouse API.

```typescript
import { FirmhouseClient, Access, InvoiceStatusEnum } from '@firmhouse/firmhouse-sdk';

const writeAccessClient = new FirmhouseClient({
 apiToken: "<write-access-token>",
 accessType: Access.write
});

const subscription = await writeAccessClient.subscriptions.get("subscription-token");
const invoices = await writeAccessClient.invoices.fetchAll({ statuses: [InvoiceStatusEnum.Pending, InvoiceStatusEnum.Paid], subscriptionId: subscription.id }, {
 invoiceLineItems: true,
 payment: true
});
```

{% hint style="danger" %}
You should make sure that your write access token is kept secure and not exposed to the public.
{% endhint %}

### Available Resources

* `writeAccessClient.subscriptions`: [SubscriptionsResource](/sdks/firmhouse-sdk/reference/resources/subscriptions.md)
* `writeAccessClient.invoices`: [InvoicesResource](/sdks/firmhouse-sdk/reference/resources/invoices.md)
* `writeAccessClient.projects`: [ProjectsResource](/sdks/firmhouse-sdk/reference/resources/projects.md)

All resources available with Storefront access are also available with Write access.

## Common Actions

The following examples assume that you have created `client` with a Storefront access token and `writeAccessClient` with a Write access token as shown above.

### Fetch Products and Plans

```typescript
const { results: products } = await client.products.fetchAll();
const { results: plans } = await client.plans.fetchAll();
const product = await client.products.fetchById('123');
```

### Create a Cart and Add a Product

```typescript
const cartToken = await client.carts.createCartToken();

await client.carts.addProduct(cartToken, {
  productId: products[0].id,
  quantity: 2,
});
```

### Apply a Discount Code and Calculate Cart Totals

```typescript
import { calculateCartTotals } from '@firmhouse/firmhouse-sdk/utils';

await client.carts.applyDiscountCode(cartToken, 'WELCOME10');

const cart = await client.carts.get(cartToken, {
  appliedPromotions: {
    includeRelations: {
      promotion: true,
      discountCode: true,
    },
  },
});

const {
  payNowSubtotalCents,
  payNowDiscountCents,
  payNowTotalCents,
  monthlySubtotalCents,
  monthlyDiscountCents,
  monthlyTotalCents,
} = calculateCartTotals(cart);

await client.carts.removeDiscountCode(cartToken);
```

`calculateCartTotals` uses the largest active promotion when multiple promotions are present; promotions do not stack. Discounts are capped at the subtotal, and shipping is not included.

### Fetch Project Details and Invoices

```typescript
const project = await writeAccessClient.projects.getCurrent({
  extraFields: true,
  promotions: true,
  taxRates: true,
});

const invoices = await writeAccessClient.invoices.fetchAll();
```

### Retrieve a Subscription Through Self-Service Login

First, send the subscriber a Self Service Center login link:

```typescript
await client.selfServiceCenterToken.create(
  'subscriber@example.com',
  'https://myapp.com/ssc/token-login',
);
```

When the subscriber follows the link, exchange its login token for the subscription:

```typescript
const selfServiceCenterLoginToken = 'TOKEN_RECEIVED_FROM_THE_LOGIN_LINK';
const subscription = await writeAccessClient.subscriptions.getBySelfServiceCenterLoginToken(
  selfServiceCenterLoginToken,
);
```

### Use Subscription and Extra-Field Helpers

```typescript
import {
  assignSubscriptionUtils,
  mapExtraFieldsByFieldId,
} from '@firmhouse/firmhouse-sdk/utils';

const subscriptionWithUtils = assignSubscriptionUtils(subscription);
const upcomingOrderDate = subscriptionWithUtils.getClosestUpcomingOrderDate();
const upcomingOrderProducts = subscriptionWithUtils.getClosestUpcomingOrderOrderedProducts();

const extraFieldsById = mapExtraFieldsByFieldId(subscription.extraFields);
const extraFieldAnswer = extraFieldsById['EXTRA_FIELD_ID'];
```
