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

# PHP SDK

> Official PHP SDK for Westyx Nexus - PHP 8.3+, Guzzle 7, TTL cache, SSE live updates.

Official PHP SDK for [Westyx Nexus](https://westyx.dev) - the centralised secrets, feature flags, and config service.

```php theme={null}
use WestyxNexus\NexusClient;
use WestyxNexus\NexusConfig;

$client = NexusClient::create(new NexusConfig(
    baseUrl: 'https://blue-ocean-a5rx7.westyx.dev',
    apiKey:  'wxs_...',
));

$dbUrl   = $client->getConfig('database.url');
$stripe  = $client->getSecret('stripe.key');
$enabled = $client->getFlag('new.checkout', false);
```

## Highlights

* **PHP 8.3+** - pure PHP, no framework required
* **Guzzle 7** HTTP client with configurable timeouts
* **TTL cache with ETag/304 support** - reads never block the network after the first sync
* **SSE live updates** via `connectStream()` (long-running CLI daemons and queue workers only)
* **Public-key vs secret-key access control** - public-key clients get `NexusPublicKeyException` from `getSecret`
* **Workload Identity Federation** - Kubernetes / AWS IRSA / GCP / Azure auto-detected; **AWS IAM (`aws_iam`)** for ECS/Fargate/Lambda/plain-EC2 *(v0.9.0)*
* **Write API** (`setSecret`, `deleteSecret`, `deleteSecretVersion`) for secret keys
* **A/B testing** (`evaluateAb`) for the AB Testing add-on
* **File-type secrets** (`getSecretFilePath`) - materialised to a temp file; cleaned up in `__destruct`
* **402/429 handling** with quarantine detection (`NexusQuarantinedException` with `$reason` and `$expiresAt`)

## What's new in v0.10.0

* Version alignment across the Westyx Nexus SDK suite.

## What's new in v0.9.0

* **`aws_iam` WIF provider (AWS IAM Caller Identity)** - authenticates non-EKS AWS compute (**ECS/Fargate, Lambda, plain EC2**) that has IAM credentials but no OIDC token. The SDK SigV4-signs an STS `GetCallerIdentity` request (never sent to AWS) and posts it to `/v1/auth/token-exchange`; Nexus replays it against a pinned STS endpoint to prove your IAM role. The signed `X-Nexus-Server-ID` is your service's own base-URL host - a captured request is valid for that one service only, and there is nothing to configure. Requires the optional `aws/aws-sdk-php` package. See [Workload identity](workload-identity#aws-iam-non-eks-aws-compute).
* **Security hardening** - the base URL must be `https://` (loopback excepted); expired WIF sessions refresh transparently on every request path and **fail closed** (a WIF-only client never falls back to an empty API key); the GCP metadata and token-exchange reads are size-bounded; auto-detection stats the AWS/Azure token files instead of trusting a bare env var; a non-positive `expires_in` is clamped.

## What's new in v0.8.2

* **WIF GCP fix** - the `gcp` provider now fetches a real Google-signed OIDC identity token from the GCE metadata server. It previously read the `GOOGLE_APPLICATION_CREDENTIALS` key file, which is not a JWT and was rejected by the token exchange. Auto-detection was aligned with the actual token sources. Verified end-to-end against a real GCE workload.

## What's new in v0.8.1

* **Docs fix** - corrected the example service base URL from the non-existent `https://<slug>.api.westyx.dev` to the correct `https://<slug>.westyx.dev` (the deployed host format). No API or behavior change.

## What's new in v0.8.0

* **OpenFeature provider** - new `westyx/nexus-openfeature` Composer package implementing the [OpenFeature](https://openfeature.dev) PHP SDK provider interface. Install separately; wraps an existing `NexusClient` with no additional network calls.

## What's new in v0.5.1

* **Requires PHP 8.3+** - PHP 8.1 and 8.2 are EOL; the SDK now requires PHP 8.3 or later.
* **Security improvements** - exception messages contain only status codes; file-type secret paths are fully hashed.
* **Reliable streaming** - improved quarantine handling and full SSE event coverage.

## What's new in v0.5.0

* **Path prefix update** - API endpoints use `/v1/`; update your `baseUrl` to `<slug>.westyx.dev`.
* **Quarantine handling** - new `429` quarantine response pauses sync until expiry; `NexusQuarantinedException` exposes `$reason` and `$expiresAt`.
* **Write API** - `setSecret`, `deleteSecret`, `deleteSecretVersion` for services using a secret key.
* **`is_public` removed** - PK keys now see all configs and flags without the `is_public` filter.

## Installation

```sh theme={null}
composer require westyx/nexus
```

A repository entry is required in your `composer.json` - see [Installation](installation) for the full setup.

Latest release: **v0.10.0** *(2026-07-05 - version alignment across the Westyx Nexus SDK suite)*.

## Quick start

```php theme={null}
<?php

require_once __DIR__ . '/vendor/autoload.php';

use WestyxNexus\NexusClient;
use WestyxNexus\NexusConfig;
use WestyxNexus\Exceptions\NexusUnauthorizedException;
use WestyxNexus\Exceptions\NexusNotFoundException;

$client = NexusClient::create(new NexusConfig(
    baseUrl: $_ENV['NEXUS_URL'],
    apiKey:  $_ENV['NEXUS_API_KEY'],
    ttl:     60,
));

$dbUrl = $client->getConfig('database.url');
if ($dbUrl === null) {
    throw new \RuntimeException('nexus: missing database.url config');
}

$stripe = $client->getSecret('stripe.key');
if ($stripe === null) {
    throw new \RuntimeException('nexus: missing stripe.key secret');
}

$newUi = $client->getFlag('new.ui', false);
```

## Pages

| Page                                   | Description                                                     |
| -------------------------------------- | --------------------------------------------------------------- |
| [Installation](installation)           | `composer require`, repository config, requirements             |
| [Configuration](configuration)         | `NexusConfig` field reference, API key types, TTL guidance      |
| [API reference](api-reference)         | Every public method with signatures and return values           |
| [Error handling](error-handling)       | Exception hierarchy, when each is thrown, try/catch examples    |
| [SSE live updates](sse-live-updates)   | `connectStream()` semantics, FPM warning, backoff, max errors   |
| [Caching behaviour](caching-behaviour) | When the SDK hits the network, ETag/304, FPM per-request model  |
| [Workload identity](workload-identity) | `WifConfig` setup, provider auto-detection, token exchange flow |
| [Custom logging](custom-logging)       | PSR-3 `LoggerInterface`, Monolog, Symfony, Laravel examples     |
