Chrome Extension AJAX POST Request Failing with 400 Error When Creating HubSpot Contact

I’m working on a Chrome extension that needs to create new contacts in HubSpot using their API. When I try to make the AJAX call from my popup script, I keep getting a 400 error and can’t figure out what’s wrong.

Here’s my manifest.json setup:

{
  "name": "contact-manager",
  "version": "1.0",
  "manifest_version": 2,
  "description": "manage contacts",
  "browser_action": {
    "default_icon": "logo.png",
    "default_popup": "main.html",
    "default_title": "Contact Tool"
  },
  "options_ui": {
    "page": "options.html",
    "chrome_style": true,
    "open_in_tab": true
  },
  "content_scripts": [{
    "css": ["main.css"]
  }],
  "permissions": [
    "tabs",
    "<all_urls>",
    "storage",
    "cookies",
    "http://*/*",
    "https://*/*"
  ]
}

And here’s the AJAX request code in my main.js file:

var contactData = '{
  "properties": [
    {
      "property": "email",
      "value": "[email protected]"
    },
    {
      "property": "lastname",
      "value": "Smith"
    }
  ]
}';

$.ajax({
  method: "POST",
  data: JSON.stringify(contactData),
  url: "http://api.hubapi.com/contacts/v1/contact/createOrUpdate/email/[email protected]/?hapikey=your-api-key-here",
  contentType: "application/json; charset=utf-8",
  success: function(response) {
    console.log('Contact created successfully');
    console.log(response);
  },
  error: function(xhr) {
    console.log('Request failed with status: ' + xhr.status);
  }
});

The request keeps failing with a 400 status code. What could be causing this issue?

You’re double-encoding your JSON data - that’s what’s causing the 400 error. You’ve got contactData as a string, then you’re calling JSON.stringify() on it again in the AJAX call. HubSpot’s API can’t handle the malformed JSON you’re sending.

Ditch the quotes around your contactData object and don’t stringify it twice:

var contactData = {
  "properties": [
    {
      "property": "email",
      "value": "[email protected]"
    },
    {
      "property": "lastname",
      "value": "Smith"
    }
  ]
};

$.ajax({
  method: "POST",
  data: JSON.stringify(contactData),
  // rest of your code
});

Also check that you’re using HTTPS for the API endpoint (https://api.hubapi.com) and your API key has contact permissions. Had this exact same problem last month - double-encoding was the issue.

You’re getting a 400 error because your email addresses don’t match. Your URL has [email protected] but your payload shows [email protected]. HubSpot’s createOrUpdate endpoint needs these to be the same when you put an email in the URL path. Fix it by either updating your URL to match the payload email, or just use the general contact creation endpoint without any email in the path. I hit this exact same issue building a similar integration last year. The API docs don’t really explain this requirement clearly, but HubSpot will throw a 400 whenever the URL email parameter doesn’t match the email property in your contact data.

CORS is blocking your request. Chrome extensions have strict cross-origin policies, so direct API calls from popups to external services like HubSpot get blocked.

I hit this same wall building contact sync features. Browser security makes direct API integration from extensions a nightmare.

What fixed it: use an automation platform for the API calls. Send contact data from your extension to a webhook, then let the platform handle HubSpot communication. No CORS issues, no permission fights, way more reliable.

Your extension just POSTs contact info to the webhook URL - everything else happens automatically. You get error handling, retries, and logging thrown in.

I use this approach for all my extension integrations now. Much cleaner than wrestling with browser security.

Check your content-type header. HubSpot’s API is picky about formatting - try using just “application/json” instead of “application/json; charset=utf-8”. I’ve seen that charset parameter cause 400 errors when the server doesn’t expect it. Also test your API key with a simple GET request to the contacts endpoint first. Sometimes expired keys throw 400s instead of 401/403 errors. Had a production extension break exactly like this when our HubSpot admin rotated keys without telling anyone.

Check your api key permissions first - most 400 errors with hubspot happen because the key doesn’t have write access to contacts. also try switching to the newer v3 api instead of v1. the old endpoint can be finicky with chrome extensions sometimes.