Once you have a configured connector, three concepts carry the rest: the SteamId value object every request accepts, the resources you call on the connector, and the readonly DTOs you get back.

SteamId is the only accepted identifier across the SDK — no raw strings. Which constructor you reach for depends on where the ID came from:

use Fkrzski\SteamApiSdk\ValueObjects\SteamId;
// Throws InvalidSteamIdException on anything but a 17-digit numeric ID.
$id = SteamId::fromSteamId64('76561198000000000');

The underlying value is available as $id->value (or (string) $id), and two IDs compare with $id->equals($other).

The connector groups every endpoint into a resource per Steam interface — players() for IPlayerService, users() for ISteamUser, stats() for ISteamUserStats, apps() for ISteamApps, news() for ISteamNews, webApi() for ISteamWebAPIUtil. Each method sends the request and hands back the DTO, so nothing needs importing:

$summaries = $connector->users()->summaries([$id]);

Behind every resource method sits a plain Saloon Request, still public and unchanged. Build one yourself when you want the response rather than only the DTO, or a Saloon feature that takes a request — pool() or sendAsync():

use Fkrzski\SteamApiSdk\Http\Requests\ISteamUser\GetPlayerSummariesRequest;
$response = $connector->send(new GetPlayerSummariesRequest([$id]));
$response->status(); // 200
$summaries = $response->dto();

The connector uses Saloon’s AlwaysThrowOnErrors, so a non-2xx response fails before the DTO is built — always as an SDK exception, never a Saloon one. The same holds when no response comes back at all, through send(), sendAsync() and pool() alike. A 200 whose payload reports a failure, one of the two 200 rows in the mapping table, fails the same way, so send() never hands back its response. Which call returns which DTO is in the API reference.

pool() sends a batch several at a time, and each handler gets the request’s key:

use Fkrzski\SteamApiSdk\Http\Requests\IPlayerService\GetOwnedGamesRequest;
use Fkrzski\SteamApiSdk\ValueObjects\SteamId;
use Saloon\Http\Response;
$libraries = [];
$connector->pool(
requests: array_map(fn (SteamId $id) => new GetOwnedGamesRequest($id), $ids),
concurrency: 5,
responseHandler: function (Response $response, int $key) use (&$libraries): void {
$libraries[$key] = $response->dto();
},
exceptionHandler: function (Throwable $e, int $key) use ($logger): void {
$logger->warning($e->getMessage());
},
)->send()->wait();

A failure reaches exceptionHandler as the SDK exception, a hidden profile Steam reports in a 200 included, and fires onFailure(). Each request goes out once, whatever tries says, and every answer counts against the budget. sendAsync() sends one request the same way and returns a promise that rejects with the same exceptions.

GetPlayerSummariesRequest and GetPlayerBansRequest take up to 100 IDs. users()->summaries() and users()->bans() take any number: up to 100 go out as one request, retried as tries says, and a longer list is cut into requests of 100 that pool() sends concurrency at a time:

$summaries = $connector->users()->summaries($ids, concurrency: 10);

Each chunk is sent once and counts as one request, so 1 000 IDs spend 10. The first failure is thrown once the chunks in flight have answered, and no chunk goes out after it. A concurrency under 1 throws InvalidArgumentException.