Migrate to GraphQL from REST
When you begin using GraphQL, you need to change how you think about retrieving and working with data. This guide describes some of the key considerations when migrating from REST to GraphQL. It's meant for app developers who are primarily using REST in their apps.
Finding GraphQL objects and operations
Anchor link to section titled "Finding GraphQL objects and operations"Many REST Admin API resources and endpoints have a direct equivalent in GraphQL. Most GET
, PUT
, POST
and DELETE
requests in REST have an equivalent query or mutation in GraphQL.
However, some REST resources and operations might not have an exact GraphQL equivalent. This is because Shopify GraphQL APIs are built to leverage the efficiencies of GraphQL, newer platform features are exposed only in GraphQL, and some enhancements to the Shopify data model are reflected in only the GraphQL schema. The functionality included in one REST POST
, PUT
, or DELETE
operation is often split between multiple GraphQL mutations.
You can explore the GraphQL Admin API reference and build your mutations using the GraphiQL explorer to identify which mutation is appropriate for your use case.
Example: Direct equivalent in GraphQL
Anchor link to section titled "Example: Direct equivalent in GraphQL"Retrieving information about a single customer is very similar in REST and GraphQL.
In this example, the GraphQL query retrieves all of the same information as is returned in the REST GET request. However, some of the field names and data structures are slightly different from their REST equivalents.
Example: REST functionality split in GraphQL
Anchor link to section titled "Example: REST functionality split in GraphQL"In the following example, using REST you can use the generic product update request to delete an image from a product. This functionality isn't included in the GraphQL Admin API’s productUpdate
mutation. Instead, to delete images, you need to use the productDeleteMedia
mutation.
Finding required access scopes
Anchor link to section titled "Finding required access scopes"After you've found an equivalent GraphQL object, you'll need to determine if your app has the appropriate access scopes to work with the object and its associated queries and mutations. Access scopes are defined at the top of the page for each type in the GraphQL Admin API reference.
You can check your app’s granted access scopes using the appInstallation
query in the GraphQL Admin API.
Translating IDs from REST to GraphQL
Anchor link to section titled "Translating IDs from REST to GraphQL"REST and GraphQL use different formats for resource and object IDs. If you use stored IDs to retrieve resources in the REST Admin API, then you need to retrieve and store the equivalent GraphQL API global ID (GID) before you can run the corresponding queries and mutations in GraphQL APIs.
Most REST responses include the admin_graphql_api_id
property. You can use the ID in this property to directly query the equivalent object in GraphQL.
You can also view some common examples of GraphQL GIDs in our GID documentation.
Example: Retrieve a GraphQL object ID from REST
Anchor link to section titled "Example: Retrieve a GraphQL object ID from REST"The following example retrieves a product variant ID in REST, and then uses the admin_graphql_api_id
property to query the equivalent product variant ID in GraphQL.
Resources that don't return an Admin GraphQL API ID
Anchor link to section titled "Resources that don't return an Admin GraphQL API ID"In some cases, a resource might not return an admin_graphql_api_id
. This ID might not be available for several reasons. For example, a resource might not have an exact equivalent GraphQL object. In this case, you can determine the appropriate object to use, and then use examples in the GraphQL Admin API reference or query the object in the GraphiQL explorer to learn about the ID format.
Anatomy of a GraphQL ID
Anchor link to section titled "Anatomy of a GraphQL ID"GraphQL ID generation is implementation dependent, and doesn't follow any convention other than being a URI. There is no guarantee that GraphQL IDs will follow the structure gid://shopify/{resource}/{rest_id}
as in the previous example, so you shouldn't generate IDs programmatically. Always treat the admin_graphql_api_id
string as an opaque ID.
The following example shows how the admin_graphql_api_id
property doesn't always follow an expected structure:
Implementing and updating pagination
Anchor link to section titled "Implementing and updating pagination"In REST, you can paginate data using query parameters. Using the limit
parameter, you can split the total number of entries into manageable groups:
To get the next page of results, you can make a request to the URL stored in the Link
header of the last response:
In GraphQL, you can apply similar concepts using cursor-based pagination. When querying a connection in GraphQL, you need to provide the first
or last
argument, which specifies the number of items that you want returned from the beginning or the end of the set. This is equivalent to the limit
parameter in REST.
You can query the cursor
field to get a reference to the position of a node in a connection, and use that reference to obtain the next set of items. The cursor
field in GraphQL is equivalent to the page_info
parameter in REST.
You can also query the pageInfo
object in GraphQL to determine if there are any more pages to request. The fields hasNextPage
and hasPreviousPage
are boolean fields that indicate whether you can paginate forwards or backwards. Depending on the direction that you're paging in, you can use the relevant field to determine when you've reached the end of the list. For example, if you're paginating forward using the first
argument, then you've reached the end of the list when hasNextPage
is false
.
You can retrieve up to 250 resources in a single request. If you need to retrieve larger volumes of data, then you can perform a bulk query operation. A bulk query operation lets you asynchronously fetch all of the items in a list using as little as one query, avoiding the need to paginate results and the risk of your requests being throttled.
The following example shows how to query the first three products and determine whether you can paginate forward. The JSON response returns the product IDs, titles, and cursor IDs, and indicates that you can paginate forward.
You can provide the after
argument with the last cursor from the response to request the next set of data:
Understanding error handling
Anchor link to section titled "Understanding error handling"In GraphQL, you can't always rely on HTTP status codes to determine whether a query or mutation completed without errors. In cases that would typically produce 4xx
or 5xx
errors in REST, GraphQL might return a 200 OK
status with additional error information in its response.
The 4xx
and 5xx
errors occur infrequently. They're often related to network communications, your account, or an issue with Shopify’s services.
To learn about the possible response codes and what they mean, refer to Shopify API response status and error codes.
Query errors
Anchor link to section titled "Query errors"If a query results in an error, then an errors
object is returned. The object contains additional detail that can help you debug your operation.
Mutation errors
Anchor link to section titled "Mutation errors"The response for mutations also can return additional detail to help debug your mutation. To access this information, you must request the userErrors
field.
Updating your error handling
Anchor link to section titled "Updating your error handling"The following is a basic JavaScript example of how you might handle an error in REST, and how your error handling might be updated to parse errors returned in GraphQL responses with a status of 200 OK.
Understanding rate limiting
Anchor link to section titled "Understanding rate limiting"To ensure the Shopify platform remains stable and fair for everyone, both the REST and GraphQL Admin APIs are rate-limited. However, these two APIs use a different rate limiting approach.
The REST Admin API is governed by request-based limits. It provides credits that clients spend every time they make a request, and those credits are refilled every second. This allows clients to keep a request pace that never limits the API usage (two requests for each second) and makes occasional request bursts when needed (making 10 requests for each second).
However, the request-based model has the following limitations:
- Clients use the same amount of credits regardless, even if they don’t need all the data in an API response.
POST
,PUT
,PATCH
andDELETE
requests produce side effects that demand more load on servers thanGET
requests, which only reads existing data. Despite the difference in resource usage, all these requests consume the same amount of credits in the request-based model.
GraphQL addresses some limitations of common methods that are typically used in REST APIs.
The GraphQL Admin API uses a calculated cost query method for rate limiting. By default, in a calculated query cost method, clients receive 50 points per second up to a limit of 1,000 points.
The main difference from the REST request-based model is that every GraphQL request has a different cost.
Calculating costs
Anchor link to section titled "Calculating costs"The best way to determine the true cost of a query or mutation is to run it. In the following mutation example that creates a metaobject, the JSON response includes information about the total mutation cost and the client’s current quota under the extensions field. You can include an Shopify-GraphQL-Cost-Debug=1
header to receive a more detailed breakdown of the query or mutation cost.
You can use the currentlyAvailable
and restoreRate
fields returned in the throttleStatus
object to understand how many points you have available and how quickly they'll refill. This also helps you to adjust if a client has a different bucket size or restore rate, or if the global allocation changes in future.
Throttled requests
Anchor link to section titled "Throttled requests"In REST, if an app reaches an API rate limit, then it receives a 429 Too Many Requests
response and a message that a throttle has been applied.
In GraphQL, if an app reaches an API rate limit, then it receives a 200 OK
response, but the response body contains an error with a message that a throttle has been applied. You can handle for these throttled requests the same way that you handle for other errors returned by GraphQL.
Optimizing your requests
Anchor link to section titled "Optimizing your requests"Depending on your use case, you might be able to further optimize your GraphQL requests. Optimizing requests improves the performance of your app by reducing the number of calls that need to be made to the GraphQL endpoint, and helps you to avoid being throttled by sending fewer queries or queries with a lower cost.
You can investigate the following optimization opportunities:
- Combine multiple REST requests into a single GraphQL query: Retrieve all of the information about a single object in a single request, rather than chaining multiple requests together.
- Request only the data that you need: Simplify your queries and mutations by requesting only information that your app is using.
- Use the best mutation: Avoid round trips and chaining by using a mutation that's tailored to your use case.
- Use bulk operations: Fetch or upload data in bulk to make working with large volumes of data easier.
Combine multiple REST requests into a single GraphQL query
Anchor link to section titled "Combine multiple REST requests into a single GraphQL query"In GraphQL, you can use connections to get information about related objects with a single request.
For example, in the case of an order, you might want to know the total price, the customer's name, metafields, and the title of other variants belonging to the product in the order.
Using REST, you need to make a request to the following endpoints and filter out unnecessary data:
/orders/{order_id}.json
/products/{product_id}/variants.json
/customers/{customer_id}/metafields.json
Using GraphQL, you can make a single request using connections to get the desired data:
Request only the data you need
Anchor link to section titled "Request only the data you need"To avoid over-fetching, request only the fields that your app is using in your queries and mutations. This reduces the payload size, reducing bandwidth usage and improving performance.
For example, when you request a customer using REST, the response contains over 60 fields:
If you only need to retrieve customer contact and address information, then you can build your query to retrieve only this information:
Use the best mutation
Anchor link to section titled "Use the best mutation"In some cases, you can lessen the number of calls that you need to make by choosing a mutation that's tailored for your use case.
For example, if you wanted to make a copy of a product using a new name, then you could query for the product to be duplicated using a product
query, edit the product fields, and then create a new product using a productCreate
mutation. However, the GraphQL Admin API provides a productDuplicate
mutation, which allows you to duplicate the product and update key information including the title and status, avoiding a round trip and lessening the amount of data that needs to be sent to and retrieved from Shopify.
If you don't need to use the duplicated product right away, then you also have the option to use productDuplicateAsyncV2
to duplicate the product asynchronously.
Use bulk operations
Anchor link to section titled "Use bulk operations"If you need to import or export large volumes of data, then you can perform a bulk operation. Bulk operations lessen complexity by reducing the number of requests that you need to make, avoiding throttling and considerations such as pagination.
For example, if you retrieved all products in REST from the /products.json
endpoint, then you can instead use bulkOperationRunQuery
.
Understanding library support
Anchor link to section titled "Understanding library support"Many API client libraries that you might use to call the Shopify Admin API support both REST and GraphQL.
- Official Shopify API libraries:
- Fetch API / Node Fetch
- Axios
- Some third-party Admin API libraries
However, you need to make updates to your code that uses these libraries. You might have to perform some or all of the following tasks:
- Switching from a REST client to a GraphQL client
- Changing the API endpoint
- Updating the request type
- Adding your query or mutation and specifying the fields to return
- Destructuring or digging into the response
For examples of updating your implementation using some commonly used libraries, refer to Updating API calls in your app.
Learn how to use GraphQL APIs by following our how-to guides that cover different use cases: