A native integration between HubSpot and Zendesk exists, but it works strictly one way: tickets from Zendesk -> contact timeline in HubSpot. No reverse sync, no tickets on the deal card, no user names — only email. Companies connect it, celebrate the “integration,” and a month later discover: the account manager cannot see an open customer ticket, HubSpot workflows do not fire on ticket status, and the support team creates Zendesk contacts manually.
What happens: the appearance of integration without real sync
After connecting the native integration through the HubSpot App Marketplace, the picture looks like this:
- “Ticket created” and “Ticket resolved” events from Zendesk appear in the HubSpot contact timeline
- The manager can see that the customer had support interactions
- Everything seems to work
But here is what is actually happening:
- Only the contact’s email is synced. First name and last name from Zendesk — not synced. If there is a user in Zendesk who is not in HubSpot — a contact is created with only an email and an empty name.
- Tickets are visible only in the contact timeline, not on the deal card, not on the company.
- Sync is only Zendesk -> HubSpot. HubSpot contacts are not pushed to Zendesk. Tickets are not created in HubSpot as Ticket objects.
- It is not possible to configure which ticket fields are synced — only a fixed set.
- HubSpot Workflows cannot see Zendesk events as triggers — automation based on ticket status is not possible.
Why the native integration is designed this way
Both companies position their tools as self-sufficient: Zendesk as a helpdesk, HubSpot as a CRM with Service Hub. The native integration was created to provide visibility — to show that a customer has had support interactions. It is a marketing decision, not an engineering one.
A full two-way integration competes with paid modules of both platforms:
— HubSpot Service Hub Professional ($100/user/mo) has its own ticket tracker
— Zendesk Sell ($19–55/user/mo) — a built-in CRM
If the integration were complete, customers could use both platforms separately — which is not beneficial to either company.
What the business specifically loses
The account manager does not know about a customer’s problems at the moment of a call.
A Zendesk ticket is only visible on the contact, not on the deal. The manager opens the deal card — no tickets. They call the customer with an upsell pitch — while the customer has an open critical incident. This is a real and common situation.
New Zendesk contacts are created without names.
If a customer writes to support via form and is not in HubSpot — a contact with only an email is created in HubSpot. First name, last name — empty. The manager gets a mess in the CRM.
HubSpot Workflows do not react to ticket status.
HubSpot Workflows cannot see Zendesk events as triggers. It is not possible to configure: “if a critical priority ticket is unresolved after 24 hours -> notify the account manager -> pause the upsell sequence.”
Support cannot see CRM data.
The Zendesk agent does not know what deal stage the customer is at, what their plan is, or who their account manager is. Zendesk does not receive data from HubSpot.
What a proper integration looks like
A complete integration requires a custom layer between the two APIs.
Architecture:
HubSpot Webhook: deal moved to "Customer" stage
↓ Backend
1. GET /crm/v3/objects/deals/{id}?associations=contacts
-> email, name, plan, account manager
2. Zendesk API: POST /api/v2/users (upsert by email)
-> name, email, user_fields: {hubspot_deal_id, plan, account_manager}
3. Optional: Zendesk: POST /api/v2/organizations
-> create company in Zendesk with HubSpot Company data
Zendesk Webhook: ticket.created / ticket.updated
↓ Backend
1. Get requester email from payload
2. HubSpot: GET /crm/v3/objects/contacts?email={email}
-> find contact, get associated deals
3. HubSpot: POST /crm/v3/objects/notes
-> Note on deal: "Ticket #{id}: {subject}. Status: {status}"
4. If priority = urgent:
-> HubSpot: PATCH /crm/v3/objects/deals/{id}
-> property active_ticket = true (for workflow trigger)
Zendesk REST API:
import requests
from requests.auth import HTTPBasicAuth
ZD_SUBDOMAIN = 'your-company'
ZD_EMAIL = 'admin@company.com'
ZD_TOKEN = 'your_api_token'
ZD_BASE = f'https://{ZD_SUBDOMAIN}.zendesk.com/api/v2'
ZD_AUTH = HTTPBasicAuth(f'{ZD_EMAIL}/token', ZD_TOKEN)
def upsert_zendesk_user(email: str, name: str, deal_id: str, plan: str) -> int:
# Search for existing user
resp = requests.get(
f'{ZD_BASE}/users/search',
params={'query': email},
auth=ZD_AUTH
)
users = resp.json().get('users', [])
user_payload = {
'user': {
'name': name,
'email': email,
'user_fields': {
'hubspot_deal_id': deal_id,
'plan': plan
}
}
}
if users:
# Update existing
user_id = users[0]['id']
requests.put(f'{ZD_BASE}/users/{user_id}', auth=ZD_AUTH, json=user_payload)
return user_id
else:
# Create new
resp = requests.post(f'{ZD_BASE}/users', auth=ZD_AUTH, json=user_payload)
return resp.json()['user']['id']
def get_ticket_details(ticket_id: int) -> dict:
resp = requests.get(f'{ZD_BASE}/tickets/{ticket_id}', auth=ZD_AUTH)
return resp.json()['ticket']
HubSpot: create a Note on the deal from a Zendesk ticket:
import requests as rq
HS_TOKEN = 'your_hubspot_private_app_token'
HS_BASE = 'https://api.hubapi.com'
HS_HEADERS = {'Authorization': f'Bearer {HS_TOKEN}', 'Content-Type': 'application/json'}
def create_ticket_note_on_deal(deal_id: str, ticket: dict):
note_body = (
f'Zendesk ticket #{ticket["id"]}: {ticket["subject"]}\n'
f'Status: {ticket["status"]} | Priority: {ticket["priority"]}\n'
f'Agent: {ticket.get("assignee_name", "unassigned")}'
)
payload = {
'properties': {
'hs_note_body': note_body,
'hs_timestamp': str(int(__import__('time').time() * 1000))
},
'associations': [
{
'to': {'id': deal_id},
'types': [{'associationCategory': 'HUBSPOT_DEFINED', 'associationTypeId': 214}]
}
]
}
rq.post(f'{HS_BASE}/crm/v3/objects/notes', json=payload, headers=HS_HEADERS)
Zendesk webhook setup:
Admin Center -> Apps and integrations -> Webhooks. The webhook receives events when a ticket is created or updated. Use Zendesk Triggers to set conditions — for example, send only tickets with the enterprise-client tag.
What the manager sees as a result
After the custom integration, the HubSpot deal card shows:
— A Note every time a new ticket is opened in Zendesk
— A Note on status change: “Ticket #1234 resolved”
— Property active_ticket = true while a ticket is open — can be used in workflows and filters
— In Zendesk the agent sees: customer plan, account manager name, HubSpot deal ID
Real-world case
SaaS company (EU market, 80 customers, HubSpot Professional + Zendesk Team):
- Before: native integration enabled. Managers thought they could see tickets — but they were not on the deal. Twice they made upsell calls to customers with active critical incidents. Support created Zendesk users without CRM data.
- After: custom integration via webhook. Every ticket is a Note on the deal. When
priority=urgent-> propertyurgent_ticket=true-> HubSpot Workflow pauses marketing emails and notifies the account manager in Slack. - Zendesk agents see the plan and account manager name in the side panel — 30% less time searching for context.
A similar one-way sync problem was described for HubSpot + Zoom: the native integration creates the appearance of data, but does not cover real scenarios.
Who this is relevant for
- HubSpot is used as the primary CRM and Zendesk as the helpdesk
- Account managers need to know the status of customer tickets before making a call
- Support must see CRM data: plan, account manager, deal stage
- Automation based on Zendesk events is needed (pause upsell during a critical incident)
Frequently asked questions
Why is the native HubSpot + Zendesk integration so limited?
Both platforms have competing products: HubSpot Service Hub — ticket tracker, Zendesk Sell — CRM. A full two-way integration reduces the incentive to purchase expensive tiers. The native integration provides baseline visibility, nothing more.
Zendesk API: Basic Auth or OAuth?
For server integrations — API Token via Basic Auth: email/token:api_token. OAuth is used for OAuth apps where a user authorizes access. API Token is simpler for server-to-server: Settings -> API -> Zendesk API -> Tokens -> Add API token.
Can Zendesk tickets be seen directly on the HubSpot deal card?
Native integration — no, only on the contact. Via custom integration: create Notes on the deal for each ticket event + use HubSpot Custom Properties (e.g., active_ticket_count) for display on the card and in lists.
Can HubSpot Workflows react to Zendesk events?
Via native integration — no. Via custom: Zendesk webhook -> backend -> update HubSpot property on the contact or deal -> this trigger is available in Workflows. Example: urgent_ticket = true -> send notification to the deal owner.
How much does a custom integration cost compared to native?
The native integration is free, included in the HubSpot App Marketplace. Custom — 2–3 weeks of development, webhook infrastructure maintenance. The question is not the cost of the integration but the cost of the problems from its absence: reputational risks from calling a customer during an active incident are hard to quantify, but they are real.
Summary
- Native HubSpot + Zendesk integration: one-way (Zendesk -> HubSpot), email only, contact timeline only
- Tickets are NOT visible on deal cards, names are NOT synced, they do NOT work as Workflow triggers
- Custom integration: Zendesk webhook -> Notes on deal + HubSpot properties for automation
- Reverse flow: HubSpot -> Zendesk, upsert user with plan and account manager data
- Typical development timeline — 2–3 weeks
If you use HubSpot and Zendesk and want to see tickets on deal cards and trigger automation — describe your scenarios. Exceltic.dev will review the webhook architecture and propose a solution for your support and sales workflow.