google-apps-scriptshopifyputurlfetchhttp-status-code-406

Shopify API, 406 response for PUT request from Google Apps Script UrlFetchApp


I am building a Google Apps Script script that connects to the Shopify API to create new products and/or update existing products from a spreadsheet. I have been successful at connecting to the API for GET requests (list all products) and POST requests (create new product, update inventory level) but when trying to do a PUT request to update a variant price I'm receiving a 406 response code.

Documentation: https://help.shopify.com/en/api/reference/products/product-variant#update-2019-07

I initially was testing using update product but was having the same issues. I switched to the variant endpoint as I found it was more direct than the update product.

I tried adding the following code to the headers to help with the response but it doesn't make a difference

'Content-Type': "application/json", 
'Accept': "application/json"

I tried replicating the PUT request using Postman and it's gone through successfully (adding to my confusion). Again, all my GET and POST requests have gone through fine so it's not an issue with my API credentials. I've checked the endpoint and it all appears correct.

Here is the code I've been testing with (even hardcoding the variant id and price to ensure there wasn't an issue with the variables)

function testUpdate(){


  var url = "https://cablemax.myshopify.com/admin/api/2019-07/variants/20731961475134.json"

  var headers = {
    "method": "put",
    "muteHttpExceptions": true,
    "Authorization": "Basic " + Utilities.base64Encode(API_KEY+":"+API_PASSWORD),
    'Content-Type': "application/json", 
    'Accept': "application/json"
  }

  var payload = {
    "variant": {
      "id": 20731961475134,
      "price": "12.44"
    }
  }

  var params = {
    'headers': headers,
    'contentType': "application/json",
    'payload': JSON.stringify(payload),
  }

  try {
    var response = UrlFetchApp.fetch(url, params);
    var responseCode = response.getResponseCode();

    if (responseCode == 200) {
      console.log("Price for: "+ variant_id + " updated successfully"); 
    } else {
      console.log("Price for: "+ variant_id + " failed to update"); 
    }
  } catch(e) {
    console.log("Price update for: " + variant_id + " has failed. Error: " + e); 
  }

}

I don't understand what's failing here as all my other requests have been successful and this request (with payload data exactly the same) is successful in Postman. The catch response just returns

Request failed for https://cablemax.myshopify.com returned code 406

Given that request is returning 406 I'm assuming there is an error in how the request is formatted instead of the payload data but I'm at a loss for what the issue is.


Solution

  • You seem to be formatting the params object incorrectly. Try the following instead:

    var url = "https://cablemax.myshopify.com/admin/api/2019-07/variants/20731961475134.json";
    var params = {
        "method":"put",
        "contentType":"application/json",
        "headers": {
            "Authorization": "Basic " + Utilities.base64Encode(API_KEY+":"+API_PASSWORD)
        },
        "payload": JSON.stringify({
            "variant": {
                "id":20731961475134,
                "price":"12.44"
            }
        })
    };
    
    var response = UrlFetchApp.fetch(url, params);
    

    In Apps Script, you don't specify Content-Type as a header; its defined as the parameter contentType on the params object instead. Also, depending on the expectations of the API, you may need to replace Utilities.base64Encode() with Utilities.base64EncodeWebSafe().

    See documentation for UrlFetchApp.fetch(url, params)