A framework-agnostic PHP SDK for the Steam Web API,
built on top of Saloon v4. Every request returns a
strongly-typed, readonly DTO — you never touch raw JSON, and a malformed profile
fails with a domain exception instead of a silent null. It powers the player profiles
on Dead by Stats.
Why php-steam-api-sdk
Section titled “Why php-steam-api-sdk”- Fluent resources —
$connector->players()->ownedGames($id), no request classes to import. - Strongly typed — PHP 8.5, PHPStan max, 100% type coverage.
- Readonly DTOs — immutable objects with
DateTimeImmutable, never framework date wrappers. - Domain exceptions — one hierarchy rooted at
SteamApiExceptionfor every failure. - Rate limit baked in — the 100 000 requests/day quota is enforced per API key and resets at 00:00 UTC;
rateLimitsswaps in your own. - Timeouts and retries — set once on
SteamConfig; only a5xxor no answer at all is retried, since every attempt spends quota. - Hooks without the key —
onRequest(),onResponse()andonFailure()for logs and metrics, anddebug()masks the key askey=***. - Your own requests — a method the SDK does not ship is one Saloon request away, sent with the key, the budget and SDK exceptions.
- Test fakes —
SteamFakefakes every endpoint through the resource chain, with a factory per DTO and the failures Steam really sends. - Zero framework coupling — plain Saloon over any
Senderyou hand it; a Laravel bridge ships separately.
Requirements
Section titled “Requirements”- PHP 8.5+
- Saloon 4+
Installation
Section titled “Installation”-
Pull the package in:
Terminal window composer require fkrzski/php-steam-api-sdk -
Keep your Steam Web API key out of the source tree, or skip it if the anonymous endpoints are all you need:
.env STEAM_API_KEY=your-steam-web-api-key -
Build a connector from it, and reuse that one instance — it carries the key and the daily budget:
steam.php use Fkrzski\SteamApiSdk\SteamConfig;use Fkrzski\SteamApiSdk\SteamConnector;$connector = new SteamConnector(new SteamConfig(apiKey: $_ENV['STEAM_API_KEY'],));
Quickstart
Section titled “Quickstart”use Fkrzski\SteamApiSdk\ValueObjects\SteamId;
$summaries = $connector->users()->summaries([SteamId::fromSteamId64('76561198000000000')]);
echo $summaries[0]->personaName;Every endpoint hangs off a resource named after its Steam interface — players(),
users(), stats(), apps(), news(), webApi() — and returns the readonly DTO straight away.
Versioning
Section titled “Versioning”The SDK follows SemVer from 1.0.0. A minor or patch release keeps:
SteamConfigand its named arguments, and onSteamConnectorthe constructor, the resources with their methods, andonRequest(),onResponse()andonFailure().- The request classes’ constructors and the DTO each one returns.
- What you read off DTOs, hook payloads and exceptions: properties and their types, the exception hierarchy and codes, and the Steam method that opens a message.
SteamId, the enums withfromApiValue(), and theHasLanguage,SendsNoApiKeyandSendsOptionalApiKeycontracts.- The
SteamApiExceptionconstructor, for exceptions of your own. - The exception each Steam answer maps to, and what a sender has to honour. Following Valve when it changes an answer is a fix.
SteamFake,SteamResponseand the factories underTesting.
Any release may change:
- Anything marked
@internal: DTO constructors andfromArray(), the hook payload andSteamSenderconstructors, and the exceptions’ named constructors such asfromLimit(). Build DTOs and failures in tests with the testing helpers; PHPStan with bleeding edge reports a call from your code. - Resource constructors; reach a resource through the connector.
- An exception’s message after the method prefix.
- Saloon’s lifecycle methods the connector and requests implement, such as
boot(),resolveEndpoint()andgetRequestException(). - Limit names and the keys in a rate limit store, so a release may restart the counters once.
Saloon’s own methods on the connector — send(), pool(), withMockClient(),
getExceededLimit() and the rest — follow Saloon’s versioning, and the SDK keeps what it
documents on top of them. A new major of Saloon or its rate limit plugin comes in an SDK major,
a higher minimum PHP in a minor.