## TL;DR
HubSpot dedupes contacts by email, so a blind create conflicts. Search for the contact by email first, then PATCH the existing record; only create when the search comes back empty.

```text
hubspot api 409 conflict contact already exists by email
```

## Use this when
- POST to create a contact returns 409 conflict.
- An import job errors on duplicates mid-run.
- Upsert logic you wrote assumes create always works.

## Not for this skill when
- 400 property validation errors.
- 401 expired OAuth tokens.
- Company or deal association errors, which have their own endpoints.

## Steps
1. Confirm the 409 body names the email as the conflicting identity. Verify: the error references the existing email address.
2. Search contacts by email before creating. Verify: the search returns the existing contact with its ID.
3. PATCH the existing contact with the new properties instead of creating. Verify: the response is 200 and the properties updated.
4. Only POST a create when the search returns zero results. Verify: new emails create cleanly with 201.
5. Make the job idempotent: wrap search-then-update in one function every caller uses. Verify: running the job twice produces no 409s and no duplicates.

## Variant phrasings
### hubspot contact already exists 409
Common phrasing of the conflict.
### hubspot api create contact conflict email
The API-angle search.
### hubspot upsert contact by email
The pattern-angle search.

Compatibility: HubSpot CRM v3 Contacts API; behavior applies to all portals.

## Why it happens
Email is the unique identity for contacts in HubSpot. Two creates with the same email race into a conflict because the second one violates that uniqueness; HubSpot returns 409 rather than silently merging.

## Edge cases / pitfalls
- The search API has its own rate limits; cache results inside a batch run.
- Associations are not carried over by a PATCH; set them separately.
- Custom dedupe rules on other identifiers do not apply to the email identity check.
- Deleted contacts can still conflict; check the recycle bin before assuming the email is free.
- The 409 response sometimes includes the existing contact ID; use it directly instead of a separate search.
- HubSpot dedupes email case-insensitively, so differently-cased versions of the same address still conflict.

## Provenance

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