## TL;DR

Stop sending property names that do not exist on the object. PROPERTY_DOESNT_EXIST means at least one internal property name in your batch is wrong or missing from the portal. Pull the live property list from HubSpot, fix the names, and the batch creates cleanly.

A generated client copying property names from docs examples or a different portal is the usual culprit.

## Verbatim query

```text
hubspot API 400: PROPERTY_DOESNT_EXIST on contacts batch create
```

## Steps

1. Read the exact property name from the error response
   HubSpot names the offending property in the error message. Copy it out.
   Expected: You have the bad internal name in hand, spelled exactly as sent.

2. Fetch the live property definitions for contacts
   Call the CRM properties endpoint for the contacts object and list every internal name the portal actually has.
   Expected: A JSON list of valid internal names; the bad name from step 1 is absent from it.

3. Fix every property name in the batch payload
   Rename misspelled, renamed, or invented properties to match the live list. Watch for label-vs-internal-name confusion, for example the docs show a display label while the API wants the lowercase internal name.
   Expected: Every property name in the payload appears in the live list.

4. Re-run the batch create
   Send the corrected batch and confirm clean creates.
   Expected: 201 responses and no PROPERTY_DOESNT_EXIST.

5. Add a pre-send name check to the generated client
   Validate property names against a cached property list before sending, so bad names fail locally with a clear message instead of at the API.
   Expected: A future bad name raises a local error naming the property.

## Use this when

- HubSpot returns 400 PROPERTY_DOESNT_EXIST on contacts batch create or batch update.
- A generated client invents property names or copies them from docs examples.
- The same payload works on one portal and fails on another.

## Not for this skill when

- The property exists but the value format is rejected (a different validation error).
- The failure is a 401 or 403 authentication problem.
- The error is on companies, deals, or tickets without checking that object's own property list first.

## Variant phrasings

### PROPERTY_DOESNT_EXIST on single-contact create

Same root cause on the single-record endpoint. The fix is identical: validate the property name against the live list.

### "Property X does not exist" wording on update

The batch update endpoint surfaces the same error. Treat it the same way.

## Why it happens

HubSpot properties are per-portal, not global. A property that exists in one portal may not exist in another, and generated clients routinely copy internal names from docs examples, sample payloads, or a different customer's portal. Custom properties add to the drift: a field an operator sees in the HubSpot UI may have a different internal name than the label suggests.

## Edge cases

- A custom property created in the HubSpot UI minutes ago may not be visible to the API yet; wait and retry.
- A property deleted from the portal after the client code was written keeps failing until the payload is updated.
- Internal name vs label: docs often show the friendly label; the API only accepts the internal name.
- Object confusion: a company property sent on a contact payload fails the same way.
- Sandbox portals and production portals can have different property sets; never assume they match.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_p_vOekrSy1mrUjIkZswPpQ
