Skip to content
EntitlerDocs

TypeScript SDK

Use Entitler from your TypeScript and JavaScript servers and web apps.

The TypeScript SDK, @entitlerhq/entitler, has two clients: EntitlerServer for your servers, with a secret key, and EntitlerClient for browsers, with a customer token. Its source is at github.com/entitlerhq/entitler-typescript.

Install

npm install @entitlerhq/entitler

On your server

import { EntitlerServer } from '@entitlerhq/entitler'

const entitler = new EntitlerServer({ key: process.env.ENTITLER_KEY ?? '' })
const ada = entitler.customer('ada')

if (await ada.isEntitled('priority_support', { default: false })) {
  openTicket()
}

const check = await ada.check('ai_credits')
const entitlements = await ada.entitlements()

await ada.recordUsage('ai_credits', 3, { idempotencyKey: 'run-42' })

const { token } = await ada.token({ scopes: ['entitlements:read', 'usage:write'] })
  • check(feature) answers the customer's entitlement to one feature: entitled, value, meter and upgrades. A meter's remaining is a number, or 'unlimited'.
  • isEntitled(feature, { default }) answers entitled, or default when Entitler can't be reached.
  • entitlements() answers every entitlement, with has(feature) and get(feature).
  • recordUsage(feature, amount, { idempotencyKey }) reports usage. It answers the same fields as check, with the meter after the report, plus outcome, refusal, amount, meterChange and overBy; see Usage and meters.
  • withHold(feature, amount, work, { idempotencyKey }) holds, runs your work and settles what it used; see Meter usage with holds.
  • token({ scopes }) mints a customer token for your app.

In the browser

import { EntitlerClient } from '@entitlerhq/entitler'

const entitler = new EntitlerClient({
  token: async ({ signal }) => {
    const response = await fetch('/api/entitler-token', { method: 'POST', signal, credentials: 'include' })
    return (await response.json()).token
  },
})

const check = await entitler.me.check('priority_support')

me is the customer the token was minted for. The client calls token when it has none, and again when Entitler refuses the one it has.

Errors

Every error the SDK throws extends EntitlerError. A refusal from the API is an ApiError, with status, code, reason, parameters, requestId and retryAfter; ConnectionError and TimeoutError mean Entitler couldn't be reached. retryAfter is in milliseconds. See Errors.

Here a report for a customer who isn't registered yet registers them, then sends the same report again, with the same idempotency key.

import { ApiError } from '@entitlerhq/entitler'

const report = () => ada.recordUsage('ai_credits', 3, { idempotencyKey: 'run-42' })

try {
  await report()
} catch (error) {
  if (error instanceof ApiError && error.reason === 'CUSTOMER_NOT_FOUND') {
    await registerAda()
    await report()
  } else {
    throw error
  }
}

The SDK retries what is safe to retry on its own; see Limits and retries.

Edit this page on GitHub