Shopify API bindings for Node.js
npm install shopify-api-node[![Version npm][npm-shopify-api-node-badge]][npm-shopify-api-node]
[![Build Status][ci-shopify-api-node-badge]][ci-shopify-api-node]
[![Coverage Status][coverage-shopify-api-node-badge]][coverage-shopify-api-node]
Shopify API bindings for Node.js.
``shell`
$ npm install --save shopify-api-node
This module exports a constructor function which takes an options object.
Creates a new Shopify instance.
#### Arguments
- options - Required - A plain JavaScript object that contains the
configuration options.
#### Options
- shopName - Required - A string that specifies the shop name. The shop'sapiKey
"myshopify.com" domain is also accepted.
- - Required for [private][generate-private-app-credentials] apps - Apassword
string that specifies the API key of the app. This option must be used in
conjunction with the option and is mutually exclusive with theaccessToken
option.password
- - Required for [private][generate-private-app-credentials] apps - AapiKey
string that specifies the private app password. This option must be used in
conjunction with the option and is mutually exclusive with theaccessToken
option.accessToken
- - Required for public apps - A string representing the permanentapiKey
[OAuth 2.0][oauth] access token. This option is mutually exclusive with the
and password options. If you are looking for a premade solution toagent
obtain an access token, take a look at the [shopify-token][] module.
- - Optional - An object that is passed as the agent option to got.apiVersion
This allows to use a proxy server. See
Got documentation
for more details.
- - Optional - A string to specify the [Shopify APIautoLimit
version][api-versioning] to use for requests. Defaults to the oldest supported
stable version.
- - Optional - This option allows you to regulate the request ratecalls
in order to avoid hitting the [rate limit][api-call-limit]. Requests are
limited using the token bucket algorithm. Accepted values are a boolean or a
plain JavaScript object. When using an object, the property and theinterval
property specify the refill rate and the bucketSize property the{ calls: 2, interval: 1000, bucketSize: 35 }
bucket size. For example true
specifies a limit of 2 requests per second with a burst of 35 requests. When
set to requests are limited as specified in the above example. Defaultsfalse
to . Mutually exclusive with the maxRetries option.hooks
- - Optional - A list of gotbeforeRetry
request hooks to
attach to all outgoing requests, like , afterResponse, etc.maxRetries
Hooks should be provided in the same format that Got expects them and will
receive the same arguments Got passes unchanged.
- - Optional - The number of times to attempt to make the request0
to Shopify before giving up. Defaults to , which means no automatic0
retries. If set to a value greater than , shopify-api-node will make upshopify-api-node
to that many retries. will respect the Retry-After headerautoLimit
for requests to the REST API, and the throttled cost data for requests to the
GraphQL API, and retry the request after that time has elapsed. Mutually
exclusive with the option.parseJson
- - Optional - The function used to parse JSON. The function isJSON.parse()
passed a single argument. This option allows the use of a custom JSON parser
that might be needed to properly handle long integer IDs. Defaults to
.presentmentPrices
- - Optional - Whether to include the header to pullfalse
presentment prices for products. Defaults to .stringifyJson
- - Optional - The function used to serialize to JSON. TheJSON.stringify()
function is passed a single argument. This option allows the use of a custom
JSON serializer that might be needed to properly handle long integer IDs.
Defaults to .timeout
- - Optional - The number of milliseconds before the request timestimeout
out. If the request takes longer than , it will be aborted. Defaults60000
to , or 1 minute.
#### Return value
A Shopify instance.
#### Exceptions
Throws an Error exception if the required options are missing.
#### Example
`js
const Shopify = require('shopify-api-node');
const shopify = new Shopify({
shopName: 'your-shop-name',
apiKey: 'your-api-key',
password: 'your-app-password'
});
`
The callLimits property allows you to monitor the API call limit. The value is
an object like this:
`js`
{
remaining: 30,
current: 10,
max: 40
}
Values start at undefined and are updated every time a request is made. AftercallLimits
every update the event is emitted with the updated limits as
argument.
`js`
shopify.on('callLimits', (limits) => console.log(limits));
When using the GraphQL API, a different property is used to track the API call
limit: callGraphqlLimits.
Keep in mind that the autoLimit option is ignored while using GraphQL API.
`js`
shopify.on('callGraphqlLimits', (limits) => console.log(limits));
Every resource is accessed via your shopify instance:
`js
const shopify = new Shopify({
shopName: 'your-shop-name',
accessToken: 'your-oauth-token'
});
// shopify.
`
Each method returns a Promise that resolves with the result:
`js`
shopify.order
.list({ limit: 5 })
.then((orders) => console.log(orders))
.catch((err) => console.error(err));
The Shopify API requires that you send a valid JSON string in the request body
including the name of the resource. For example, the request body to create a
country should be:
`json`
{
"country": {
"code": "FR",
"tax": 0.25
}
}
When using shopify-api-node you don't have to specify the full object but only
the nested one as the module automatically wraps the provided data. Using the
above example this translates to:
`js`
shopify.country
.create({ code: 'FR', tax: 0.25 })
.then((country) => console.log(country))
.catch((err) => console.error(err));
Similarly, the Shopify API includes the resource name in the JSON string that is
returned in the response body:
`json`
{
"country": {
"id": 1070231510,
"name": "France",
"tax": 0.2,
"code": "FR",
"tax_name": "TVA",
"provinces": []
}
}
shopify-api-node automatically unwraps the parsed object and returns:
`js`
{
id: 1070231510,
name: 'France',
tax: 0.2,
code: 'FR',
tax_name: 'TVA',
provinces: []
}
This behavior is valid for all resources.
Shopify allows for adding metafields to various resources. You can use the
owner_resource and owner_id properties to work with metafields that belong
to a particular resource as shown in the examples below.
Get metafields that belong to a product:
`js`
shopify.metafield
.list({
metafield: { owner_resource: 'product', owner_id: 632910392 }
})
.then(
(metafields) => console.log(metafields),
(err) => console.error(err)
);
Create a new metafield for a product:
`js`
shopify.metafield
.create({
key: 'warehouse',
value: 25,
type: 'integer',
namespace: 'inventory',
owner_resource: 'product',
owner_id: 632910392
})
.then(
(metafield) => console.log(metafield),
(err) => console.error(err)
);
[Pagination][paginated-rest-results] in API version 2019-07 and above can be
done as shown in the following example:
`js
(async () => {
let params = { limit: 10 };
do {
const products = await shopify.product.list(params);
console.log(products);
params = products.nextPageParameters;
} while (params !== undefined);
})().catch(console.error);
`
Each set of results may have the nextPageParameters andpreviousPageParameters properties. These properties specify respectively the
parameters needed to fetch the next and previous page of results.
This feature is only available on version 2.24.0 and above.
shopify-api-node has two optional mechanisms for avoiding requests failing429 Rate Limit Exceeded
with errors from Shopify.
The autoLimit option implements a client side leaky bucket algorithm forautoLimit
delaying requests until Shopify is likely to accept them. When isShopify
on, each instance will track how many requests have been made, andautoLimit
delay sending subsequent requests if the rate limit has been exceeded. is very efficient because it almost entirely avoids sending requestsShopify
which will return 429 errors, but, it does not coordinate between multiple instances or across multiple processes. If you're usingshopify-api-node in many different processes, autoLimit will not correctly
avoid 429 errors.
The maxRetries option implements a retry based strategy for getting requestsRetry-After
to Shopify, where when a 429 error occurs, the request is automatically retried
after waiting. Shopify usually replies with a header indicating toshopify-api-node
the client when the rate limit is available, and so will waitshopify-api-node
that long before retrying. If you are using in many differentRetry-After
processes, they will all be competing to use the same rate limit shopify
enforces, so there is no guarantee that retrying after the headermaxRetries
delay will work. It is recommended to set to a high value like 10
if you are making many concurrent requests in many processes to ensure each
request is retried for long enough to succeed.
autoLimit and maxRetries can't be used simultaneously. Both are off by
default.
- accessScope
- list()delete()
- apiPermission
- activate(id[, params])
- applicationCharge
- create(params)
- get(id[, params])
- list([params])
- create(params)
- applicationCredit
- get(id[, params])
- list([params])
- authors()
- article
- count(blogId[, params])
- create(blogId, params)
- delete(blogId, id)
- get(blogId, id[, params])
- list(blogId[, params])
- tags([blogId][, params])
- update(blogId, id, params)
- create(themeId, params)
- asset
- delete(themeId, params)
- get(themeId, params)
- list(themeId[, params])
- update(themeId, params)
- list()
- balance
- transactions([params])
- count()
- blog
- create(params)
- delete(id)
- get(id[, params])
- list([params])
- update(id, params)
- accept(fulfillmentOrderId[, message])
- cancellationRequest
- create(fulfillmentOrderId[, message])
- reject(fulfillmentOrderId[, message])
- create(params)
- carrierService
- delete(id)
- get(id)
- list()
- update(id, params)
- complete(token)
- checkout
- count([params])
- create(params)
- get(token)
- list([params])
- shippingRates(token)
- update(token, params)
- count([params])
- collect
- create(params)
- delete(id)
- get(id[, params])
- list([params])
- get(id[, params])
- collection
- products(id[, params])
- get(id)
- collectionListing
- list([params])
- productIds(id[, params])
- approve(id)
- comment
- count([params])
- create(params)
- get(id[, params])
- list([params])
- notSpam(id)
- remove(id)
- restore(id)
- spam(id)
- update(id, params)
- count()
- country
- create(params)
- delete(id)
- get(id[, params])
- list([params])
- update(id, params)
- list()
- currency
- count([params])
- customCollection
- create(params)
- delete(id)
- get(id[, params])
- list([params])
- update(id, params)
- accountActivationUrl(id)
- customer
- count([params])
- create(params)
- delete(id)
- get(id[, params])
- list([params])
- orders(id[, params])
- search(params)
- sendInvite(id[, params])
- update(id, params)
- create(customerId, params)
- customerAddress
- default(customerId, id)
- delete(customerId, id)
- get(customerId, id)
- list(customerId[, params])
- set(customerId, params)
- update(customerId, id, params)
- count([params])
- customerSavedSearch
- create(params)
- customers(id[, params])
- delete(id)
- get(id[, params])
- list([params])
- update(id, params)
- list()
- deprecatedApiCall
- create(priceRuleId, params)
- discountCode
- delete(priceRuleId, id)
- get(priceRuleId, id)
- list(priceRuleId)
- lookup(params)
- update(priceRuleId, id, params)
- create(priceRuleId, params)
- discountCodeCreationJob
- discountCodes(priceRuleId, id)
- get(priceRuleId, id)
- get(id)
- dispute
- list([params])
- get(disputeId)
- disputeEvidence
- update(disputeId, params)
- create(disputeId, params)
- disputeFileUpload
- delete(disputeId, id)
- complete(id[, params])
- draftOrder
- count()
- create(params)
- delete(id)
- get(id[, params])
- list([params])
- sendInvoice(id[, params])
- update(id, params)
- count([params])
- event
- get(id[, params])
- list([params])
- cancel(orderId, id)
- fulfillment
- cancelV2(id)
- complete(orderId, id)
- count(orderId[, params)
- create(orderId, params)
- createV2(params)
- get(orderId, id[, params])
- list(orderId[, params])
- open(orderId, id)
- update(orderId, id, params)
- updateTracking(id, params)
- create(orderId, fulfillmentId, params)
- fulfillmentEvent
- delete(orderId, fulfillmentId, id)
- get(orderId, fulfillmentId, id)
- list(orderId, fulfillmentId[, params])
- update(orderId, fulfillmentId, id, params)
- cancel(id)
- fulfillmentOrder
- close(id[, message])
- fulfillments(id)
- get(id)
- hold(id, params)
- list([params])
- locationsForMove(id)
- move(id, locationId)
- releaseHold(id)
- reschedule(id, deadline)
- setFulfillmentOrdersDeadline(params)
- accept(fulfillmentOrderId[, message])
- fulfillmentRequest
- create(fulfillmentOrderId, params)
- reject(fulfillmentOrderId[, message])
- create(params)
- fulfillmentService
- delete(id)
- get(id)
- list([params])
- update(id, params)
- count([params])
- giftCard
- create(params)
- disable(id)
- get(id)
- list([params])
- search(params)
- update(id, params)
- create(giftCardId, params)
- giftCardAdjustment
- get(giftCardId, id)
- list(giftCardId)
- get(id)
- inventoryItem
- list(params)
- update(id, params)
- adjust(params)
- inventoryLevel
- connect(params)
- delete(params)
- list(params)
- set(params)
- count
- location
- get(id)
- inventoryLevels(id[, params])
- list()
- count()
- marketingEvent
- create(params)
- delete(id)
- get(id)
- list([params])
- update(id, params)
- engagements(id, params)
- count([params])
- metafield
- create(params)
- delete(id)
- get(id[, params])
- list([params])
- update(id, params)
- cancel(id[, params])
- order
- close(id)
- count([params])
- create(params)
- delete(id)
- fulfillmentOrders(id)
- get(id[, params])
- list([params])
- open(id)
- update(id, params)
- create(orderId, params)
- orderRisk
- delete(orderId, id)
- get(orderId, id)
- list(orderId)
- update(orderId, id, params)
- count([params])
- page
- create(params)
- delete(id)
- get(id[, params])
- list([params])
- update(id, params)
- count(checkoutToken)
- payment
- create(checkoutToken, params)
- get(checkoutToken, id)
- list(checkoutToken)
- get(id)
- payout
- list([params])
- list([params])
- policy
- create(params)
- priceRule
- delete(id)
- get(id)
- list([params])
- update(id, params)
- count([params])
- product
- create(params)
- delete(id)
- get(id[, params])
- list([params])
- update(id, params)
- count(productId[, params])
- productImage
- create(productId, params)
- delete(productId, id)
- get(productId, id[, params])
- list(productId[, params])
- update(productId, id, params)
- count()
- productListing
- create(productId[, params])
- delete(productId)
- get(productId)
- list([params])
- productIds([params])
- create(productId[, params])
- productResourceFeedback
- list(productId)
- count(productId)
- productVariant
- create(productId, params)
- delete(productId, id)
- get(id[, params])
- list(productId[, params])
- update(id, params)
- count(countryId[, params])
- province
- get(countryId, id[, params])
- list(countryId[, params])
- update(countryId, id, params)
- activate(id, params)
- recurringApplicationCharge
- create(params)
- delete(id)
- get(id[, params])
- list([params])
- customize(id, params)
- count([params])
- redirect
- create(params)
- delete(id)
- get(id[, params])
- list([params])
- update(id, params)
- calculate(orderId, params)
- refund
- create(orderId, params)
- get(orderId, id[, params])
- list(orderId[, params])
- create(params)
- report
- delete(id)
- get(id[, params])
- list([params])
- update(id, params)
- create(params)
- resourceFeedback
- list()
- count([params])
- scriptTag
- create(params)
- delete(id)
- get(id[, params])
- list([params])
- update(id, params)
- list([params])
- shippingZone
- get([params])
- shop
- count([params])
- smartCollection
- create(params)
- delete(id)
- get(id[, params])
- list([params])
- order(id, params)
- products(id[, params])
- update(id, params)
- create(params)
- storefrontAccessToken
- delete(id)
- list()
- list([params])
- tenderTransaction
- create(params)
- theme
- delete(id)
- get(id[, params])
- list([params])
- update(id, params)
- count(orderId)
- transaction
- create(orderId, params)
- get(orderId, id[, params])
- list(orderId[, params])
- create(recurringApplicationChargeId, params)
- usageCharge
- get(recurringApplicationChargeId, id[, params])
- list(recurringApplicationChargeId[, params])
- current()
- user
- get(id)
- list()
- count([params])
- webhook
- create(params)
- delete(id)
- get(id[, params])
- list([params])
- update(id, params)
-
where params is a plain JavaScript object. See the [Rest Admin API
reference][reading-api-docs] for parameters details.
The shopify instance also allows to use the GraphQL API through the graphql
method, which returns a promise that resolves with the result data:
`js
const shopify = new Shopify({
shopName: 'your-shop-name',
accessToken: 'your-oauth-token'
});
const query = {
customers(first: 5) {
edges {
node {
displayName
totalSpent
}
}
}
};
shopify
.graphql(query)
.then((customers) => console.log(customers))
.catch((err) => console.error(err));
`
shopify-api-node supports being passed hooks which are called by got (the
underlying HTTP library) during the request lifecycle.
For example, we can log every error that is encountered when using the
maxRetries option:
`jsbeforeRetry
const shopify = new Shopify({
shopName: 'your-shop-name',
accessToken: 'your-oauth-token',
maxRetries: 3,
// Pass the hook down to Got.`
hooks: {
beforeRetry: [(options, error, retryCount) => console.error(error)]
}
});
For more information on the available got hooks, see thegot` v11 hooks documentation.
- [Talking To Other Masters][talking-to-other-masters]
- [Reading API Docs][reading-api-docs]
- [Learning from others][learning-from-others]
[Polaris][polaris]
(add yours!)
- [Sample Node Express app by Shopify][sample-node-express-app-by-shopify]
- [Youtube Traffic][youtube-traffic]
- [Shipatron][shipatron]
- [UPC Code Manager][upc-code-manager]
- [Shopify Passwordless Login][dimension-software]
[MONEI][monei]
[sample-node-express-app-by-shopify]:
https://github.com/Shopify/shopify-node-app
[npm-shopify-api-node-badge]: https://img.shields.io/npm/v/shopify-api-node.svg
[npm-shopify-api-node]: https://www.npmjs.com/package/shopify-api-node
[ci-shopify-api-node-badge]:
https://img.shields.io/github/actions/workflow/status/MONEI/Shopify-api-node/ci.yml?branch=master&label=CI
[ci-shopify-api-node]:
https://github.com/MONEI/Shopify-api-node/actions?query=workflow%3ACI+branch%3Amaster
[coverage-shopify-api-node-badge]:
https://img.shields.io/coveralls/MONEI/Shopify-api-node/master.svg
[coverage-shopify-api-node]: https://coveralls.io/github/MONEI/Shopify-api-node
[generate-private-app-credentials]:
https://shopify.dev/apps/auth/basic-http#step-2-generate-api-credentials
[oauth]: https://shopify.dev/apps/auth/oauth
[shopify-token]: https://github.com/lpinca/shopify-token
[api-call-limit]: https://shopify.dev/api/usage/rate-limits
[api-versioning]: https://shopify.dev/api/usage/versioning
[talking-to-other-masters]: https://community.shopify.com/
[reading-api-docs]: https://shopify.dev/api/admin-rest
[learning-from-others]: https://stackoverflow.com/questions/tagged/shopify
[paginated-rest-results]: https://shopify.dev/api/usage/pagination-rest
[polaris]: https://polaris.shopify.com/?ref=microapps
[monei]:
https://monei.com/?utm_source=shopify-api-node-module-repo-readme&utm_medium=click&utm_campaign=github
[youtube-traffic]: https://apps.shopify.com/youtube-traffic?ref=microapps
[shipatron]: https://shipatron.io
[upc-code-manager]: https://apps.shopify.com/upc-code-manager-1
[dimension-software]: https://login.dimensionsoftware.com