HubSpot Forms API fix

Fix HubSpot Forms API 400 Bad Request errors.

A HubSpot Forms API 400 usually means the request reached HubSpot, but the endpoint, JSON body, field structure, context data, or consent block failed validation.

Fast checklist

  • Use the correct portal ID and form GUID.
  • Send valid JSON with a top-level `fields` array.
  • Use HubSpot internal field names, not labels.
  • Include required fields with non-empty values.
  • Add legal consent data when the form requires it.

Common causes

1. The JSON body is malformed

HubSpot expects a JSON request body. A missing comma, trailing comma, unescaped quote, or form-encoded body can produce a 400 before HubSpot can validate the fields.

2. `fields` is missing or shaped incorrectly

The request should include a top-level `fields` array. Each field should be an object with a HubSpot internal property name and a value.

{
  "fields": [
    {
      "name": "email",
      "value": "developer@example.com"
    },
    {
      "name": "firstname",
      "value": "Alex"
    }
  ]
}

3. You are using field labels instead of internal names

The field name should be the HubSpot internal property name, such as `email`, `firstname`, `lastname`, `company`, or a custom property name. Labels like "Email Address" or "First Name" can fail because HubSpot cannot map them reliably.

4. Required fields are missing or empty

If the HubSpot form requires a field, the API submission should include that field with a usable value. The most common missing required field is `email`.

5. `context` is malformed

Context is commonly used for attribution. It should be an object, not a string. `pageUri`, `pageName`, and `hutk` are the values worth checking first.

{
  "context": {
    "pageUri": "https://example.com/contact",
    "pageName": "Contact",
    "hutk": "hubspotutk-cookie-value"
  }
}

6. The consent block does not match the form

Forms with GDPR, privacy, or subscription consent enabled may need `legalConsentOptions`. If the form requires processing consent, include a consent block that matches what the visitor accepted.

{
  "legalConsentOptions": {
    "consent": {
      "consentToProcess": true,
      "text": "I agree to allow this website to store and process my personal data."
    }
  }
}

A complete baseline payload

Start with a small known-good payload, then add custom fields one by one. This makes it much easier to find the field or consent setting causing the 400.

{
  "fields": [
    {
      "name": "email",
      "value": "developer@example.com"
    },
    {
      "name": "firstname",
      "value": "Alex"
    }
  ],
  "context": {
    "pageUri": "https://example.com/contact",
    "pageName": "Contact",
    "hutk": "hubspotutk-cookie-value"
  }
}