shopify/shopify-api
Official Shopify API library for PHP. Build Shopify apps and integrations with REST and GraphQL Admin API support, OAuth, webhooks, session storage, and typed request/response helpers for modern PHP applications.
Architecture fit. shopify/shopify-api is Shopify's official, framework-agnostic PHP SDK: PSR-7/PSR-18 HTTP client, PSR-16 cache adapter, PSR-3 logging, and explicit Context/Session objects for auth, plus Rest, Graphql, and webhook utilities. That is a clean seam for a Laravel app, but it is not a Laravel package — there is no service provider, no config publish, no facade. We would own the glue: bindings in AppServiceProvider, a config/shopify.php, a session repository backed by Eloquent or Redis, and a middleware that hydrates and tears down Context per request/job. Fit is good for a thin anti-corruption layer; it is poor if the team expects drop-in Laravel ergonomics.
Integration feasibility. High for the happy path. composer require shopify/shopify-api, an OAuth install/callback route, a webhook controller with HMAC verification, and a session table gets us to a working merchant install in roughly one to two sprints for one engineer. Write paths (orders, inventory, fulfillments) add idempotency, retry, and reconciliation work — that is where the schedule actually lives.
Technical risk. The dominant risk is not code quality, it is lifecycle: the repository is archived and shows zero dependents, which means no upstream security patches, no compatibility work for new Shopify API versions, and effectively no peer-reviewed usage signal to lean on. Shopify ships a new API version quarterly and sunsets old ones on a fixed calendar; an archived SDK will drift out of support on a known date. Secondary risks: the Context object is process-global, so it leaks across requests under Octane and across jobs in a Horizon worker unless explicitly reset; per-shop rate limiting requires shared throttle state in a multi-worker deployment; and REST/GraphQL quota semantics (leaky bucket vs. calculated cost) need different backoff strategies.
Key questions.
Stack fit. Works with Laravel 10–12 on PHP 8.1+ alongside Guzzle, Redis, and Horizon with no conflicts. Recommended shape: a ShopifyGateway interface owned by our domain, with the SDK confined to one adapter package. Every call site talks to the interface, never to Shopify\Clients\* directly — this is the single most valuable design decision given the archive risk, because it turns a future library swap into a one-class change. Persist sessions in a shopify_sessions table keyed by shop domain; use Redis for the PSR-16 cache and for a shared rate-limit ledger.
Migration path. Treat this as an adopt-with-exit. Phase 0: two-day spike proving OAuth, one GraphQL query, one webhook. Phase 1: if the archive is confirmed terminal, evaluate the successor and decide fork-vs-replace before building breadth — a fork is acceptable if we only need the Admin GraphQL client and auth helpers, which is a small, auditable surface. Phase 2: if we adopt, vendor the fork under our namespace with a pinned commit and an SBOM entry so security scanning tracks it. If a maintained alternative appears, the ShopifyGateway seam lets us run both adapters behind a feature flag and cut over per-endpoint.
Compatibility. Pin the API version explicitly in config (never "latest"), record it in the ADR, and put the quarterly deprecation calendar into the platform roadmap as recurring work rather than a surprise. Pin the SDK to an exact version — no caret ranges, since no upstream will fix breakage. Verify PHP minor-version support against our runtime before each Laravel upgrade.
Sequencing. (1) Spike and archive-risk decision gate. (2) Auth, install/callback, session persistence, Context lifecycle middleware. (3) Read-only catalog and order sync to validate auth and pagination. (4) Write paths with idempotency keys and a reconciliation job. (5) Webhook intake — HMAC verification, dedupe on X-Shopify-Webhook-Id, enqueue and ack fast. (6) Rate-limit and backoff layer with per-shop budgets. (7) Observability, runbooks, load test. Do not start at (4); the ordering exists so the exit decision at (1) is made cheaply.
Maintenance. Archived means we inherit the maintenance burden outright. Budget a recurring line item: a named owner, a quarterly review against Shopify's API changelog, dependency and CVE scanning on the vendored fork, and a documented patch process. Realistically 2–4 engineer-days per quarter in steady state, spiking when Shopify deprecates a resource we use.
Support. No upstream issue tracker, no maintainer response, no security advisories. Shopify Partner Support will help with API behavior but will not debug our SDK. Internal Tier-2 ownership is mandatory; without it, an auth regression becomes a merchant-facing outage with no escalation path.
Scaling. Shopify throttles per shop, not per app: REST is a leaky bucket at ~2 req/s with burst 40, GraphQL is a calculated-cost budget that refills over time. Horizontal scaling therefore requires a shared throttle ledger (Redis) rather than per-process state, or workers will collectively blow the bucket. Bulk operations (bulkOperationRunQuery) are the correct answer for large backfills and should be designed in from the start rather than bolted on after the first timeout. Webhook ingestion should be queue-fronted so traffic spikes from a busy merchant do not touch the request path.
Failure modes. Expect: expired or revoked access tokens (needs re-auth prompts and merchant notification); HMAC mismatches from proxy body mutation (do not let middleware rewrite the raw payload); 429 storms from absent shared throttling; duplicate and out-of-order webhooks (dedupe on webhook ID, treat payload as a hint and re-fetch); Context bleed under Octane/Horizon causing cross-shop data access — the highest-severity failure here and worth an explicit test; and silent drift when a pinned API version is sunset. Each needs an alert, not just a log line.
Ramp-up. One to two backend engineers, roughly two to three weeks to productive, with the ShopifyGateway seam and a written ADR covering the archive decision as the onboarding artifacts. A runbook covering token refresh, throttle saturation, webhook backlog, and the fork-patch procedure is the deliverable that makes this supportable by someone who did not build it. Given the archived status and zero dependents, the honest framing to stakeholders is: we are adopting a small, well-shaped library and accepting ownership of it — approve on that basis, or fund the evaluation of a maintained alternative first.
How can I help you explore Laravel packages today?