Connect Typeform with HubSpot
Implementation Guide
Overview: Connecting Typeform and HubSpot
For B2B SaaS teams running inbound demand generation, the gap between a Typeform submission and a qualified record inside HubSpot is where lead velocity dies. A prospect fills out a multi-step form — answering qualification questions, selecting a product tier, or booking a demo — and that structured, high-intent data sits in Typeform's response store while your CRM waits. The Typeform-to-HubSpot integration closes that gap by treating every form response as a first-class CRM event, not just a CSV export scheduled for Monday morning.
Typeform's conversational form engine captures richer, more contextual data than a traditional flat form because respondents engage with one question at a time. This means a single response object can contain a deeply nested answer set — NPS scores, open-text qualifiers, file uploads, matrix selections, and hidden fields pre-populated with UTM parameters or account IDs passed from your marketing stack. When this payload is mapped correctly to HubSpot contact, deal, or ticket properties, you end up with CRM records that are genuinely useful for sales routing and lifecycle automation, rather than records that require a rep to manually interpret a PDF export.
This guide covers the full technical implementation for connecting Typeform to HubSpot using both the native Typeform Webhooks API and iPaaS middleware (Make / Zapier), including exact property mapping, OAuth scoping, hidden field configuration, and error recovery patterns.
Core Prerequisites
Before configuring the integration, you must satisfy requirements on both the Typeform and HubSpot sides independently.
On the Typeform side, you need a Typeform account on the Basic plan or higher to access the Webhooks API. Free-tier accounts do not expose webhook configuration. You must be the form owner or have been granted admin-level access to the specific workspace containing the target form. To authenticate against the Typeform API programmatically, generate a Personal Access Token (PAT) from your Typeform Admin panel under Account > Personal tokens. The PAT is a Bearer token used in the Authorization header for all API calls. If your organisation uses Typeform's OAuth 2.0 flow for a multi-tenant integration, you must register an application under Developer Apps and request the responses:read and webhooks:write scopes. The redirect URI registered in your Typeform app must exactly match the callback URL in your middleware or receiver service — a mismatch will produce a redirect_uri_mismatch error during the OAuth handshake.
On the HubSpot side, you require a Private App token with the following scopes explicitly granted: crm.objects.contacts.write, crm.objects.contacts.read, crm.objects.deals.write, and automation if you intend to enroll contacts into workflows. HubSpot deprecated its legacy API keys in November 2022; any implementation still relying on a hapikey query parameter will receive a 401 Unauthorized response from all v3 API endpoints. Navigate to Settings > Integrations > Private Apps, create a new app, and select the exact scopes listed above. Store the generated token securely — it is only displayed once. If you intend to use HubSpot's OAuth 2.0 for a marketplace-style integration rather than a private app, you must additionally configure a redirect URL, client ID, and client secret, and implement the token refresh flow since HubSpot access tokens expire after six hours.
You also need admin access to your HubSpot portal to create custom contact properties if your Typeform contains fields that do not map to HubSpot's default property set. Custom properties are created under Settings > Properties and must have their internal property name noted (e.g., typeform_nps_score) for use in API payloads.
Top Enterprise Use Cases
Lead Qualification and Routing: Enterprise sales teams use multi-step Typeform surveys as qualification gates. A prospect completing a "Request a Demo" form answers questions about team size, current tooling, and budget range. Each answer maps to a HubSpot contact property, and a HubSpot workflow then applies a lead score delta and routes the contact to the correct BDR queue based on the composite score.
Customer NPS and CSAT Closing the Loop: Post-onboarding NPS surveys sent via Typeform write scores directly to a custom HubSpot contact property. A HubSpot workflow triggers when the typeform_nps_score property is set to a value below 7, automatically creating a task for the CSM and enrolling the contact in a "at-risk" sequence.
Event and Webinar Registration: Typeform registration forms for webinars or field events create HubSpot contacts and simultaneously create a deal in a "Events" pipeline at a specific stage. This gives revenue teams full pipeline attribution for event-sourced opportunities.
Support Ticket Creation from Intake Forms: Technical support intake forms on Typeform submit data that creates HubSpot Service Hub tickets with pre-populated subject, priority, and category fields derived from the form answers, bypassing manual ticket triage entirely.
Step-by-Step Implementation Guide
Configuring the Typeform Webhook
The most direct and low-latency implementation path is to use Typeform's native Webhooks feature, which sends an HTTP POST request to a destination URL every time a form is submitted. Navigate to your target form in Typeform, select Connect > Webhooks, and add a new webhook endpoint. The destination URL will be the receiver endpoint in your middleware (e.g., a Make HTTP module listener, a Zapier Catch Hook URL, or your own Express.js service). Enable the Verify delivery toggle, which causes Typeform to include a Typeform-Signature header containing an HMAC-SHA256 hash of the payload body signed with a secret you configure. Your receiver must validate this signature before processing to prevent spoofed submissions.
A raw Typeform webhook payload follows this structure:
{
"event_id": "01HXYZ1234ABCD",
"event_type": "form_response",
"form_response": {
"form_id": "abc123XY",
"token": "resp_token_here",
"submitted_at": "2025-06-15T14:23:00Z",
"hidden": {
"utm_source": "google",
"utm_campaign": "q2-enterprise",
"account_id": "ACC-98765"
},
"answers": [
{
"field": { "id": "field_001", "type": "short_text", "ref": "first_name" },
"type": "text",
"text": "Priya"
},
{
"field": { "id": "field_002", "type": "email", "ref": "email_address" },
"type": "email",
"email": "[email protected]"
},
{
"field": { "id": "field_003", "type": "number", "ref": "company_size" },
"type": "number",
"number": 450
},
{
"field": { "id": "field_004", "type": "multiple_choice", "ref": "budget_range" },
"type": "choice",
"choice": { "label": "$50k - $100k" }
}
]
}
}
Your middleware must parse the answers array by iterating over each object and matching on field.ref — the human-readable reference name you assign to each question inside Typeform's form builder. This is more resilient than matching on field.id, which is an opaque system identifier that does not change but is harder to reason about during maintenance. Set the ref value for every question in your form before building the integration.
Hidden fields are accessed under form_response.hidden and are populated by appending query parameters to the Typeform URL (e.g., https://yourorg.typeform.com/to/abc123XY#utm_source=google&account_id=ACC-98765). These are invaluable for passing context from your marketing attribution layer directly into the CRM record without asking the user to provide it.
Creating or Updating a HubSpot Contact
Once you have extracted the answer values from the Typeform payload, you must issue a POST request to the HubSpot Contacts upsert endpoint to create a new contact or update an existing one matched by email address:
POST https://api.hubapi.com/crm/v3/objects/contacts/upsert
Authorization: Bearer YOUR_PRIVATE_APP_TOKEN
Content-Type: application/json
{
"properties": {
"email": "[email protected]",
"firstname": "Priya",
"company_size_typeform": "450",
"budget_range": "$50k - $100k",
"utm_source": "google",
"hs_lead_status": "NEW"
},
"idProperty": "email"
}
The idProperty: "email" directive instructs HubSpot to treat the email address as the deduplication key. If a contact with that email already exists, the specified properties are updated; if not, a new contact is created. This is critical for avoiding duplicate records when the same prospect submits multiple Typeform forms at different funnel stages.
For iPaaS implementations in Make (formerly Integromat), use a Webhooks > Custom Webhook module as the trigger, followed by a JSON > Parse JSON module to structure the raw payload, and then an HTTP > Make a Request module or the native HubSpot > Create/Update a Contact module. In Zapier, a Typeform > New Entry trigger feeds directly into a HubSpot > Create or Update Contact action. In Zapier, map each answer field using the field reference ID visible in the Typeform trigger test data panel. Note that Zapier's Typeform trigger uses the Typeform Responses API with polling (every 1–15 minutes depending on plan), introducing latency compared to the webhook approach.
Common Pitfalls & Troubleshooting
401 Unauthorized from HubSpot: This is almost always caused by using a legacy hapikey parameter, by using a Private App token that does not include the required scopes, or by the token having been regenerated after initial setup without updating the middleware configuration. Inspect the response body — HubSpot returns a JSON error object with a category field set to INVALID_AUTHENTICATION and a message that specifies whether the token is missing or lacks permissions. Regenerate the Private App token, ensure all required scopes are checked, and update the stored credential in your middleware.
422 Unprocessable Entity from HubSpot: This error occurs when you attempt to set a property value that does not conform to the expected type or enumeration. For example, if your budget_range property in HubSpot is a dropdown with defined options and you pass a string value that does not exactly match one of the defined option labels, the API rejects the request. Audit your HubSpot property definitions and ensure your Typeform answer labels exactly match the HubSpot option internal values (not display labels, which can differ).
Typeform Webhook Signature Validation Failures: If your receiver is rejecting valid Typeform payloads due to HMAC signature mismatch, confirm that you are computing the HMAC over the raw request body bytes before any JSON parsing, and that you are using the correct secret configured in the Typeform webhook settings. Middleware platforms that automatically parse the request body before your validation logic runs can corrupt the signature check.
429 Too Many Requests from HubSpot: HubSpot's API enforces rate limits of 100 requests per 10 seconds for Private Apps on paid portals. High-volume form submission events — such as a webinar registration surge — can breach this limit. Implement exponential backoff in your receiver: on receiving a 429 response, read the Retry-After header, wait the specified number of seconds, and requeue the payload. In Make, use the built-in error handler with a Resume directive and a sleep interval. In a custom service, use a queue (e.g., AWS SQS or Redis with BullMQ) to buffer submissions and process them at a controlled rate.
Hidden Fields Not Populating: Hidden fields only work when the Typeform URL is accessed with the correct query parameters. If UTM parameters are not reaching the form, verify that your marketing links are correctly structured and that no URL shortener or redirect is stripping query parameters before the user lands on the form.