PHPackages                             getstream/getstream-php - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. getstream/getstream-php

ActiveLibrary[API Development](/categories/api)

getstream/getstream-php
=======================

PHP SDK for GetStream API

v10.0.0(3w ago)045.2k↑22.7%[2 PRs](https://github.com/GetStream/getstream-php/pulls)MITPHPPHP ^8.1CI passing

Since Aug 25Pushed 1w agoCompare

[ Source](https://github.com/GetStream/getstream-php)[ Packagist](https://packagist.org/packages/getstream/getstream-php)[ RSS](/packages/getstream-getstream-php/feed)WikiDiscussions master Synced 2w ago

READMEChangelog (10)Dependencies (49)Versions (57)Used By (0)

GetStream PHP SDK
=================

[](#getstream-php-sdk)

A PHP SDK for the GetStream API.

Installation
------------

[](#installation)

Install via Composer:

```
composer require getstream/getstream-php
```

Migrating from stream-chat-php?
-------------------------------

[](#migrating-from-stream-chat-php)

If you are currently using [`stream-chat-php`](https://github.com/GetStream/stream-chat-php), we have a detailed migration guide with side-by-side code examples for common Chat use cases. See the [Migration Guide](docs/migration-from-stream-chat-php/README.md).

Configuration
-------------

[](#configuration)

Copy `.env.example` to `.env` and configure:

```
cp .env.example .env
```

Required environment variables:

```
STREAM_API_KEY=your_api_key_here
STREAM_API_SECRET=your_api_secret_here
STREAM_BASE_URL=https://chat.stream-io-api.com
```

Connection Pool Tuning
----------------------

[](#connection-pool-tuning)

```
$client = (new GetStream\ClientBuilder())
    ->apiKey($apiKey)
    ->apiSecret($apiSecret)
    ->maxConnsPerHost(5)   // default 5 (per-host concurrency cap, see runtime caveats)
    ->idleTimeout(55)      // default 55s (per-connection lifetime cap, see runtime caveats)
    ->connectTimeout(10)   // default 10s
    ->requestTimeout(30)   // default 30s
    ->build();
```

**Per-call timeout override:**

```
$response = $client->getHttpClient()->request(
    'GET', $url, $headers, null, ['timeout' => 2]
);
```

Per-call `curl` overrides replace (do not merge with) the client-level `curl` options, since Guzzle unions options shallowly. Only `['timeout' => N]` is documented for per-call use.

**Runtime caveats.** `maxConnsPerHost` and `idleTimeout` are enforced via libcurl's persistent multi-handle pool (`CURLMOPT_MAX_HOST_CONNECTIONS` and `CURLOPT_MAXLIFETIME_CONN`). They take effect only when the SDK client is reused across requests within a single PHP process: long-running runtimes such as Swoole, RoadRunner, ReactPHP, and CLI daemons. Instantiate the SDK client once and reuse it. Under PHP-FPM (and one-shot CLI scripts) the PHP process exits at the end of each request, so there is no cross-request pool to size; the per-call request and connect timeouts still apply. `idleTimeout` requires libcurl 7.80.0 (Nov 2021) or later; pooling still works without it on older builds, just without active lifetime cycling.

**Escape hatch:** Passing your own client via `->httpClient($mine)` skips all 4 knobs; your client is used as-is.

Retries (opt-in)
----------------

[](#retries-opt-in)

Auto-retry is off by default: the client makes exactly one attempt and surfaces errors unchanged. Enable it with `->retry(new RetryConfig(...))`:

```
$client = GetStream\ClientBuilder::fromEnv()
    ->retry(new RetryConfig(enabled: true, maxAttempts: 3, maxBackoff: 30.0))
    ->build();
```

When enabled, a failed attempt is retried only if all of the following hold: the method is `GET` or `HEAD`; the failure is an HTTP 429 (and not marked `unrecoverable`) or a transport error (`StreamTransportException`); and fewer than `maxAttempts` attempts have been made. Writes (`POST`/`PUT`/`PATCH`/`DELETE`) and any other 4xx/5xx status are never retried.

Backoff honors a parsed `Retry-After` header when present (capped at `maxBackoff`, no jitter); otherwise it uses exponential backoff with full jitter, also capped at `maxBackoff`. On exhaustion, the last attempt's error is thrown unchanged.

**Breaking change from earlier versions:** this SDK previously retried HTTP 429 responses on every request automatically (`maxRetries`, default 3). That always-on behavior is gone; retries are now opt-in via `RetryConfig` and apply only to `GET`/`HEAD`.

Logging
-------

[](#logging)

The SDK emits structured events through a [PSR-3](https://www.php-fig.org/psr/psr-3/) `Psr\Log\LoggerInterface`. No logger is injected by default (`Psr\Log\NullLogger`, a no-op); pass your own via `->logger(...)`:

```
$client = (new GetStream\ClientBuilder())
    ->apiKey($apiKey)
    ->apiSecret($apiSecret)
    ->logger($myPsr3Logger)
    ->build();
```

Events emitted:

EventLevelWhen`client.initialized`INFOOnce, at construction`http.request.sent`DEBUGBefore each HTTP attempt`http.response.received`DEBUGAfter any HTTP response, including 4xx/5xx (status codes are data, not a failure)`http.request.failed`ERRORTransport failure that surfaces to the caller unchanged (connection reset, timeout, DNS failure, TLS handshake failure) — no HTTP response was received`http.request.failed`DEBUGAlso emitted, with a `retry.attempt` field, right before each retry backoff sleep (see [Retries](#retries-opt-in))The SDK never sets the logger's minimum level; that's the caller's responsibility.

**Bodies are not logged by default.** Enable with `->logBodies(true)`; this emits one WARN at construction and adds (key-redacted) `http.request.body` / `http.response.body` fields to the DEBUG events. Query values for `api_key`, `api_secret`, `token` and top-level JSON body keys `api_secret`, `token`, `password` are always redacted (case-insensitive for query values), whether or not body logging is on. No headers are ever logged.

```
$client = (new GetStream\ClientBuilder())
    ->apiKey($apiKey)
    ->apiSecret($apiSecret)
    ->logger($myPsr3Logger)
    ->logBodies(true)
    ->build();
```

Code Generation
---------------

[](#code-generation)

Generate API methods from OpenAPI spec:

```
./generate.sh
```

Testing
-------

[](#testing)

Run tests:

```
# Run all tests
make test

# Run unit tests only
make test-unit

# Run integration tests (requires API credentials)
make test-integration
```

Usage
-----

[](#usage)

### Basic Setup

[](#basic-setup)

```
