Check our documentation for more information on Supertab Connect.
npm install @getsupertab/supertab-connect-sdk
# or
yarn add @getsupertab/supertab-connect-sdk
Obtain a license token for a resource URL:
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/premium/article",
usage: UsageType.SEARCH,
});
if (token) {
// Send the token as: Authorization: License <token>
} else {
// No token is required for this resource and usage.
}Supertab Connect SDK offers various CDN-attuned implementations of CAP (Crawler Authentication Protocol).
import { SupertabConnect, Env, ExecutionContext } from "@getsupertab/supertab-connect-sdk";
export default {
async fetch(
request: Request,
env: Env,
ctx: ExecutionContext
): Promise<Response> {
return SupertabConnect.cloudflareHandleRequests(request, env, ctx);
},
};/// <reference types="@fastly/js-compute" />
import { SecretStore } from "fastly:secret-store";
import { SupertabConnect } from "@getsupertab/supertab-connect-sdk";
addEventListener("fetch", (event) =>
event.respondWith((async () => {
const configDict = new SecretStore("demo");
const merchantApiKey = await configDict.get("MERCHANT_API_KEY");
return SupertabConnect.fastlyHandleRequests(
event.request,
merchantApiKey,
"origin-backend"
);
})())
);import {
SupertabConnect,
CloudFrontRequestEvent,
CloudFrontRequestResult,
} from "@getsupertab/supertab-connect-sdk";
export async function handler(
event: CloudFrontRequestEvent
): Promise<CloudFrontRequestResult> {
return SupertabConnect.cloudfrontHandleRequests(event, {
apiKey: "stc_live_your_api_key",
});
}Analytics is not supported on CloudFront. The Lambda@Edge handler performs verification and enforcement only — it does not emit analytics events. Relay analytics is available on Cloudflare and Fastly, which emit one event per request (Fastly is the primary edge target for analytics).
If you want to do a manual integration, the SDK also provides low-level methods for token verification and event recording.
import { SupertabConnect } from "@getsupertab/supertab-connect-sdk";
const supertabConnect = new SupertabConnect({
apiKey: "stc_live_your_api_key",
});
// Verify a license token and record an analytics event
const result = await supertabConnect.verifyAndRecord({
token: licenseToken,
resourceUrl: "https://example.com/article",
userAgent: request.headers.get("User-Agent") ?? undefined,
ctx, // pass your platform's execution context for non-blocking event recording
});
if (result.valid) {
// Allow access
} else {
console.log("Denied:", result.error);
}The SDK is configured using the SupertabConnectConfig object:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
apiKey |
string |
Yes | - | Your Supertab merchant API key |
enforcement |
EnforcementMode |
No | OBSERVE |
Enforcement mode: DISABLED, OBSERVE, or ENFORCE |
botDetector |
BotDetector |
No | - | Custom bot detection function (request, ctx?) => boolean |
debug |
boolean |
No | false |
Enable debug logging |
analyticsEnabled |
boolean |
No | false |
Emit one analytics event per request to the Supertab Connect relay (see Analytics) |
analyticsBaseUrl |
string |
No | https://ingest-connect.supertab.co |
Base URL of the analytics ingest service. Independent of setBaseUrl (token/JWKS/verify). Also settable globally via setAnalyticsBaseUrl() |
The SDK can emit one analytics event per request to the Supertab Connect
relay endpoint at {analyticsBaseUrl}/ingest/events, which defaults to the
dedicated ingest service (https://ingest-connect.supertab.co). This is off by
default — enable it by passing analyticsEnabled: true:
const supertabConnect = new SupertabConnect({
apiKey: "stc_live_your_api_key",
analyticsEnabled: true,
});The same flag is available on the Cloudflare and Fastly convenience handlers
(cloudflareHandleRequests, fastlyHandleRequests) via their options object.
Analytics is not supported on CloudFront.
No extra credentials are required. Analytics requests are authenticated with
your configured merchant apiKey using Authorization: Bearer <apiKey>. The
backend derives merchant identity from the API key, so the SDK sends no
merchant identifier in the analytics payload.
Each event captures the request id, source CDN, a normalized client IP, and the verification/enforcement decision for the request. When the CDN exposes them, it also captures richer fingerprinting signals for downstream bot- and spoof-analysis in the warehouse:
- the request country, ASN, and TLS fingerprint;
Sec-Fetch-*and client-hint (Sec-CH-UA*) request headers; the set of header names sent; and whether a cookie was present (the cookie value is never stored, only its presence);- connection-level signals on Cloudflare (from
request.cf): negotiated HTTP protocol, TLS version/cipher, TLS ClientHello length and extension fingerprint, and the CDN's verified-bot category; - query-string shape signals — length, parameter count, and a suspicious-pattern flag (the raw query string itself is never stored);
- HTTP Message Signature headers, when present.
Analytics events emit schema_version: 2. Classification stays query-time in
the warehouse — the SDK emits raw signals only and does not label traffic.
Fail-open: analytics emission is fire-and-forget and can never block, slow,
or alter request handling. If emission fails, the error is swallowed and the
request proceeds exactly as it would with analytics disabled. Analytics is also
fully isolated from billing — it is sent only to the relay at /ingest/events.
The relay endpoint is
POST /ingest/eventson the dedicated ingest service (the backend also serves it as a compatibility bridge).
Analytics is sent to {analyticsBaseUrl}/ingest/events, which defaults to the
ingest service and is independent of setBaseUrl. Point it at another
environment (or localhost) with setAnalyticsBaseUrl(), or per-instance via the
analyticsBaseUrl config option.
On Fastly, analytics can be delivered through a native Fastly real-time
logging endpoint (fastly:logger → S3 → Tinybird) instead of the HTTP relay,
which keeps the per-request event firehose off the Supertab Connect backend.
Enable it by passing logEndpoint (the name of a logging endpoint configured on
your Fastly service) together with merchantSystemUrn to fastlyHandleRequests:
return SupertabConnect.fastlyHandleRequests(
event.request,
merchantApiKey,
"origin-backend",
{
analyticsEnabled: true,
logEndpoint: "bot_events",
merchantSystemUrn: "urn:supertab:merchant-system:...",
}
);merchantSystemUrn is required for native logging — there's no backend to derive
merchant identity in this path, so the SDK stamps it onto each row. If
logEndpoint is omitted (or merchantSystemUrn is missing), Fastly analytics
falls back to the HTTP relay. This option is Fastly-only; Cloudflare always uses
the HTTP relay.
The SDK serves a self-report endpoint at GET /.well-known/supertab/status on
your origin. It lets the Supertab Connect backend confirm a deployed SDK's live
configuration — this powers the merchant portal's live-health view. It is served
automatically across all runtimes; no configuration is required.
The endpoint is gated: it returns config only to a request carrying a valid,
backend-minted signed challenge (Authorization: Bearer <challenge>). Any other
request — no challenge, or an invalid/expired one — gets a minimal
{ "supertab": true } 404. Both responses set Cache-Control: no-store.
On a valid challenge it returns the SDK's running config:
{
"runtime": "cloudflare",
"sdkVersion": "2.1.0",
"enforcement": "observe",
"eventReporting": true
}It short-circuits at the top of request handling — before token verification, bot detection, and analytics — so a probe never triggers enforcement or emits an analytics event. Ensure your edge config lets this path reach the SDK rather than routing it elsewhere.
Creates a new SupertabConnect instance (singleton). Returns the existing instance if one already exists with the same config. Throws if an instance with different config exists unless reset is true.
Clear the singleton instance, allowing a new one to be created with different config.
Pure token verification — verifies a license token without recording any events.
Parameters (options object):
| Parameter | Type | Required | Description |
|---|---|---|---|
token |
string |
Yes | The license token to verify |
resourceUrl |
string |
Yes | The URL of the resource being accessed |
baseUrl |
string |
No | Override for the Supertab Connect API base URL |
debug |
boolean |
No | Enable debug logging |
Returns: { valid: boolean; error?: string }
const result = await SupertabConnect.verify({
token: licenseToken,
resourceUrl: "https://example.com/article",
});Verifies a license token and records an analytics event. Uses the instance's apiKey for event recording.
Parameters (options object):
| Parameter | Type | Required | Description |
|---|---|---|---|
token |
string |
Yes | The license token to verify |
resourceUrl |
string |
Yes | The URL of the resource being accessed |
userAgent |
string |
No | User agent string for event recording |
requestHeaders |
Record<string, string> |
No | Request headers to include in event properties |
debug |
boolean |
No | Enable debug logging |
ctx |
ExecutionContext |
No | Execution context for non-blocking event recording |
Returns: { valid: boolean; error?: string }
Handles an incoming request end-to-end: extracts the license token from the Authorization header, verifies it, optionally emits a relay analytics event, and applies bot detection and enforcement mode when no token is present.
Parameters:
request(Request): The incoming HTTP requestcontext(HandleRequestContext, optional): Per-request context object. Carries the execution context (ctx) for non-blocking work, thesourceCdn, and CDN-supplied analytics signals (clientIp,requestId,requestCountry,requestAsn,tlsFingerprint).
Returns: HandlerResult — one of { action: "allow", headers? }, { action: "block", status, body, headers }, or { action: "respond", status, body, headers } (the SDK serving its own response, e.g. the status endpoint). In observe mode, a bot without a token is allowed through with RSL signal headers (X-RSL-Status: token_required); the analytics event still records final_action: "observe".
Convenience handler for Cloudflare Workers. Reads config from Worker environment bindings (MERCHANT_API_KEY).
Parameters:
request(Request): The incoming Worker requestenv(Env): Worker environment bindingsctx(ExecutionContext): Worker execution context
Convenience handler for Fastly Compute.
Parameters:
request(Request): The incoming Fastly requestmerchantApiKey(string): Your Supertab merchant API keyoriginBackend(string): The Fastly backend name to forward allowed requests tooptions.enableRSL(boolean, optional): Servelicense.xmlat/license.xmlfor RSL-compliant clients (default:false)options.merchantSystemUrn(string): Required whenenableRSListrue(to fetchlicense.xml) and when using native Fastly logging (logEndpoint, to stamp analytics rows with merchant identity). Enforced at the type level via a discriminated union (FastlyHandlerOptions).options.logEndpoint(string, optional): Name of a Fastly real-time logging endpoint. When set (withmerchantSystemUrn), analytics events are delivered through native Fastly logging (→ S3 → Tinybird) instead of the HTTP relay. Omit it to use the relay.options.botDetector(BotDetector, optional): Custom bot detection functionoptions.enforcement(EnforcementMode, optional): Enforcement mode (defaultOBSERVE)options.analyticsEnabled(boolean, optional): Emit analytics events (defaultfalse)
The options parameter is optional. RSL hosting (enableRSL + merchantSystemUrn) is independent of analytics. For analytics, merchantSystemUrn is sent only on the native-logging path (where the SDK stamps it onto each row); on the HTTP relay path the backend derives merchant identity from the API key and no merchant identifier is sent.
Convenience handler for AWS CloudFront Lambda@Edge viewer-request functions.
Parameters:
event(CloudFrontRequestEvent): The CloudFront viewer-request eventoptions(CloudfrontHandlerOptions): Configuration object withapiKeyand optionalbotDetector/enforcement. CloudFront does not emit analytics events.
Request a license token from the Supertab Connect token endpoint using OAuth2 client credentials.
If usage is provided and a matching <content> block permits that usage without requiring a license token,
the SDK returns undefined instead of requesting a token as this is the valid behavior.
Parameters (options object):
| Parameter | Type | Required | Description |
|---|---|---|---|
clientId |
string |
Yes | OAuth client identifier |
clientSecret |
string |
Yes | OAuth client secret for client_credentials flow |
resourceUrl |
string |
Yes | Resource URL to obtain a license for |
usage |
UsageType |
No | Usage being requested; enables serverless usage matching |
debug |
boolean |
No | Enable debug logging |
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/articles/post-1",
usage: UsageType.SEARCH,
});
if (token === undefined) {
// The matching serverless license already permits this usage.
} else {
// Use the token in the Authorization header.
}