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

Rest Api Laravel Package

bagisto/rest-api

REST API for Bagisto e-commerce: exposes storefront and admin data—products, categories, carts, customers, orders, and more—via token-authenticated JSON endpoints, so Laravel developers can build headless storefronts, mobile apps, and integrations on top of Bagisto's backend.

View on GitHub
Deep Wiki
Context7

Getting Started

Check the precondition before anything else. bagisto/rest-api is a presentation layer over the Bagisto domain model (customers, carts, catalog, checkout, orders). It does not transplant onto vanilla Laravel, and none of the patterns below transfer if your app isn't already on Bagisto 2.3.x. Compare the repo's composer.json support matrix against your PHP/Laravel/Bagisto versions before running composer require, because this package ships roughly in lockstep with Bagisto core and a version skew surfaces as confusing model/repository mismatches rather than a clean install failure.

Install and confirm what registered:

composer require bagisto/rest-api
php artisan vendor:publish --provider="Webkul\RestApi\Providers\RestApiServiceProvider"
php artisan migrate
php artisan route:list --path=api

That last command is your fastest sanity check on three things: which routes exist by default, what middleware they carry (auth guard, throttle, ETag), and whether the route prefix matches your config. Read the published config at the same time — in this package, route-level access control is configuration, and the default exposure is a security decision you inherit unless you change it.

Where to look first, in order:

  1. routes/ in the vendor package — the real contract, always more current than prose.
  2. The Swagger UI (typically /api/documentation) — the refreshed spec in v2.3.1 is the fastest way to see request/response shapes.
  3. Http/Controllers and Http/Resources — this is where you'll extend, and reading them tells you the serialization conventions you must match.

First use case: unauthenticated catalog read. It's the lowest-friction end-to-end validation and the traffic profile the package optimizes for:

curl -i 'https://your-store.test/api/v1/products?limit=10'

Inspect three things in the response: the resource envelope (single vs. collection shape), the pagination metadata keys, and — after v2.3.1 — the ETag header. If an ETag is present, immediately follow up:

curl -i -H 'If-None-Match: "<etag-value>"' 'https://your-store.test/api/v1/products?limit=10'

A 304 with an empty body confirms conditional requests are wired correctly. A 200 with a body means middleware ordering or a proxy is interfering — see Gotchas.

Second use case: authenticated customer. Token auth is the gate to cart and order history. Register or log in, capture the token, and pin it in a shared client service (not per-endpoint). This is the flow every SPA/mobile client reuses, so get the client-side handling right once.


Implementation Patterns

Wrap the API in one Laravel service, not scattered Http:: calls. You will have multiple consumers (web SPA, mobile, internal jobs) that must agree on base URL, token handling, retry policy, and ETag caching:

class BagistoClient
{
    public function __construct(
        private readonly string $baseUrl,
        private readonly ?string $token = null,
    ) {}

    public function get(string $path, array $query = [], ?string $etag = null): Response
    {
        return Http::baseUrl($this->baseUrl)
            ->withToken($this->token)
            ->withHeaders(array_filter(['If-None-Match' => $etag]))
            ->acceptJson()
            ->get($path, $query)
            ->throwUnlessStatus(304);
    }
}

The 304 needs explicit handling: it is a success, not an error, and your caller should reuse the cached body it already holds.

Consume ETags deliberately, per resource. The pattern that pays off is a cache keyed by request URL storing {etag, body}. On repeat read, send If-None-Match; on 304, return the cached body; on 200, replace both. Apply it to catalog, categories, and product detail. Do not apply it to /cart, /checkout, /customer, or /orders — those responses are personalized and the correctness risk dwarfs the bandwidth win.

Treat token lifecycle as a first-class concern. Store the token server-side if you're proxying (encrypted, per-user row); avoid a localStorage blob on a public SPA. On 401, attempt one re-auth and retry once — never in a loop. Confirm which driver backs tokens (Sanctum vs. Passport) by reading the package's auth config, then document expiry and rotation. Token semantics you guess at are token semantics you'll get wrong in production.

Model cart/checkout as a stateful sequence, not independent calls. The shape is: create cart → add line items → set shipping/billing address → set shipping method → set payment method → place order. Two rules:

  • Persist the cart identifier server-side between steps — don't rely on a client variable surviving app backgrounding or a refresh.
  • Put the sequence in a single CheckoutService with one method per step, so a failure at "set shipping method" is diagnosable without replaying the full chain.

Extend the package's controllers and resources rather than writing new ones. For a custom endpoint (loyalty balance, B2B price list), subclass the package controller and reuse its JsonResource classes. This keeps your envelope, pagination keys, and ETag middleware behavior consistent across built-in and custom routes. Register custom routes under the same prefix and middleware group the package uses so auth and throttling apply automatically.

Contract-test the spec in CI. The refreshed Swagger spec is an asset only if it matches runtime. Generate the spec and diff it against the committed artifact; fail the build on drift. If it turns out to be hand-maintained rather than annotation-generated, treat it as documentation with a shelf life and add at least one smoke test per endpoint shape against a real response.

Test with feature tests against a seeded store. Pest/PHPUnit feature tests catch what matters: status codes, envelope shape, pagination keys, and 200/304 round-trips. Add one Http::fake-free integration test against a real database — resource serialization bugs hide in eager-loading, and fakes won't reveal them.

Run a real proxy locally. php artisan serve won't reproduce ETag/If-None-Match behavior under compression, and it won't reproduce your CDN's header rewriting. Use nginx or Traefik in Docker and mirror production cache-header config.


Gotchas and Tips

ETags on personalized responses are the top correctness risk. A shared cache serving one customer's cart to another is the failure mode. On authenticated routes the response must carry Cache-Control: private and a Vary that includes Authorization (plus Accept-Language/locale/tenant if those change the body). Verify with curl -i against a cart endpoint using two different tokens — if the ETag is identical across identities, you have a leak. When in doubt, disable ETag on personalized routes rather than reasoning about it.

Middleware ordering: ETag must hash the final transformed body. If the ETag is computed before resource transformation or a response decorator mutates the payload, the hash covers the wrong bytes and clients get stale bodies on 304. Force a body change between two identical requests; a 304 where a 200 is correct means the hash is computed too early.

Compression and proxies rewrite ETags. nginx and many CDNs convert strong ETags ("abc") to weak ones (W/"abc") or strip them when gzipping. Test behind a production-like edge in staging, and make sure your client echoes back exactly what the server sent — including W/ — or you'll silently never get a 304.

Never emit ETags on errors. A 4xx/5xx should never be cached or conditionally matched. Confirm your exception handler bypasses the conditional-request middleware; otherwise a transient 500 can get pinned by a client.

Pin to a Bagisto core version and re-verify each upgrade. Use a tight Composer constraint. The failure mode of drift isn't a clear exception — it's a subtly wrong serialization or a repository method whose signature changed. Add "re-run API smoke tests" to your Bagisto upgrade checklist.

You are the support tier. 28 stars and zero known dependents means community answers won't arrive on your timeline. Budget time for reading vendor source, name an internal owner for the API layer, and keep a local patch workflow (Composer patches or a fork) ready. This is fine for first-party infrastructure — but plan for it rather than discovering it mid-incident.

Audit route access before you deploy. Which capabilities are exposed — read-only catalog vs. cart mutation vs. customer data — is configuration, and the default may be broader than you want. A read-only affiliate token and a full-checkout partner token should be different configurations, not code branches. Do this review once, deliberately, before the first partner gets a key.

Cart/session state behind a load balancer. If the cart implementation touches session or cache, multiple app servers need a shared store (Redis) or sticky sessions. This works in staging-behind-one-node and only breaks in production. Test the checkout chain with more than one app instance.

Pagination shape is a contract — read it, don't assume it. Don't default to Laravel's data/meta/links without checking the package's resources; mobile clients that hardcode the wrong keys are expensive to fix post-release. Assert the shape in a test on day one.

Debugging playbook. php artisan route:list --path=api for routing; curl -i for status and headers; log the ETag sent and received on both client and server during integration. When a "stale data" report lands, triage in order — client cache, proxy cache, origin. Give your on-call runbook a documented lever to disable ETag middleware mid-incident; not having that lever turns a cache bug into an outage.

Tell your consumers what 304 means. An integrator who treats 304 as an error, or who doesn't resend If-None-Match, gets none of the benefit and files bugs against you. One paragraph in the onboarding doc — cache the body, send the header, reuse on 304 — removes a recurring support ticket.

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.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route