Shopify's Ajax API

Shopify provides shop-owners with an Ajax API that returns JSON-encoded responses.

This Ajax API makes it possible to add items to the cart, update quantities in the cart, and fetch information about the cart, without a page refresh. With this API, you can also fetch information about a particular product using its handle.

Wrapper library: use one or not

You can use a jQuery wrapper library to submit your requests to Shopify.

To use our own jQuery wrapper library, include it like so:

{{ '//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js' | script_tag }}
{{ 'api.jquery.js' | shopify_asset_url | script_tag }}

Information

Take note that you don't need a wrapper library at all when using our Ajax API with jQuery. The code you need to write is simple enough that you don't require an additional abstraction layer.

Laboratory page

If you're using the jQuery wrapper library, head over to the laboratory page at http://mayert-douglas4935.myshopify.com/pages/api. This page serves as documentation for our jQuery wrapper library.

Shopify Ajax API Reference

The following calls can be submitted via Ajax to your Shopify shop. Note that all URLs end with a .js extension. .js stands for JSON.

The coding examples provided below don't always use a callback for the sake of simplicity. It goes without saying that you'll almost always need to update the page (or do something, anything), after submitting a request, so you'll use a callback where none has been provided.

GET /products/<product-handle>.js

Get the JSON of a product using the product handle.

Response The JSON of the product.

Example:

{
  "id": 329678821,
  "title": "Red Rain Coat",
  "handle": "red-rain-coat",
  "description": "<p>Lorem Ipsum.</p>",
  "published_at": "2014-06-12T16:28:11-04:00",
  "created_at": "2014-06-12T16:28:13-04:00",
  "vendor": "Shopify",
  "type": "Coat",
  "tags": [
    "Spring"
  ],
  "price": 12900,
  "price_min": 12900,
  "price_max": 12900,
  "available": true,
  "price_varies": false,
  "compare_at_price": null,
  "compare_at_price_min": 0,
  "compare_at_price_max": 0,
  "compare_at_price_varies": false,
  "variants": [
    {
      "id": 794864229,
      "title": "Small",
      "options": [
        "Small"
      ],
      "option1": "Small",
      "option2": null,
      "option3": null,
      "price": 12900,
      "weight": 0,
      "compare_at_price": null,
      "inventory_quantity": 3,
      "inventory_management": "shopify",
      "inventory_policy": "deny",
      "available": true,
      "sku": null,
      "requires_shipping": true,
      "taxable": true,
      "barcode": "49738645"
    },
    {
      "id": 794864233,
      "title": "Medium",
      "options": [
        "Medium"
      ],
      "option1": "Medium",
      "option2": null,
      "option3": null,
      "price": 12900,
      "weight": 0,
      "compare_at_price": null,
      "inventory_quantity": 10,
      "inventory_management": "shopify",
      "inventory_policy": "deny",
      "available": true,
      "sku": null,
      "requires_shipping": true,
      "taxable": true,
      "barcode": "49738657"
    },
    {
      "id": 794864237,
      "title": "Large",
      "options": [
        "Large"
      ],
      "option1": "Large",
      "option2": null,
      "option3": null,
      "price": 12900,
      "weight": 0,
      "compare_at_price": null,
      "inventory_quantity": 10,
      "inventory_management": "shopify",
      "inventory_policy": "deny",
      "available": true,
      "sku": null,
      "requires_shipping": true,
      "taxable": true,
      "barcode": "49738673"
    }
  ],
  "images": [
    "//cdn.shopify.com/s/files/1/0040/7092/products/red-rain-coat.jpeg?v=1402604893"
  ],
  "featured_image": "//cdn.shopify.com/s/files/1/0040/7092/products/red-rain-coat.jpeg?v=1402604893",
  "options": [
    {
      "name": "Size",
      "position": 1
    }
  ],
  "url": "/products/red-rain-coat"
}

Example of coding using jQuery:

jQuery.getJSON('/products/red-rain-coat.js', function(product) {
  alert('The title of this product is ' + product.title);
} );

(Return to top)

POST /cart/add.js

Use this to add a variant to the cart.

POST data

{
  quantity: 2,
  id: 794864229
}

Where quantity is how many you want to add of a particular variant, and id is the variant ID of that variant.

You can also send a serialized Add to Cart form:

jQuery.post('/cart/add.js', $('form[action="/cart/add"]').serialize());

You can add to the cart with Line Item Properties, not just a quantity and id:

jQuery.post('/cart/add.js', {
  quantity: 1,
  id: 794864229,
  properties: {
    'First name': 'Caroline'
  }
});

You cannot add different variants to the cart with a single Ajax request. You'll need to queue up several Ajax requests synchronously to add different variants to the cart.

Response if successful The JSON of the line item associated with the added variant.

Example:

{
  "id": 794864229,
  "title": "Red Rain Coat - Small",
  "price": 12900,
  "line_price": 12900,
  "quantity": 1,
  "sku": null,
  "grams": 0,
  "vendor": "Shopify",
  "properties": null,
  "variant_id": 794864229,
  "gift_card": false,
  "url": "/products/red-rain-coat?variant=794864229",
  "image": "http://cdn.shopify.com/s/files/1/0040/7092/products/red-rain-coat.jpeg?v=1402604893",
  "handle": "red-rain-coat",
  "requires_shipping": true
}

If the item was already in the cart, the quantity will be equal to the new quantity for that item.

Response if error

If the exact quantity specified for the item cannot be added to the cart (say you were trying to add 9 items, 2 are already in the cart, and 10 are in stock), no item is added the cart. The error returned will be:

{
  "status": 422,
  "message": "Cart Error",
  "description": "You can only add 8 Messenger Bag to the cart."
}

Note that the error too is formatted as JSON.

The error code is:

422 (Unprocessable Entity)

If the product is entirely sold out, the error returned will say this:

The product #{item.name} is already sold out.

If the product is not sold out but the requested quantity exceeds what is available, yet at least 1 item can still be added to the cart, the error returned will specify how many more items can be added to the cart:

You can only add #{item.remaining_inventory} #{item.name} to the cart.

The #{item.remaining_inventory} value is equal to #{item.inventory_quantity} minus what's in the cart.

If the product is not sold out, but all of its stock is in the cart, the returned error will say:

All #{item.inventory_quantity} #{item.name} are in your cart.

(Return to top)

GET /cart.js

Use this to get the cart as JSON.

Response The JSON of the cart.

Example:

{
  "token": "1d19a32178501c44ef2223d73c54d16d",
  "note": "hello!",
  "attributes": {
  },
  "total_price": 15800,
  "total_weight": 0,
  "item_count": 2,
  "items": [
    {
      "id": 794864229,
      "title": "Red Rain Coat - Small",
      "price": 12900,
      "line_price": 12900,
      "quantity": 1,
      "sku": null,
      "grams": 0,
      "vendor": "Shopify",
      "properties": null,
      "variant_id": 794864229,
      "gift_card": false,
      "url": "/products/red-rain-coat?variant=794864229",
      "image": "http://cdn.shopify.com/s/files/1/0040/7092/products/red-rain-coat.jpeg?v=1402604893",
      "handle": "red-rain-coat",
      "requires_shipping": true,
      "product_title":"Red Rain Coat",
      "product_description":"A bright red rain coat for rainy days!",
      "variant_title":"Red",
      "variant_options":["Red"]
    },
    {
      "id": 794864101,
      "title": "Gray Fedora",
      "price": 2900,
      "line_price": 2900,
      "quantity": 1,
      "sku": null,
      "grams": 0,
      "vendor": "Shopify",
      "properties": null,
      "variant_id": 794864101,
      "gift_card": false,
      "url": "/products/gray-fedora?variant=794864101",
      "image": "http://cdn.shopify.com/s/files/1/0040/7092/products/gray-fedora.jpeg?v=1402604885",
      "handle": "gray-fedora",
      "requires_shipping": true,
      "product_title":"Gray Fedora",
      "product_description":"A gray hat for looking cool!",
      "variant_title":"Gray",
      "variant_options":["Gray"]
    }
  ],
  "requires_shipping": true
}

Example of a response for an empty cart:

{
  "token": "1d19a32178501c44ef2223d73c54d16d",
  "note": null,
  "attributes": {},
  "total_price": 0,
  "total_weight": 0,
  "item_count": 0,
  "items": [],
  "requires_shipping": false
}

(Return to top)

POST /cart/update.js

Use this to change cart attributes, the cart note, and quantities of line items in the cart.

POST data

{
  quantity: 1,
  id: 794864053
}

Where quantity is the new quantity you want for a particular item, and id is the variant ID of that line item. You can also send a serialized cart form.

Response The JSON of the cart.

Reminder

This is what you will use to submit cart attributes and a cart note.

If the cart is empty the following jQuery snippet will add 2 of variant 794864053 and 3 of variant 794864233:

jQuery.post('/cart/update.js', {updates: {794864053: 2, 794864233: 3}});

This version will yield the same result:

jQuery.post('/cart/update.js', "updates[794864053]=2&updates[794864233]=3");

If you send the following you will update the quantity of 794864053 to 5:

jQuery.post('/cart/update.js', {updates: {794864053: 5}});

Finally, you can remove both 794864053 and 794864233 from the cart with the following:

jQuery.post('/cart/update.js', {updates: {794864053: 0, 794864233: 0}});

If it's not possible to set the quantity of an item to the requested value, because there is not enough of that item in stock, there will be a 422 error, and no quantity will be set as a result, not even the quantities of items that have sufficient stock.

If you use Line Item Properties you may end up with several items in the cart that share the same variant ID. How do you update the quantity of items in the cart when that happens? It turns out that you can also submit an array of numbers to /cart/update.js, where the size of the array will need to match the amount of line items in the cart.

Example, say you have 3 line items in the cart, with quantities 1, 2 and 3, and you want to change those quantities to 3, 2 and 1, you can use the following:

jQuery.post('/cart/update.js', {updates: [3, 2, 1]});

If there's any problem with updating any quantity when submitting an array of number, there will be a 422 error, and the quantities will remain the same as they were.

To change the quantity of one line item, you will need to use /cart/change.js instead (see the following section) and provide the 1-based index of the item in the cart like so:

jQuery.post('/cart/change.js', { line: 1, quantity: 1 });

To change the quantity of the second line item in the cart, you'll use this:

jQuery.post('/cart/change.js', { line: 2, quantity: 1 });

(Return to top)

POST /cart/change.js

This call sets the quantity of an item already in the cart.

POST data

{
  quantity: 1,
  id: 794864053
}

Response The JSON of the cart.

If you use Line Item Properties you may end up with several items in the cart that share the same variant ID. How do you update the quantity of an item in the cart that has specific line item properties? Once you have identified the 1-based index of the item in the cart, you can use the line property instead of id like so:

{
  quantity: 1,
  line: 1
}
jQuery.post('/cart/change.js', { quantity: 1, line: 1 });

Caution

Although /cart/update.js and /cart/change.js may seem like they accomplish the same function, they truly are quite different. The /cart/update.js controller allows updates to several items at once, including items that may not yet be in the cart (it will add them), and it also allows updates of cart attributes and the cart note. The /cart/change.js controller is only able to update the quantity of one item at a time, and that item must be in the cart already. If the item is not in the cart, /cart/change.js will not add it and it will then return a 404 error. Whereas the /cart/update.js controller updates no quantity when any of the requested update cannot be met, the /cart/change.js controller, on the other hand, will adjust the quantity to add all items in stock if what is requested is greater than what's available. Use your browser's JavaScript console to test things out if you're not sure about the behavior of the different request URLs.

(Return to top)

POST /cart/clear.js

This call sets all quantities of all line items in the cart to zero.

Response The JSON of an empty cart. This does not remove cart attributes nor the cart note.

Example:

{
  "token": "1d19a32178501c44ef2223d73c54d16d",
  "note": null,
  "attributes": {},
  "total_price": 0,
  "total_weight": 0,
  "item_count": 0,
  "items": [],
  "requires_shipping": false
}

(Return to top)

GET /cart/shipping_rates.json

Get estimated shipping rates.

Example of call:

/cart/shipping_rates.json?shipping_address%5Bzip%5D=K1N+5T2&shipping_address%5Bcountry%5D=Canada&shipping_address%5Bprovince%5D=Ontario

Response

Example:

{
  "shipping_rates": [
    {
      "name": "Ground Shipping",
      "price": "8.00",
      "delivery_date": null,
      "source": "shopify"
    },
    {
      "name": "Expedited Shipping",
      "price": "15.00",
      "delivery_date": null,
      "source": "shopify"
    },
    {
      "name": "Express Shipping",
      "price": "30.00",
      "delivery_date": null,
      "source": "shopify"
    }
  ]
}

(Return to top)

You're building a quick order form? Beware

Caution

Ajax requests that update the cart must be queued and sent synchronously to the server. Meaning: you must wait for your 1st ajax callback, to send your 2nd request, and then wait for its callback to send your 3rd request, etc.

Your request queue can be a very simple JavaScript array:

Shopify.queue = [];

As you examine your quantity fields, you will add requests to that queue:

jQuery('.quantity').each(function() {
  Shopify.queue.push( {
    variantId: jQuery(this).data('variant-id'),
    quantity: parseInt(jQuery(this).val(), 10) || 0
  } );
});

When you are done, you start your engine, using for instance Shopify.addItem.

The callback of this Ajax request should call a function that shifts (removes) a request from Shopify.queue and then call Shopify.addItem with the variantId and quantity stored in the next request. Of course, you'll check if the queue has any requests left in it. If it's empty, you must cheerfully redirect to the cart page.

Something like this:

Shopify.moveAlong = function() {
  // If we still have requests in the queue, let's process the next one.
  if (Shopify.queue.length) {
    var request = Shopify.queue.shift();
    Shopify.addItem(request.variantId, request.quantity, Shopify.moveAlong);
  }
  // If the queue is empty, we will redirect to the cart page.
  else {
    document.location.href = '/cart';
  }
};

Shopify.moveAlong must be called within the callback of each Ajax request.

Information

If you're interested in looking at a fully-coded example that adds several items to the cart with one single click, head over to the tutorial Add an order form to your website.

Ready to put what you've learned into action?

Build an online store with Shopify. Try it free.

Experience the future of retail now.

Shopify Point of Sale. Try it free.