Integrating Typeform with HubSpot for Automated Lead Capture
Syncing Typeform conversational form entries directly into HubSpot's CRM v3 Contacts API automates inbound lead qualification. Instead of manual exports or third-party middleware bottlenecks, developers can parse Typeform's signed form_response webhooks and invoke HubSpot's batch create/update endpoints within 200 milliseconds of submission.
Comparison matrix
| Feature | Typeform | HubSpot | Edge |
|---|---|---|---|
| Starting Price | $25/month (Basic plan, 100 responses/mo) | $20/seat/month (Starter plan, free tier available) | HubSpot |
| API Rate Limits | 2 requests/second | 100โ190 requests/10 seconds per app | HubSpot |
| Authentication Methods | Bearer Token / OAuth 2.0 | Private App Access Token (Bearer) / OAuth 2.0 | Tie |
| Webhook Payload Signing | Supported (HMAC-SHA256 via Typeform-Signature) | Supported (v3 request signature validation) | Tie |
| Ecosystem Integrations | 120+ prebuilt integrations | 1,600+ App Marketplace integrations | HubSpot |
| Data Volume Restrictions | Tier-gated monthly response caps (overage charges apply) | Up to 15,000,000 non-marketing contacts on free CRM | HubSpot |
| Frontend Lead Conversion UX | Conversational single-question display with conditional logic | Standard embedded iframe and traditional static form builder | Typeform |
| Custom Data Schema Storage | Hidden fields and dynamic payload variables only | Custom properties on standard objects (Custom Objects gated to Enterprise) | HubSpot |
| Start free | Try Typeform โ | Try HubSpot โ |
ROI metrics
Hours saved / mo
38
Typeform / mo
$55
HubSpot / mo
$40
Break-even
1.4 wks
Annual savings
$21,780
Automating Typeform lead ingestion directly to HubSpot removes 1.5 hours of daily manual CRM imports across a 10-person team, offsetting the $95 combined monthly tool cost within 10 business days.
Step-by-step setup guide
1.Generate HubSpot Private App Token
In HubSpot Settings, navigate to Integrations > Private Apps. Create an app named 'Typeform Lead Ingestion' and assign the 'crm.objects.contacts.write' and 'crm.objects.contacts.read' scopes. Copy the resulting Bearer token starting with 'pat-'.
curl -X GET https://api.hubapi.com/crm/v3/properties/contacts -H "Authorization: Bearer pat-na1-xxxx-xxxx"
2.Configure Typeform Webhook Endpoint
Use the Typeform Create Webhook API endpoint or the Typeform Connect UI to point submission events to your backend routing server. Define a secret token to verify payload authenticity.
curl -X PUT https://api.typeform.com/forms/{form_id}/webhooks/hubspot-sync -H "Authorization: Bearer tfp_xxxx" -H "Content-Type: application/json" -d '{"url":"https://api.yourdomain.com/webhooks/typeform","enabled":true,"secret":"whsec_AlphaNumericSecretKey99"}'3.Verify HMAC-SHA256 Webhook Signatures
Compute the HMAC-SHA256 hash of the incoming request body using your Typeform secret key and compare it in constant time against the value found in the 'Typeform-Signature' HTTP request header.
const crypto = require('crypto'); const signature = req.headers['typeform-signature']; const hash = 'sha256=' + crypto.createHmac('sha256', process.env.TYPEFORM_SECRET).update(req.rawBody).digest('base64'); const isValid = crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(hash));4.Extract Form Fields and Build HubSpot Contact Payload
Parse the 'form_response.answers' array. Match answers by 'field.ref' or 'field.id' to the target HubSpot contact properties ('email', 'firstname', 'lastname', 'company').
const answers = req.body.form_response.answers; const email = answers.find(a => a.type === 'email')?.email; const firstname = answers.find(a => a.field.ref === 'first_name')?.text; const company = answers.find(a => a.field.ref === 'company_name')?.text;
5.Upsert Contact into HubSpot via CRM v3 API
Send a POST request to HubSpot's contact creation endpoint. Set 'idProperty' to 'email' or handle HTTP 409 Conflict status codes to update existing lead records without overwriting lead creation dates.
curl -X POST https://api.hubapi.com/crm/v3/objects/contacts -H "Authorization: Bearer pat-na1-xxxx-xxxx" -H "Content-Type: application/json" -d '{"properties":{"email":"jane.doe@enterprise.io","firstname":"Jane","company":"Acme Corp","leadsource":"Typeform Inbound"}}'
Webhook payload example
POST https://api.yourdomain.com/webhooks/typeform ยท event: form_response
{
"event_id": "01HNY78QW45Z8M1ZXY019ABCDE",
"event_type": "form_response",
"form_response": {
"form_id": "d7kM9Z8A",
"token": "01HNY78QW45Z8M1ZXY019FGHIJ",
"landed_at": "2024-10-24T14:15:22Z",
"submitted_at": "2024-10-24T14:16:05Z",
"definition": {
"id": "d7kM9Z8A",
"title": "Enterprise Inbound Request",
"fields": [
{"id": "em_1", "ref": "contact_email", "type": "email", "title": "What is your work email?"},
{"id": "txt_1", "ref": "contact_name", "type": "short_text", "title": "What is your full name?"},
{"id": "txt_2", "ref": "company_name", "type": "short_text", "title": "What company are you with?"}
]
},
"answers": [
{"type": "email", "email": "jordan.smith@cloudscale.net", "field": {"id": "em_1", "type": "email", "ref": "contact_email"}},
{"type": "text", "text": "Jordan Smith", "field": {"id": "txt_1", "type": "short_text", "ref": "contact_name"}},
{"type": "text", "text": "CloudScale Net", "field": {"id": "txt_2", "type": "short_text", "ref": "company_name"}}
]
}
}Typeform: pros & cons
- โ Conversational layout produces 20% to 40% higher form completion rates on mobile devices compared to static web forms.
- โ Payload verification via HMAC-SHA256 headers guarantees request origin integrity before payload execution.
- โ Built-in conditional logic jumps capture branching lead qualifications without bespoke front-end code.
- โ ๏ธ Aggressive response caps on entry-level tiers ($25/mo caps at 100 responses, $0.40/response overage).
- โ ๏ธ API rate limit constrained to 2 requests per second makes bulk retro-syncing slow.
HubSpot: pros & cons
- โ Robust CRM v3 API allows up to 190 requests per 10-second window per private app.
- โ Free tier hosts up to 15 million contacts and includes lead scoring and timeline tracking.
- โ Private App access tokens bypass complex multi-tenant OAuth overhead for direct server-to-server pipelines.
- โ ๏ธ Custom Objects schema configuration is restricted to Enterprise tier plans ($3,600+/month).
- โ ๏ธ Contact update batch endpoints will fail the entire batch if an individual record contains a validation error.
FAQ
How does the pipeline handle existing contacts without duplicate record errors in HubSpot?
When sending a POST request to '/crm/v3/objects/contacts', HubSpot returns an HTTP 409 Conflict if the email already exists, along with the conflicting record ID. Your webhook handler must catch the 409 response, extract the existing record ID from the error message body, and execute a 'PATCH /crm/v3/objects/contacts/{contactId}' request to update fields.
What happens if Typeform webhook dispatch fails due to an endpoint timeout?
Typeform retries failed webhook deliveries using an exponential backoff schedule for up to 24 hours. Your receiver endpoint must return an HTTP 200 or 204 status within 10 seconds of initial receipt; execute contact upserts asynchronously via an internal job queue (e.g., Redis BullMQ or AWS SQS) to prevent timeouts.
Can I map Typeform Hidden Fields to HubSpot UTM tracking properties?
Yes. Typeform appends hidden URL query parameters to the root of the 'form_response.hidden' object. You can directly extract 'hidden.utm_source', 'hidden.utm_medium', and 'hidden.utm_campaign' and write them into the default HubSpot properties 'hs_analytics_source_data_1' and 'hs_analytics_source_data_2'.
How do Typeform API limits impact high-traffic product launches?
Typeform's 2 req/s REST API limit applies to inbound GET/POST requests directed at 'api.typeform.com' (such as manual polling or form configuration edits). Outbound webhooks pushed to your server are not throttled by this 2 req/s limit, allowing your application to handle sudden bursts of hundreds of concurrent submissions.