> ## Documentation Index
> Fetch the complete documentation index at: https://help.the-meridian.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Server client

`createMeridianServerClient` is the SDK without React: the same reads and the same billing writes, for resource routes, Shopify extensions, background jobs and anything else that runs outside a component.

```ts theme={null}
import { createMeridianServerClient } from "@the-meridian/sdk/server"

const client = createMeridianServerClient(shopToken)
const { enabled, limit } = await client.checkFeature("advanced_reports")
await client.track({ eventKey: "api_calls", quantity: 5 })
```

It takes a shop token, either bare or as `{ shopToken, baseUrl }` to override the API root. If you have a shop domain rather than a token, [`createMeridianApp`](/sdk-app) gets you there in one call with `serverClientForShop(shop)`.

## Methods

| Method | Returns |
| - | - |
| `getMe()` | The customer, entitlements and plans in one read |
| `getCustomer()` | The shop's CRM record, including its custom field values |
| `getEntitlements()` | The resolved entitlements snapshot |
| `getGates()` | Entitlements plus gating helpers |
| `checkFeature(featureKey)` | `{ enabled, limit? }` for one feature |
| `getUsage(key)` | This period's usage for one event, or a [view](/usage-views) by its key |
| `getView(viewKey)` | A view's full reading, including the window it was measured over |
| `track(input)` | Records a metered event. Pass a `timestamp` and an `idempotencyKey` to record one that happened earlier. See [Dated events](/events#dated-events) |
| `trackMany(events)` | Records up to 50 metered events in one request and one transaction, each dated or not. See [Sending events in batch](/events#sending-events-in-batch) |
| `subscribe(planId, returnUrl, billingInterval?)` | Starts a subscription |
| `cancelSubscription()` | Cancels the shop's subscription |
| `updateUsageCap(input)` | Raises the merchant-approved spending cap |
| `refreshShopToken()` | Rotates the token and returns the new one |

## Gates

`getGates()` is the server-side equivalent of the provider's gates, resolved once and then read synchronously:

```ts theme={null}
const gates = await client.getGates()

gates.planId          // string | null
gates.planName        // string | null
gates.can("advanced_reports")     // boolean
gates.limitOf("team_seats")       // number | undefined
gates.usage("api_calls")          // EntitlementEvent | undefined, event or view key
gates.view("gmv")                 // EntitlementView | undefined, with its window
```

`getGates` is the one method that **does not** throw when Meridian is unreachable: `entitlements` comes back `null` and every gate reads as ungated, so it suits a request path. See [fail open or fail closed](/features#fail-open-or-fail-closed).

`checkFeature` costs one call per feature, so prefer `getGates` when you are checking more than one.

## Errors

Every other method throws `MeridianApiError` on failure, unlike `createMeridianApp`, which degrades.

```ts theme={null}
import { MeridianApiError, isShopTokenExpiredError } from "@the-meridian/sdk/server"

try {
  await client.track({ eventKey: "api_calls" })
} catch (err) {
  if (isShopTokenExpiredError(err)) {
    const { shopToken } = await client.refreshShopToken()
    // retry with a client built from the new token
  }
  throw err
}
```

There is no automatic token refresh on the server client; only the provider does that. If a job holds a token for longer than an hour, refresh it when a call reports it expired, or mint a fresh one with `mintShopToken`. See [Errors](/sdk-errors).

`isShopTokenRevokedError(err)` (`401 SHOP_TOKEN_REVOKED`) means the shop uninstalled the app. `refreshShopToken()` only helps once it has reinstalled, and only within the revoked token's original hour, so mint a fresh token instead.

## Subscribing from the server

`subscribe` takes the `returnUrl` as a required argument here, with the same shop-admin constraint as the [pricing page](/plans#the-returnurl). The SDK validates it before the call either way.

Server-side subscribing is what the provider's `onSubscribe` override routes to. Reach for it when you want a billing action enforced on your own server.

## Pure helpers

`featureEnabled`, `featureLimit` and `eventUsage` are exported from the server entry too, so a snapshot you already hold can be gated without a client:

```ts theme={null}
import { featureEnabled } from "@the-meridian/sdk/server"

featureEnabled(entitlements, "advanced_reports")
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.