Ghost admin API | Create tag | 401 error

Hello,
I’m trying to develop an API sync between my Google Spreadsheet and Ghost Admin API to create new tags based on Google Sheets new rows. At this moment everything supposed to be good, except auth error. I created new Integration in admin panel, set Script Properties in Google Scripts, so my code could get auth params from there. But it seems that I lost something… please help me with advice.

I left Google Sheets page shared for your review.
Origin in headers was changed to my original website.

Here is my code:

function createTags() {
  var spreadsheet = SpreadsheetApp.openById("12NWkY2oYf9mqGscF31Ajv2OsU0TPhlfLhycnbuwfwDg");
  var sheet = spreadsheet.getSheetByName("tags");
  var range = sheet.getRange(2, 1, sheet.getLastRow() - 1, sheet.getLastColumn());
  var values = range.getValues();
  var scriptProperties = PropertiesService.getScriptProperties();
  var apiName = scriptProperties.getProperty("API_Name");
  var contentApiKey = scriptProperties.getProperty("Content_API_key");
  var adminApiKey = scriptProperties.getProperty("Admin_API_key");
  var apiUrl = scriptProperties.getProperty("API_URL");
  for (var i = 0; i < values.length; i++) {
    var status = values[i][0];
    var slug = values[i][1];
    var name = values[i][2];
    var description = values[i][3];
    var visibility = values[i][4];
    var metaTitle = values[i][5];
    var metaDescription = values[i][6];
    if (slug && !status) {
      try {
        var tagUrl =
          apiUrl + "/ghost/api/v3/content/tags/slug/" + slug + "/?key=" + adminApiKey;
        var tagOptions = {
          method: "get",
          headers: {
            Origin: "https://myappsite.com",
          },
          muteHttpExceptions: true,
        };
        var tagResponse = UrlFetchApp.fetch(tagUrl, tagOptions);
        var tagData = JSON.parse(tagResponse.getContentText());
        if (tagResponse.getResponseCode() == 200) {
          if (tagData.tags && tagData.tags.length > 0) {
            var tag = tagData.tags[0];
            sheet.getRange(i + 2, 1).setValue("Exists");
            Logger.log("Tag with slug " + slug + " already exists.");
          } else {
            Logger.log("No tag data found for slug " + slug);
          }
        } else {
          sheet.getRange(i + 2, 1).setValue("API_Error_" + tagResponse.getResponseCode());
          Logger.log(
            "Failed to get tag with slug " +
              slug +
              ". API Error: " +
              tagResponse.getResponseCode()
          );
        }
      } catch (error) {
        try {
          var newTagUrl =
            apiUrl + "/ghost/api/v3/admin/tags/?key=" + adminApiKey;
          var newTagPayload = {
            name: name,
            slug: slug,
            description: description,
            visibility: visibility,
            meta_title: metaTitle,
            meta_description: metaDescription,
          };
          var newTagOptions = {
            method: "post",
            contentType: "application/json",
            payload: JSON.stringify(newTagPayload),
            headers: {
              Origin: "https://myappsite.ghost.io/",
            },
            muteHttpExceptions: true,
          };
          var newTagResponse = UrlFetchApp.fetch(newTagUrl, newTagOptions);
          var newTagData = JSON.parse(newTagResponse.getContentText());
          if (newTagData.tags && newTagData.tags.length > 0) {
            var newTag = newTagData.tags[0];
            sheet.getRange(i + 2, 1).setValue("Created");
            Logger.log("Tag with slug " + slug + " was created.");
          } else {
            Logger.log("No tag data found for slug " + slug);
          }
        } catch (error) {
          sheet.getRange(i + 2, 1).setValue("Ghost_Failure");
          Logger.log("Failed to create tag with slug " + slug + ". Error: " + error);
        }
      }
    }
  }
}

And I get this response:

1:38:58 PM Notice Execution started
1:39:01 PM Info Failed to get tag with slug artificial-intelligence. API Error: 401
1:39:01 PM Info Failed to get tag with slug no-code. API Error: 401
1:39:03 PM Notice Execution completed

There’s a lot here, so it’s going to be hard to debug.

I can see, right off the bat, that the Admin API calls won’t work because auth isn’t configured correctly.
See the docs for more info: Ghost Admin API Documentation

The API is also no longer versioned, so you can remove that from the URL. https://ghost.org/docs/content-api/

My first step in debugging this would be to confirm that all the environment variables are populating correctly. By that, I mean log out your API keys and URLs and confirm that they are correct. Then, I’d confirm I can make API calls successfully in Node or the browser. That way, you know that everything is working before moving to the more complicated Google Scripts environment.

1 Like

Ryan, thank you for your help! You helped a lot, I swapped an auth method to JWT and everything is alright now!

1 Like