Magento 2 API Setup: REST, GraphQL, Custom Endpoints

Integrations with external systems slow you down, and data exchange fails under load? We set up Magento 2 API turnkey: REST, GraphQL, and custom endpoints — with access policies and rate limits. We build the API layer so that data exchange time is reduced several times over, and integrations work predictably.

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Frequently Asked Questions

Why Magento 2 API slows down and returns errors under load

Magento 2 API is essentially a facade over the catalog, prices, stock, and orders: REST for synchronous operations, GraphQL for the storefront, custom endpoints for tasks that aren't in the core. While traffic is low, everything looks healthy.

Under load, integration bottlenecks that aren't visible in a calm mode begin to surface: API errors come in batches, responses stretch out, and some requests simply drop off on timeout.

The first thing worth checking is how the queries are structured. A collection with loaded relations for each product turns a single request into hundreds of database calls, and this is the first place where the load on the API goes into non-linear growth.

The second is caching: if catalog responses aren't cached at the API layer level, every call recalculates the same thing, even though the data hasn't changed.

The third is database locks: parallel writes for stock and orders begin to wait on each other, and instead of an error the client gets a hung request.

A separate category is limits on the integration side. An external system may throttle the request rate, and then Magento 2 API looks like the culprit, even though the problem is in how the queue and retries are set up.

We go through these four layers in order — queries, cache, locks, limits — and show how each one is closed at the level of configuration and code, rather than by "scaling up the server."

What a well-built API layer delivers for business and integrations

Response speed under load

A catalog with tens of thousands of items and a shopping cart at the peak of a sale means thousands of concurrent requests per second.

A well-built API layer responds in fractions of a second where a "raw" integration starts hitting limits and returning timeouts: heavy queries go to cache, repeated requests are not recalculated from scratch, and responses are delivered in a compact form.

The storefront, mobile app, and partner channels receive data simultaneously, without queues or "fluctuating" speed.

Stability of exchange with external systems

Integrations break not from load, but from unexpected responses: the warehouse returned an incomplete list, the payment service sent an error, the delivery service changed the format.

We build in retries with increasing backoff, isolation of a failing channel, and an exchange log that shows exactly where the data was lost.

One failed service stops dragging the others down with it — orders, stock, and statuses reach their destination, and discrepancies are resolved via the log rather than by searching blindly.

Fewer manual operations

Every exchange that used to be done by hand — exporting price lists, reconciling stock, transferring orders into the accounting system — is switched to automatic mode on a schedule or event.

An employee stops being a "bridge" between systems: data synchronizes itself, and a person gets involved only in disputed cases. This reduces the share of input errors and frees up the team's time for tasks that genuinely require a decision.

Readiness for new channels

When the API layer is described and stable, connecting a new channel — a marketplace, a partner storefront, a mobile client — stops being a separate project.

A new consumer gets the same proven access points with clear rules and limits, rather than assembling data "however it turns out." That is precisely why investment in an API pays off not on the first release, but on every subsequent connection.

REST, GraphQL, and custom endpoints: comparing approaches

The choice of exchange protocol is not a matter of taste, but a consequence of who accesses the data and how often.

A storefront, a mobile app, and an internal integration system place different demands on the same catalog: some need the full object with a dozen nested entities, others need three fields for a card in a list.

That is why in Magento 2 API we almost always combine modes rather than choosing one "correct" one.

Option When it fits Limitations
REST Exchange with accounting systems, exports to ERP, write operations: orders, stock, prices Redundant responses: it pulls the whole object even when only two fields are needed. The number of requests grows when assembling composite pages
GraphQL Storefront and mobile clients: fetching exactly the fields the screen needs Read-only. Complex queries without a depth limit hit the database hard; limits and caching are needed
Custom endpoints Non-standard logic: shipping calculation, personalized prices, aggregates from external services Require maintenance during platform updates and their own test coverage

Why REST remains for write operations

REST is predictable where transactionality matters: creating an order, deducting stock, syncing statuses. Each call is an atomic operation with a clear response code, easy to retry and log.

The limitation is redundancy: to assemble a product card, the client makes several requests, and on a slow network this is noticeable.

Where GraphQL wins

GraphQL returns to the client exactly the set of fields requested — one query instead of three or four, and the response size drops severalfold.

This is noticeable on mobile: the catalog page loads faster because it does not drag along descriptions and galleries that are not shown on the screen. The price is read-only access and the need to limit query depth, otherwise one careless client loads the database.

When a custom endpoint is justified

A custom endpoint is needed when the standard modes do not express the business logic: the price depends on the customer segment, shipping is calculated via an external service, an aggregate from several sources is needed.

Such an endpoint provides a clean contract, but becomes part of the codebase — it needs to be tested and verified with every platform update.

In practice, we lock down the exchange scheme before work begins: which clients, which operations, what expected volume. This eliminates half of the integration problems at the design stage.

How we configure Magento 2 API: stages of work

We start with an inventory: we collect all the points where external systems access the store — mobile app, ERP, warehouse, marketplaces, CRM.

For each one, we record exactly what it requests and how often, so we understand the real load profile rather than relying on assumptions.

  1. API audit. We review the current REST and GraphQL requests, looking for bottlenecks: uncached requests, "fetch everything at once" queries, duplicate calls, missing rate limiting. The output is an integration map marking what we reuse, what we rewrite, and what we decommission.
  2. Endpoint design. We determine where the standard REST is sufficient, where GraphQL will provide a single-query fetch instead of three, and where a custom endpoint is needed for a specific partner's logic. We fix the contracts: which fields, which response codes, how we return errors.
  3. Configuration and implementation. We set up role-based access rights, request rate limiting, and caching of heavy queries. We move custom endpoints into a separate module so that core updates don't overwrite them.
  4. Integration testing. We run scenarios on the test environment: correct responses, external system failures, repeated requests, peak loads. We separately verify that the store continues to accept orders when a partner is unavailable.
  5. API documentation. We describe each endpoint: purpose, parameters, request and response examples, error codes. We keep the documentation next to the code so it doesn't diverge from reality after edits.
  6. Handover and monitoring. We show the client's team how to read integration logs and where to look at failure metrics. We agree on a threshold beyond which we return for further refinement.

This order delivers a predictable result: integrations stop failing silently, and any new system is connected according to an already described contract, without rebuilding the logic from scratch.

Access policies, roles, and limits in the API

Permission separation in the Magento 2 API is built on integrations: each is issued its own key pair and a set of permissions from the resource tree.

The access token lives for a limited time, is renewed by a separate request, and binding to an integration allows access to be revoked in a targeted way — without reissuing keys for the other consumers.

This way the same API serves both the mobile app, the warehouse system, and the partner portal, without mixing up their permissions.

We describe roles through ACL resources, not through "admin/non-admin." The integration for the storefront cache gets catalog read-only, the integration for ERP gets write access to orders and stock, and analytics gets read access without the right to change data.

The principle of least privilege here is not a formality: if a key leaks, the damage is limited to one resource rather than the entire database.

We set request limits at three levels: at the perimeter — by IP and key, at the application level — by integration, and at the level of heavy queries — separately.

This protects against exhausting the connection pool to the database when one careless script takes down the storefront. We absorb burst traffic from sales with a queue rather than by denying service.

For GraphQL, we separately limit query depth and complexity — otherwise a single nested query ten levels deep selects the entire catalog. We log every call with the integration identifier so that an incident is investigated based on facts rather than guesses.

We work with Magento on the current branch — the mechanisms for ACL, tokens, and throttling are already there; they need to be configured correctly rather than reinvented on top.

Bottom line: access is granted per task, keys are revoked without downtime, and limits prevent one consumer from bringing down the service for everyone else.

What the client receives after API setup

After API setup, the client receives not a "working endpoint" but a package that allows the integration to be developed and maintained without the author. Below is what exactly is included in the handover.

  • API documentation — a description of all methods with request and response examples, error codes, and limits. A developer on the client's side or a new contractor can get up to speed using it without reading the source code.
  • Integration diagrams — which systems exchange data, in which direction, at what frequency, and what happens when one of the parties is unavailable. The diagram answers the question "why was the order sent to ERP twice" without having to pull logs manually.
  • Environment configurations — separate sets of parameters for the test and production environments, access keys, API role permissions. Test requests do not go to production systems, and keys are not stored in the code.
  • Support regulations — what is monitored, which errors are considered critical, to whom and how the signal is transmitted, who responds and within what timeframes. The on-call engineer sees the problem before the client notices it.
  • Instructions for the team — how to add a new method, change the response structure, roll back an unsuccessful change. Routine operations are performed step by step, without contacting us.
  • A set of automated tests — checks of key exchange scenarios that are run before every release. A change in the catalog or order placement does not silently break the integration.
  • Change log — what changed in the API contract and when, which versions are still supported, how to migrate to a new one. Updates on the client's side do not turn into a surprise for related systems.

We separately spell out the boundaries: which endpoints are public, which are protected by authorization, where rate limits apply. This removes most of the "why were we denied access" questions before the first inquiry.

Describe your task — we will get back to you with an estimate and a plan: which artifacts your specific environment needs and in what scope.

How does REST differ from GraphQL in the Magento 2 API?

REST in Magento 2 is a resource model: each entity type (product, category, order, customer) is available at its own address, and the selection is controlled by query parameters.

The response comes back in its entirety in the form the service layer returns it, so the client cannot ask for "just the name, price, and stock" — it gets the whole object and discards the excess on its side.

For single operations and "write/read" integrations, this is predictable and convenient: HTTP-level caching, clear response codes, simple debugging via a regular HTTP client.

GraphQL in Magento 2 solves a different problem — it is built around the needs of the storefront. The client describes in the query exactly the fields it needs and gets a single response instead of a chain of calls to multiple endpoints.

This is critical for storefronts built on React, Vue, and mobile apps, where time to first render and traffic volume matter.

The flip side is strict limitations: GraphQL in the core is oriented toward reading, some administrative and write operations are unavailable through it, and complex queries require depth and cost control, otherwise a single careless query lands on the database as a heavy scan.

Choosing an approach is not about "what is more modern" but about "what load profile." REST wins where bulk operations, integrations with accounting systems, exchange with external services, and administration are needed: it gives full access to the service layer and scales predictably by the number of workers.

GraphQL wins on the storefront: fewer network round trips, less channel congestion, flexible selection for a specific screen.

In practice, a hybrid works best — GraphQL for the storefront and mobile clients, REST for integrations and service scenarios, with a shared business logic layer beneath both.

Custom endpoints deserve separate mention.

When the standard routes are not enough — for example, you need aggregation of data from several sources or a specific business operation — we add our own route to the module and move the logic into the service layer rather than the controller.

Such an endpoint reuses existing repositories and does not duplicate rules, which means it does not diverge from the rest of the system when changes occur.

The decision on whether to extend REST, add a schema to GraphQL, or make a separate route is made based on the task, not on habit — both the storefront's speed and the cost of maintenance depend on it.

Case study: accelerating data exchange with external systems

What it was like before

The client — an online store on Magento 2 with data exchange between the warehouse, the accounting system, and the storefront.

The catalog and stock levels were synchronized by a nightly batch job: the export took several hours, and between runs the data on the storefront diverged from actual availability.

A customer would place an order for a product that was already out of stock, managers would manually remove the items, and some orders were canceled after the fact.

The second problem was worse — a whole class of errors. The standard REST endpoint returned the entire product object in full, including dozens of unused attributes and relations.

During a mass export, this put load on the database, caused timeouts, and produced "floating" failures: some requests timed out, and the exchange completed only partially.

Tracking exactly which items failed to come through was nearly impossible — the log recorded only the fact that a failure had occurred.

What we changed

We switched the exchange from batch to event-driven and rewrote the data access points.

Instead of one heavy REST request for the entire catalog, we built the selection through GraphQL: the client requests exactly the fields that the warehouse and the accounting system need — stock levels, prices, identifiers.

The volume of data transmitted per operation shrank severalfold, and the response time for a typical request dropped from several seconds to fractions of a second.

For non-standard scenarios — receiving deliveries and reconciling batches — we added custom endpoints with their own input validation. Every request now either passes in full or is rejected with a clear error, with no partially applied changes.

This eliminated the very class of "half-completed" exchanges: discrepancies that used to surface a day later no longer occur.

What it became

The exchange between systems now happens in real time rather than once a day: stock levels on the storefront match actual availability at the moment an order is placed.

Cancellations due to an out-of-stock product have practically disappeared, and manual item corrections by managers are no longer needed.

The load on the database during peak hours has decreased, because the heavy nightly exports and the unnecessary queries of unused fields are gone.

A separate result is the predictability of failures. Integration errors now come with the specific entity and cause indicated, rather than "the exchange failed." The on-duty engineer sees the problem before a customer notices it and fixes it in a targeted way.

Common technical concerns about the API

REST and GraphQL in Magento 2 coexist rather than replace each other: REST remains for administrative operations, integrations with accounting systems, and webhooks, while GraphQL is for the storefront, where it is important to retrieve a product, prices, stock, and content in a single request without a series of sequential calls.

Compatibility is ensured at the level of service contracts: as long as a module declares interfaces and does not break their signatures, both layers work on top of the same business logic, and adding a custom endpoint does not require rewriting existing ones.

We already use REST — will switching to GraphQL break our current integrations?

No, the layers do not conflict. GraphQL is connected as a separate transport on top of the same service contracts, while the old REST routes continue to respond.

We carry out the migration in stages: first the storefront scenarios, then the secondary ones, with both layers running in parallel and responses checked for data identity.

How do we determine that the API will withstand peak load?

We run load testing on a profile close to production: bulk catalog queries, checkout, stock synchronization.

We look not at the average response time, but at behavior at the 95th percentile and during failures of external services — that is exactly where unoptimized queries and locks show up. Based on the results, we add caching and rate limiting.

What should be done with integrations written by a developer who is not ours?

We start with an inventory: which endpoints are called, at what frequency, which fields are read and written. Then we lock down the contract with tests — that way, a change to internal logic does not silently break someone else's integration.

Support comes down to a set of rules: route versioning, call logging, and a clear rollback procedure in case of failure.

How do we roll back an unsuccessful API change?

Contracts are versioned, and old routes are kept for the transition period, so a rollback is a return to the previous version of the module without changes on the consumer side.

Before deployment, we run a set of compatibility checks so that the rollback is a deliberate decision rather than a reaction to an incident.

Let's discuss your API task

To make the estimate substantive rather than "give or take," we need a minimum of context: which systems consume the data, which operations are critical, and whether there are constraints on load and timelines.

With that, we'll review the current endpoints, schemas, and access rights and come back with a work plan where each stage is tied to a result.

  • Review of the current API: which REST and GraphQL requests are already in use, where calls are duplicated, and which endpoints slow down the storefront's response.
  • Integration schema: a map of consumers — mobile app, ERP, warehouse, marketplaces — and what data each of them pulls and how often.
  • Scope estimate: a list of endpoints to be modified or created, with priorities based on their impact on business processes.
  • Stage-by-stage work plan: contract design, implementation, tests, load testing, production rollout.
  • Access and security policy: tokens, roles, method restrictions, and request limits.
  • Rollback schema: how to revert to the previous contract version without downtime for consumers.
  • Documentation scope: endpoint descriptions, request and response examples, change management regulations.

Describe your task — which systems need to be connected and what's getting in the way right now — and we'll come back with an API estimate and a work plan. After that, we'll agree on the stages and get started.

Our competencies:

Latest works

  • B2B ADVANCE company website development
    B2B ADVANCE company website development
    1542
  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1393
  • Website development for BELFINGROUP
    Website development for BELFINGROUP
    1081
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1368
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1139
  • Website development for FIXPER company
    Website development for FIXPER company
    1060