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

# TypeScript SDK

The Supertab Connect TypeScript SDK allows publishers to implement Really Simple Licensing (RSL) and the
Crawler Authentication Protocol (CAP) directly in their applications or at the CDN edge.

The SDK manages license token verification, bot detection, and licensing event recording with minimal configuration.

## Overview

Supertab Connect helps you manage how bots and automated systems access your content. It uses license tokens (JWTs) to verify that a caller has a valid license to access a specific resource.

### Key Features

* **Edge-Ready**: Optimized for Cloudflare Workers, Fastly Compute, and AWS CloudFront Lambda\@Edge.
* **Flexible Enforcement**: Choose between logging-only, signaling, or strictly blocking unauthorized requests.
* **Plugin Bot Detection**: Built-in logic to identify common AI crawlers and headless browsers, customizable using signals from your WAF provider.
* **Analytics**: Automatically records license usage and verification failures.

## Installation

Install the SDK using your preferred package manager:

```bash theme={null}
npm install @getsupertab/supertab-connect-sdk
```

## Quickstart: Fastly Compute

The fastest way to get started is using one of the built-in CDN handlers.
For Fastly Compute, read your API key from the Secret Store and pass your origin backend name.

```typescript theme={null}
/// <reference types="@fastly/js-compute" />
import { SupertabConnect } from "@getsupertab/supertab-connect-sdk";
import { SecretStore } from "fastly:secret-store";

const secrets = new SecretStore("supertab_config");
const merchantApiKey = await secrets.get("MERCHANT_API_KEY");

addEventListener("fetch", (event) => {
  event.respondWith(
    SupertabConnect.fastlyHandleRequests(
      event.request,
      merchantApiKey,
      "origin_backend_name",
      {
        enableRSL: true, // Optionally host /license.xml
        merchantSystemUrn: "your_website_urn",
      }
    )
  );
});
```

## Initializing the Client

If you aren't using a convenience handler, you can initialize the `SupertabConnect` client manually. The client follows a singleton pattern.

```typescript theme={null}
import { SupertabConnect, EnforcementMode } from "@getsupertab/supertab-connect-sdk";

const supertab = new SupertabConnect({
  apiKey: "stc_live_...", // API Keys should be read from environment variables or secrets management
  enforcement: EnforcementMode.SOFT, // Defaults to SOFT if not provided
  debug: false // When enabled debug mode prints more logging information about token handling
});
```

### Configuration Options

| Property      | Type              | Description                                                                                  |
| :------------ | :---------------- | :------------------------------------------------------------------------------------------- |
| `apiKey`      | `string`          | **Required.** Your Supertab Merchant API Key.                                                |
| `enforcement` | `EnforcementMode` | Controls how unauthorized requests are handled. See [Enforcement Modes](#enforcement-modes). |
| `botDetector` | `BotDetector`     | A custom function to identify bots. Defaults to `defaultBotDetector`.                        |
| `debug`       | `boolean`         | Enables verbose logging to the console.                                                      |

## Common Workflows

### Edge Integration (CDN Handlers)

The SDK provides static methods that handle the entire request/response lifecycle for specific platforms. These handlers:

1. Extract tokens from the `Authorization: License <token>` header.
2. Verify the token against the Supertab JWKS.
3. Record an analytics event.
4. If no token is present, run bot detection and apply the enforcement mode.

#### Fastly Compute

```typescript theme={null}
import { SupertabConnect } from "@getsupertab/supertab-connect-sdk";

addEventListener("fetch", (event) => {
  event.respondWith(
    SupertabConnect.fastlyHandleRequests(
      event.request,
      "YOUR_MERCHANT_API_KEY",
      "your-origin-backend-name",
      {
        enableRSL: true, // Automatically hosts /license.xml
        merchantSystemUrn: "urn:stc:merchant:system:..."
      }
    )
  );
});
```

#### Cloudflare Workers

Always pass `ctx` — the SDK uses it to record analytics in the background without blocking the response. The API key is read from the `env` object (`MERCHANT_API_KEY` secret).

```typescript theme={null}
import { SupertabConnect, Env } from "@getsupertab/supertab-connect-sdk";

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    return SupertabConnect.cloudflareHandleRequests(request, env, ctx);
  },
};
```

#### AWS CloudFront (Lambda\@Edge)

Note: This handler is designed for **Origin Request** events.

```typescript theme={null}
import { SupertabConnect, CloudFrontRequestEvent } from "@getsupertab/supertab-connect-sdk";

export async function handler(event: CloudFrontRequestEvent) {
  return SupertabConnect.cloudfrontHandleRequests(event, {
    apiKey: "YOUR_MERCHANT_API_KEY"
  });
}
```

### Manual Verification

Use `verifyAndRecord` when you need granular control or are running in a standard Node.js/Bun/Deno backend.

```typescript theme={null}
const result = await supertab.verifyAndRecord({
  token: "...", // Extracted from header or other source
  resourceUrl: "https://example.com/premium-article",
  userAgent: request.headers.get("User-Agent"),
  ctx: ctx // Optional: Pass context to use waitUntil for non-blocking analytics
});

if (result.valid) {
  // Allow access to content
} else {
  // Handle invalid license (e.g., return 401)
  console.error(result.error);
}
```

### Obtaining a License Token

If you are building a client that needs to access protected resources, use `obtainLicenseToken` to get a license token.
The SDK handles retrieval of the licensing details and automatically refreshes the token when needed.
Whenever a usage type is specified and a token is not required
(the matched content rule permits the intended usage without a license), the method returns no token (`undefined`).
You should call `obtainLicenseToken` before every request, the SDK will handle caching and expiration.

```typescript theme={null}
const token = await SupertabConnect.obtainLicenseToken({
  clientId: "your_client_id",
  clientSecret: "your_client_secret",
  resourceUrl: "https://example.com/protected-resource"
});

if (token) {
  const headers = { Authorization: `License ${token}` };
  // Use these headers on the resource request.
}
```

When you know the intended content usage type, pass `usage`. If there is a matching `<content>` rule with the license
explicitly permitting that usage without requiring a license token, the SDK returns `undefined`.
This allows you to treat `undefined` as "no token needed" rather than an error.

```typescript theme={null}
import { SupertabConnect, UsageType } from "@getsupertab/supertab-connect-sdk";

const token = await SupertabConnect.obtainLicenseToken({
  clientId: "your_client_id",
  clientSecret: "your_client_secret",
  resourceUrl: "https://example.com/public-resource",
  usage: UsageType.SEARCH
});

if (token) {
  const headers = { Authorization: `License ${token}` };
  // Use these headers on the resource request.
}
```

## Important Types

### `EnforcementMode`

Enforcement modes determine what happens when a bot is detected without a valid license token.

* `STRICT`: Blocks the request immediately with a `401 Unauthorized` (missing or invalid token) or `403 Forbidden` (token valid but wrong audience).
* `SOFT` (Default): Allows the request but attaches RSL headers (`Link`, `X-RSL-Status`) to signal that a license is required.
* `DISABLED`: No enforcement, signaling, or analytics recording. Requests are allowed without licensing intervention.

Non-bot requests are always allowed regardless of mode. Invalid tokens are always blocked except in `DISABLED` mode.

### Handler Result

When calling `handleRequest` manually, you receive a `HandlerResult`:

* `{ action: "allow", headers?: ... }`: The request should proceed.
* `{ action: "block", status: number, body: string, headers: ... }`: The request should be rejected with the provided response.

## Error Handling

The SDK provides clear error reasons when a license is invalid. Common reasons include:

* `missing_license_token`: No license was provided in the headers.
* `license_token_expired`: The JWT `exp` claim is in the past.
* `invalid_license_audience`: The token is valid but not for the requested URL.
* `license_signature_verification_failed`: The token was tampered with or signed by an untrusted issuer.

## Tips and Pitfalls

* **Performance**: When using Cloudflare Workers, always pass the `ExecutionContext` (`ctx`) to the handlers. This allows the SDK to record analytics in the background without delaying the response to the user.
* **Singleton Pattern**: The `SupertabConnect` constructor returns the existing instance if one was already created with the same API key. Use `SupertabConnect.resetInstance()` if you need to change configurations dynamically.
* **Custom Bot Detection**: If you have specific traffic patterns (e.g., a known internal scraper), provide a custom `botDetector` function to prevent false positives.
* **No token required**: `obtainLicenseToken` returning `undefined` is valid when `usage` matches content without server URL that permits that usage. Treat it as "no token needed", not as an authentication failure.
* **Cache behavior**: `obtainLicenseToken` caches `license.xml` by origin for 15 minutes and license tokens by client, token server, and matched URL pattern. Process restarts clear that cache.

```typescript theme={null}
import { defaultBotDetector } from "@getsupertab/supertab-connect-sdk";

const customDetector = (request: Request) => {
  const ua = request.headers.get("User-Agent");
  return ua?.includes("MyInternalBot") ? false : defaultBotDetector(request);
};
```

## API Reference

### Static Methods

* `cloudflareHandleRequests(request, env, ctx, options?)`: Cloudflare-specific handler.
* `fastlyHandleRequests(request, apiKey, backend, options?)`: Fastly-specific handler.
* `cloudfrontHandleRequests(event, options)`: CloudFront-specific handler.
* `verify(options)`: Pure token verification (no analytics).
* `obtainLicenseToken(options)`: Client-side token acquisition.

### Instance Methods

* `handleRequest(request, ctx?)`: The core logic used by CDN handlers.
* `verifyAndRecord(options)`: Verifies a token and records the result to Supertab analytics.
