Contact usTry for free
Developer documentation API keys
Developers/HubSpot guide

HubSpot implementation guide

Enrich a HubSpot contact with TargetWise

Read a HubSpot contact, request missing work email or business phone fields, review the result and apply a safe update through the Contacts API.

Updated 10 September 2026 · Documentation and review policy

Start with a reviewed test contact.

  1. Create a named TargetWise workspace key.
  2. Use a HubSpot app credential with contact read and write permissions. Retrieve the contact by its record ID; keep the token in your backend secret store. The request and update shapes follow the HubSpot Contacts API.
  3. Confirm that the name and company domain identify this CRM contact. The fictional record below must be replaced with your own approved test record.
  4. Download targetwise-crm.mjs beside your Node.js script. It proposes changes by default.

Read, enrich and inspect the proposed update.

Node.js · dry run
import { enrichCrmContact } from './targetwise-crm.mjs';

const outcome = await enrichCrmContact({
  platform: 'hubspot',
  recordId: process.env.CRM_CONTACT_ID,
  identity: {
  "first_name": "Alex",
  "last_name": "Reed",
  "company_domain": "example.com"
},
  targetwiseKey: process.env.TARGETWISE_API_KEY,
  crmToken: process.env.CRM_ACCESS_TOKEN,
  includePhone: false,
  apply: false,
});
// Inspect outcome.patch in your secure review interface.
// Log only status and request ID, not the contact values.
console.log(outcome.status, outcome.requestId);

The helper reads the existing contact, skips a lookup when the requested fields are already filled, and calls POST /api/v1/contacts/enrich once. Phone retrieval is off by default. The lookup can consume your plan’s usage balance even when the CRM update is a dry run.

Keep trusted data and inspect unresolved fields.

TargetWise fieldHubSpot propertyWrite rule
data.work_emailemailOnly when the existing value is empty and the returned identity was reviewed
data.business_phonephoneOnly if phone was requested; preserve the current value
data.phone_typeDo not infer mobilephoneunknown is not a verified mobile classification
request_idYour integration event logStore for tracing without logging the result body
Illustrative partial response
{
  "object": "enrichment_result",
  "status": "partial",
  "request_id": "illustrative-request",
  "data": {
    "work_email": "alex@example.com",
    "business_phone": null
  },
  "unresolved_fields": [
    "business_phone"
  ]
}

A partial result may still contain the email you requested. A missing value never clears an existing CRM field. Add company enrichment as a separate, deliberate request when account context is needed; use reverse email lookup when the business email is your starting identifier.

Apply only after the test record passes review.

Set apply: true for your reviewed test run. The example re-reads the record and stops if its tracked fields changed. HubSpot updates are not an atomic fill-if-empty operation. Serialize writes for each contact in your integration and use a review or shadow-property workflow if other systems can edit the same fields concurrently.

  • Test a missing email, an already-filled record, a partial response, no match and a record changed during the lookup.
  • Stop on 400 or 401. Correct input or authentication. On 402, review balance. On 429, respect Retry-After and workspace limits; do not loop immediately.
  • Store an integration event ID with the completed outcome. Check it before re-running the event; a repeated POST is not automatically free.

The downloadable mapping and orchestration example is covered by local fixture tests, including CRM HTTP requests. Run this checklist in your own CRM sandbox before enabling production writes. This guide does not install a native CRM connector.