Once OAuth is complete, we can use ShopifyAPI
's REST library to make authenticated API calls to the Shopify Admin API.
Every API request requires a valid ShopifyAPI::Auth::Session.
To instantiate a session, we recommend you either use the shopify_app
if working in Rails, or refer to our OAuth docs on constructing a session:
- "Custom Apps" - documentation on how to create Session from a custom app API token.
- "Performing OAuth" - documentation on how to create new sessions
- [ShopifyApp] - "Session" - documentation on session handling if you're using the
ShopifyApp
gem.
-
- Resource classes with similar syntax as
ActiveResource
, and follows our REST convention. Example:
# Update product title product = ShopifyAPI::Product.find(id: <product_id>) product.title = "My awesome product" product.save!
- Resource classes with similar syntax as
-
- More manual input method to make the API call. Example:
# Create a new client. rest_client = ShopifyAPI::Clients::Rest::Admin.new # Update product title body = { product: { title: "My cool product" } } # Use `client.put` to send your request to the specified Shopify Admin REST API endpoint. rest_client.put(path: "products/<id>.json", body: body)
We provide a templated class library to access REST resources similar to ActiveResource
. Format of the methods closely resemble our REST API schema.
The version of REST resource that's loaded and used is set from ShopifyAPI::Context.setup
Create an instance of the REST resource you'd like to use and optionally provide the following parameters.
Parameter | Type | Notes |
---|---|---|
session |
ShopifyAPI::Auth::Session |
Default value is nil . When nil is passed in, active session information is inferred from ShopifyAPI::Context.active_session . To set active session, use ShopifyAPI::Context.activate_session . This is handled automatically behind the scenes if you use ShopifyApp's session controllers. |
from_hash |
Hash |
Default value is nil . Sets the resource properties to the values provided from the hash. |
Examples:
# To construct an Orders object using default session
# This creates a new order object with properties provided from the hash
order = ShopifyAPI::Orders.new(from_hash: {property: value})
order.save!
Typical methods provided for each resources are:
find
delete
all
count
Full list of methods can be found on each of the resource class.
- Path:
- Example for
Order
resource on2024-01
version:
The save
or save!
method on a resource allows you to create
or update
that resource.
To create a new resource using the save
or save!
method, you can initialize the resource with a hash of values or simply assigning them manually. For example:
# Create a new product from hash
product_properties = {
title: "My awesome product"
}
product = ShopifyAPI::Product.new(from_hash: product_properties)
product.save!
# Create a new product manually
product = ShopifyAPI::Product.new
product.title = "Another one"
product.save!
To update an existing resource using the save
or save!
method, you'll need to fetch the resource from Shopify first. Then, you can manually assign new values to the resource before calling save
or save!
. For example:
# Update a product's title
product = ShopifyAPI::Product.find(id: product_id)
product.title = "My new title"
product.save!
# Remove a line item from a draft order
draft_order = ShopifyAPI::DraftOrder.find(id: draft_order_id)
new_line_items = draft_order.line_items.reject { |line_item| line_item["id"] == 12345 }
draft_order.line_items = new_line_items
draft_order.save!
Important
If you need to unset an existing value,
please explicitly set that attribute to nil
or empty values such as []
or {}
. For example:
# Removes shipping address from draft_order
draft_order.shipping_address = {}
draft_order.save!
This is because only modified values are sent to the API, so if shipping_address
is not "modified" to {}
. It won't be part of the PUT request payload
When updating a resource, only the modified attributes, the resource's primary key, and required parameters are sent to the API. The primary key is usually the id
attribute of the resource, but it can vary if the primary_key
method is overwritten in the resource's class. The required parameters are identified using the path parameters of the PUT
endpoint of the resource.
You can add custom headers to the HTTP calls made by methods like find
, delete
, all
, count
by setting the headers
attribute on the ShopifyAPI::Rest::Base
class in an initializer, like so:
ShopifyAPI::Rest::Base.headers = { "X-Custom-Header" => "Custom Value" }
# `find` will call the API endpoint with the custom header
ShopifyAPI::Customer.find(id: customer_id)
# Find and update a customer email
customer = ShopifyAPI::Customer.find(id: customer_id)
customer.email = "[email protected]"
customer.save!
# Get all orders
orders = ShopifyAPI::Orders.all
# Retrieve a specific fulfillment order
fulfillment_order_id = 123456789
fulfillment_order = ShopifyAPI::FulfillmentOrder.find(id: fulfillment_order_id)
# Remove an existing product image
product_id = 1234567
image_id = 1233211234567
ShopifyAPI::Image.delete(product_id: product_id, id: image_id)
More examples can be found in each resource's documentation on shopify.dev, e.g.:
Create an instance of ShopifyAPI::Clients::Rest::Admin
using the current session to make requests to the Admin API.
Parameter | Type | Notes |
---|---|---|
session |
ShopifyAPI::Auth::Session |
Default value is nil . When nil is passed in, active session information is inferred from ShopifyAPI::Context.active_session . To set active session, use ShopifyAPI::Context.activate_session . This is handled automatically behind the scenes if you use ShopifyApp's session controllers. |
api_version |
String |
Default value is nil . When nil is passed in, api version is inferred from ShopifyAPI::Context.setup . |
Examples:
# Create a default client with `ShopifyAPI::Context.api_version`
# and the active session from `ShopifyAPI::Context.active_session`
client = ShopifyAPI::Clients::Rest::Admin.new
# Create a client with a specific session "my_session"
client = ShopifyAPI::Clients::Rest::Admin.new(session: my_session)
# Create a client with active session from `ShopifyAPI::Context.active_session`
# and a specific api_version - "unstable"
client = ShopifyAPI::Clients::Rest::Admin.new(api_version: "unstable")
# Create a client with a specific session "my_session" and api_version "unstable"
client = ShopifyAPI::Clients::Rest::Admin.new(session: my_session, api_version: "unstable")
The ShopifyAPI::Clients::Rest::Admin
client offers the 4 core request methods:
get
delete
post
put
Each method can take the parameters outlined in the table below.
Parameter | Type | Required in Methods | Default Value | Notes |
---|---|---|---|---|
path |
String |
all | none | The requested API endpoint path. This can be one of two formats:
|
body |
Hash(any(Symbol, String), untyped) |
put , post |
none | The body of the request |
query |
Hash(any(Symbol, String), any(String, Integer, Float)) |
none | none | An optional query object to be appended to the request url as a query string |
extraHeaders |
Hash(any(Symbol, String), any(String, Integer, Float)) |
none | none | Any additional headers you want to send with your request |
tries |
Integer |
None | 1 |
The maximum number of times to try the request (must be >= 0) |
Note: These parameters can still be used in all methods regardless of if they are required.
If the request is successful these methods will all return a ShopifyAPI::Clients::HttpResponse
object, which has the following methods:
Methods | Type | Notes |
---|---|---|
code |
Integer |
HTTP Response code, e.g. 200 |
headers |
Hash{String, [String]} |
HTTP Response headers |
body |
Hash{String, Untyped} |
HTTP Response body |
prev_page_info |
String |
See Pagination |
next_page_info |
String |
See Pagination |
If the request has failed, an error will be raised describing what went wrong.
You can rescue ShopifyAPI::Errors::HttpResponseError
and output error messages with errors.full_messages
See example:
client = ShopifyAPI::Clients::Rest::Admin.new(session: session)
response = client.get(path: "NOT-REAL")
some_function(response.body)
rescue ShopifyAPI::Errors::HttpResponseError => e
puts fulfillment.errors.full_messages
# {"errors"=>"Not Found"}
# If you report this error, please include this id: bce76672-40c6-4047-b598-46208ab076f0.
# Create a new client.
client = ShopifyAPI::Clients::Rest::Admin.new(session: session)
# Use `client.get` to request the specified Shopify REST API endpoint, in this case `products`.
response = client.get(path: "products")
# Do something with the returned data
some_function(response.body)
For more information on the products
endpoint, check out our API reference guide.
# Create a new client.
client = ShopifyAPI::Clients::Rest::Admin.new(session: session)
# Build your post request body.
body = {
product: {
title: "Burton Custom Freestyle 151",
body_html: "\u003cstrong\u003eGood snowboard!\u003c\/strong\u003e",
vendor: "Burton",
product_type: "Snowboard",
}
}
# Use `client.post` to send your request to the specified Shopify Admin REST API endpoint.
# This POST request will create a new product.
client.post({
path: "products",
body: body,
});
For more information on the products
endpoint, check out our API reference guide.
# Create a new client.
client = ShopifyAPI::Clients::Rest::Admin.new
# Update product title
body = {
product: {
title: "My cool product"
}
}
# Use `client.put` to send your request to the specified Shopify Admin REST API endpoint.
# This will update product title for product with ID <id>
client.put(path: "products/<id>.json", body: body)
For more information on the products
endpoint, check out our API reference guide.
The REST resources have api_call_limit
and retry_after
can be found on the Resource class. These values correspond to the X-Shopify-Shop-Api-Call-Limit
and Retry-After
headers respectively.
product = ShopifyAPI::Product.find(session: session, id: 12345)
# X-Shopify-Shop-Api-Call-Limit: 32/40
request_count = ShopifyAPI::Product.api_call_limit[:request_count] # 32
bucket_size = ShopifyAPI::Product.api_call_limit[:bucket_size] # 40
retry_after = ShopifyAPI::Product.retry_request_after
This library also supports cursor-based pagination for REST Admin API requests. Learn more about REST request pagination.
After making a request, the next_page_info
and prev_page_info
can be found on the response object and passed as the page_info
query param in other requests.
An example of this is shown below:
client = ShopifyAPI::Clients::Rest::Admin.new(session: session)
response = client.get(path: "products", query: { limit: 10 })
next_page_info = response.next_page_info
if next_page_info
next_page_response =client.get(path: "products", query: { limit: 10, page_info: next_page_info })
some_function(next_page_response)
end
Similarly, when using REST resources the next_page_info
and prev_page_info
can be found on the Resource class and passed as the page_info
query param in other requests.
An example of this is shown below:
products = ShopifyAPI::Product.all(session: session, limit: 10)
loop do
some_function(products)
break unless ShopifyAPI::Product.next_page?
products = ShopifyAPI::Product.all(session: session, limit: 10, page_info: ShopifyAPI::Product.next_page_info)
end