> ## 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.

# PHP SDK

The Supertab Connect PHP SDK lets publishers implement RSL license serving and CAP enforcement in PHP applications. It handles token verification, bot detection, enforcement, and analytics recording.

**Requirements:** PHP 8.1+, with extensions `ext-curl`, `ext-json`, `ext-openssl`, `ext-simplexml`.

## Installation

```bash theme={null}
composer require getsupertab/connect-sdk-php
```

## Initializing the Client

```php theme={null}
use Supertab\Connect\SupertabConnect;
use Supertab\Connect\Enum\EnforcementMode;

$connect = new SupertabConnect(
    apiKey: 'stc_live_your_api_key', // from your Supertab Connect dashboard
    enforcement: EnforcementMode::SOFT, // default
);
```

### Configuration Options

| Parameter     | Type                    | Required | Default | Description                                            |
| ------------- | ----------------------- | -------- | ------- | ------------------------------------------------------ |
| `apiKey`      | `string`                | Yes      | —       | Merchant API key (`stc_live_...` or `stc_sandbox_...`) |
| `enforcement` | `EnforcementMode`       | No       | `SOFT`  | How to handle bots without a valid token               |
| `debug`       | `bool`                  | No       | `false` | Enables verbose logging via `error_log()`              |
| `botDetector` | `?BotDetectorInterface` | No       | `null`  | Custom bot detection logic                             |
| `httpClient`  | `?HttpClientInterface`  | No       | `null`  | Custom HTTP client                                     |

The SDK enforces a singleton pattern per API key. Instantiating with a different key throws an exception. Use `SupertabConnect::resetInstance()` if you need to change configuration.

## Common Workflows

### Handle a Protected Request

`handleRequest()` manages the full lifecycle — token extraction, verification, bot detection, enforcement, and analytics recording. By default it reads from `$_SERVER`.

```php theme={null}
use Supertab\Connect\SupertabConnect;
use Supertab\Connect\Enum\EnforcementMode;
use Supertab\Connect\Result\BlockResult;

$connect = new SupertabConnect(
    apiKey: 'stc_live_your_api_key',
    enforcement: EnforcementMode::STRICT,
);

$result = $connect->handleRequest();

foreach ($result->headers as $name => $value) {
    header("{$name}: {$value}");
}

if ($result instanceof BlockResult) {
    http_response_code($result->status);
    echo $result->body;
    exit;
}

// Serve content for allowed requests
```

### Framework Integration

Pass a `RequestContext` instead of relying on `$_SERVER` when using a framework:

```php theme={null}
use Supertab\Connect\Http\RequestContext;

$ctx = new RequestContext(
    url: $request->getUri(),
    authorizationHeader: $request->header('Authorization'),
    userAgent: $request->header('User-Agent'),
    accept: $request->header('Accept'),
    acceptLanguage: $request->header('Accept-Language'),
    secChUa: $request->header('Sec-CH-UA'),
);

$result = $connect->handleRequest($ctx);
```

### Verify a Token and Record Usage

`verifyAndRecord()` verifies a token and records an analytics event for billing and reporting.

```php theme={null}
$connect = new SupertabConnect(apiKey: 'stc_live_your_api_key');

$result = $connect->verifyAndRecord(
    token: $token,
    resourceUrl: 'https://example.com/article/my-slug',
    userAgent: $_SERVER['HTTP_USER_AGENT'] ?? null,
);

if (!$result->valid) {
    http_response_code(401);
    echo $result->error;
    exit;
}
```

### Verify Without Recording

Use the static `verify()` for a lightweight validity check with no analytics side effects.

```php theme={null}
$result = SupertabConnect::verify(
    token: $token,
    resourceUrl: 'https://example.com/article/my-slug',
);

if (!$result->valid) {
    http_response_code(401);
    echo $result->error;
    exit;
}
```

### Obtain a License Token

Use `obtainLicenseToken()` to acquire a token before requesting licensed content. The SDK fetches and parses the publisher's `license.xml`, matches the resource URL to a content rule, and exchanges your credentials for a token. Tokens are cached in memory and refreshed automatically before expiry.

```php theme={null}
$token = SupertabConnect::obtainLicenseToken(
    clientId: 'your_client_id',
    clientSecret: 'your_client_secret',
    resourceUrl: 'https://example.com/article/my-slug',
);

$ch = curl_init('https://example.com/article/my-slug');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ["Authorization: License {$token}"],
]);
$response = curl_exec($ch);
```

### Serve the RSL License

Use `fetchLicenseXml()` to proxy your RSL license from Supertab Connect and serve it at `/license.xml` on your domain.

```php theme={null}
$xml = SupertabConnect::fetchLicenseXml(
    merchantSystemUrn: 'urn:stc:merchant:system:your_system_id',
);

header('Content-Type: application/rsl+xml');
echo $xml;
```

## 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.

### `HandlerResult`

Returned by `handleRequest()`. Has two subtypes:

* **`AllowResult`** — `action: ALLOW`, plus `headers` to set on the response
* **`BlockResult`** — `action: BLOCK`, plus `status` (HTTP code), `body`, and `headers`

### `VerificationResult`

Returned by `verify()` and `verifyAndRecord()`:

| Field   | Type      | Description                                           |
| ------- | --------- | ----------------------------------------------------- |
| `valid` | `bool`    | Whether the token is valid for the requested resource |
| `error` | `?string` | Human-readable error message when invalid             |

## Tips

**Always apply response headers.** The SDK returns `Link` and `X-RSL-Status` headers even on allowed requests in SOFT mode. Apply `$result->headers` before serving content so crawlers get the correct licensing signals.

**Pass `RequestContext` in frameworks.** Relying on `$_SERVER` directly works for plain PHP, but frameworks often normalize request data before it reaches `$_SERVER`. Use `RequestContext` to ensure the SDK reads the right values.

**Debug mode logs to `error_log()`.** Enable with `debug: true` to trace token fetching, license XML parsing, and URL matching.

## API Reference

### Static Methods

| Method                                                         | Description                                       |
| -------------------------------------------------------------- | ------------------------------------------------- |
| `verify(token, resourceUrl, ...)`                              | Verify a token without analytics recording        |
| `obtainLicenseToken(clientId, clientSecret, resourceUrl, ...)` | Acquire a license token as a crawler client       |
| `fetchLicenseXml(merchantSystemUrn, ...)`                      | Fetch RSL license XML from Supertab Connect       |
| `resetInstance()`                                              | Clear the singleton, allowing fresh instantiation |

### Instance Methods

| Method                                           | Description                                                                   |
| ------------------------------------------------ | ----------------------------------------------------------------------------- |
| `handleRequest(?RequestContext $context)`        | Handle a request end-to-end — detection, verification, enforcement, analytics |
| `verifyAndRecord(token, resourceUrl, userAgent)` | Verify a token and record a usage event                                       |
