Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Steam Api Sdk Laravel Package

fkrzski/laravel-steam-api-sdk

Laravel SDK for the Steam Web API, giving you a clean, configurable PHP interface to fetch player profiles, owned games, achievements, stats, and news with expressive fluent methods and sensible defaults.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Require the package (this release needs the base SDK ^0.9):
    composer require fkrzski/laravel-steam-api-sdk
    php artisan vendor:publish --tag=steam-api-config
    
  2. Set your key in .env:
    STEAM_API_KEY=...
    
  3. First call — everything now goes through a resource, not the facade's endpoint helpers:
    use Fkrzski\LaravelSteamApiSdk\Facades\Steam;
    
    $me = Steam::users()->summaries(SteamId::make('7656119...'));
    
  4. First useful checks before writing feature code:
    • php artisan about — confirm the key is picked up and read the new "Requests Remaining", "429 Cool-down" and "Sender" rows.
    • Steam::webApi()->serverTime() — zero-risk smoke test of connectivity: it returns Steam's clock as a DateTimeImmutable (UTC) and never sends your key.
    • Steam::webApi()->supportedApis() — lists the Web API methods your key can call (falls back to the unauthenticated list if no key is configured). Great for verifying key permissions and for discovering which resource a given endpoint lives on.

Where to look first: the API reference (which resource holds which endpoint — this changed in 0.9.0), the new rate limiting docs page, and the base SDK's hooks page linked from the docs.

Implementation Patterns

Always go through resources. The 19 facade helpers (Steam::summaries() … Steam::appNews()) are gone. Each call keeps its name, arguments and return type, so migration is mostly adding the resource segment:

Steam::groups($id);            // → Steam::users()->groups($id)
Steam::currentPlayers(440);   // → Steam::stats()->currentPlayers(440)
Steam::newsFeed();            // unchanged, still on the facade

A quick grep for Steam:: in your app plus the API reference will surface every site to update.

Own limits instead of the fixed daily cap. Configure in config/steam-api.php:

'rate_limit' => [
    'limits' => [
        ['allow' => 100, 'every' => 60, 'sleep' => 1000], // per-minute guard
        ['allow' => 100000, 'every' => 'day'],            // Steam's daily budget, resets 00:00 UTC
    ],
    'cooldown' => 60, // seconds held back after a 429 without Retry-After
],

limits => [] disables local metering entirely (useful in tests, or when you meter elsewhere). Note the day boundary is UTC midnight, not 24h after the first request — align any of your own windowing logic with that.

Queue jobs that touch Steam. Wrap jobs with RespectsSteamRateLimit; it releases the job until the next UTC midnight when the daily budget is spent, rather than failing it. Pair this with a limit set in config so the trait knows what's left.

Custom HTTP sender via the container. Middleware now lives on a GuzzleSender subclass that the container builds:

// AppServiceProvider::register()
$this->app->bind(\Fkrzski\PhpSteamApiSdk\Http\Senders\GuzzleSender::class, function () {
    $sender = new class extends \Fkrzski\PhpSteamApiSdk\Http\Senders\GuzzleSender {
        // add your middleware / handler stack here
    };
    return $sender;
});
STEAM_API_SENDER=App\Steam\MyGuzzleSender

Use this for retry/logging/tracing middleware, a proxy, or to point the Guzzle client at a stubbed handler in local environments. Because the sender is resolved each time the connector is built, a request-scoped binding will take effect (e.g. swapping in a mock per test).

Test with the fluent fake, which now covers the new endpoints:

Steam::fake([
    '*GetPlayerSummaries*' => Steam::response()->users()->summaries(...),
]);

Steam::fake()->webApi()->serverInfo();          // clock
Steam::fake()->webApi()->supportedApiList();    // authenticated method list
Steam::fake()->webApi()->supportedApiListInvalidKey();
Steam::fake()->users()->summaries()->friendsOnly(); // profile read back as CommunityVisibility::FriendsOnly

Use the factory helpers (PlayerSummaryFactory::friendsOnly(), WebApiMethodFactory, WebApiParameterFactory) to build realistic batches, including the friends-only case that used to blow up whole 100-profile calls.

Observability. With laravel/nightwatch installed and enabled, Steam calls appear as outgoing requests with the API key stripped from recorded URLs — useful for spotting slow endpoints or 429 storms in staging. Combine with the about "Requests Remaining" row to decide whether a job should even be dispatched.

Health/ops surface. A tiny scheduled command calling Steam::webApi()->serverTime() is a cheap liveness probe (no key spent, no quota spent) — good for an uptime check that actually exercises your credentials path minus the key.

Gotchas and Tips

  • Breaking changes, four of them. Endpoint helpers removed; Steam::connector()->sender() now returns the SDK's SteamSender wrapper, so addMiddleware(), getHandlerStack() and getGuzzleClient() are gone — move that code into a GuzzleSender subclass as above.
  • Exception rename. InvalidSteamRateLimitStoreException → InvalidSteamRateLimitOptionException. Catching the old name silently won't catch. It now guards the whole steam-api.rate_limit block, so a typo in limits/cooldown throws from here — check the message, it usually points at the offending key.
  • Config merging is shallow. A config file published before 0.9.0 has no http.sender, rate_limit.limits or rate_limit.cooldown — your values are used, but STEAM_API_SENDER and STEAM_API_RATE_LIMIT_COOLDOWN are unread until you copy those keys into the published file. If the sender binding "doesn't work", this is almost always why.
  • One-time counter reset. The daily limit key is renamed 100000_every_utc_midnight, so any persistent rate-limit store restarts from zero once on upgrade. Harmless, but don't be alarmed by a burst on deploy.
  • about --json consumers. daily_requests_remaining → requests_remaining, and it's now a list spanning every configured limit rather than a single number. Update dashboards and any assertions in CI.
  • Debugging rate limits: the tracker is local; a 429 from Steam means your local limits don't reflect Steam's reality (or another machine/key shares the budget). Check cooldown is non-zero, and remember it only applies to 429s without Retry-After.
  • Don't send the key when you don't need to. serverTime() never sends it; supportedApis() sends it only when configured. Prefer these for unauthenticated smoke tests so keys stay out of logs and third parties.
  • Nightwatch redaction covers URLs it records — but your own logging isn't redacted. If you log the connector's base URL, keep the key out of query strings.
  • Extension points: custom Sender (config/container), rate limit store (persistent store config for multi-node fleets), and the factories for building realistic fakes. Pre-1.0, so pin the package and the base SDK in lockstep (^0.9) and read the Upgrading section before every minor bump.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource