HubSpot Tickets API

The HubSpot tickets API treats tickets as a standard CRM object, so it behaves like the rest of the CRM API. The traps are associations, retries and rate limits.

HubSpot tickets API authentication and scopes

For your own portal, create a private app and use its access token as a bearer token. For an integration other people install, use OAuth. Legacy API keys are gone, so if you find a tutorial using one, the tutorial is old and probably wrong elsewhere too.

Grant the narrowest scopes that work. A ticket integration usually needs read and write on tickets, plus read on contacts if it resolves people, plus whatever association scopes your calls require. Over-scoping a private app is a real security exposure and nobody audits it after go-live.

Store the token as a secret, rotate it when someone leaves, and never let it near client-side code. Obvious, routinely ignored.

Creating and updating tickets

Tickets sit under the CRM objects API, so you POST a properties payload to the tickets object endpoint and PATCH the same object by id to update it. If you want the conceptual version first, start with what a HubSpot ticket is and the four ways to create one.

The properties you'll almost always set:

subject, the ticket name.
content, the description or first message.
hs_pipeline and hs_pipeline_stage, both of which take internal ids rather than the labels you see in the UI. Fetch them from the pipelines endpoint once and store them in config, because typing an id from a screenshot is how integrations break silently after someone edits a pipeline.
hs_ticket_priority, if you use it.
Your own custom properties, by internal name. Internal names aren't labels, and they don't change when someone renames the field in the UI, which is the whole point of them.

Send dates as the format the current API expects and don't improvise, and remember enumerated properties take the option internal value, not the display label.

Associations are the part people forget

A ticket with no contact association is an orphan. It doesn't appear in the customer history, it won't be found by anyone looking at the account, and your reporting under-counts that customer forever.

Create the association in the same operation as the ticket where the API allows it, or immediately after with the associations endpoint. Do not leave it to a nightly job.

Resolve the contact before you create the ticket. Search by email, use the existing record if it exists, and only create a contact if it genuinely does not. Integrations that create a contact per ticket are the single largest manufacturer of duplicate records I have seen in real HubSpot portals, and every duplicate contact splits a customer history in half.

Search, batching and rate limits

Three operational realities to design around rather than discover in production.

Batch endpoints exist and you should use them. Creating or updating records in batches rather than looping single calls is the difference between an import that finishes and one that spends the afternoon being throttled.
The search endpoint has its own tighter limit than the standard object endpoints, and it's also eventually consistent. A record you just created may not appear in a search result immediately, so never build a "does this exist" check that depends on searching for something you wrote a second ago.
Rate limits are per app, over a short rolling window, with a daily cap that varies by tier. The exact figures move, so read the current documentation rather than a blog post, including this one. Handle 429 responses with exponential backoff and respect the retry headers.

For anything volume-heavy, prefer webhooks over polling. Polling a queue every minute for changes is how a well-behaved integration turns into a rate limit problem.

The retry trap

This one deserves its own section because it causes more mess than every other mistake combined.

Your integration posts a ticket. The request times out at the network layer, but HubSpot processed it. Your code retries. Now there are two identical tickets, and both are real, and neither is marked as a copy.

Two defences. Store your own external reference on a custom property and check for it before creating, accepting that search is eventually consistent so you also need the second defence. And make the retry logic itself idempotent: a request that has already succeeded from HubSpot side should not be reissued blindly just because your client didn't hear back.

Every deduplication problem I have traced back through an API integration started with a timeout and a well-meaning retry.

What the API won't decide for you

The endpoints do exactly what you tell them. Everything interesting is a judgement call you have to make in your own code.

Whether a ticket is a duplicate. There is no similarity check. If you want one, you write it.
Which contact a message belongs to when the email address is new but the person is not.
What the category should be. The API stores it. Deciding it's your problem.
Whether to merge. Ticket merging in HubSpot is a UI action, two records at a time, permanent. Do not design a bulk cleanup on the assumption that you can drive it programmatically without checking the current API reference first.
FAQ

Frequently asked questions

Which endpoint creates a ticket?

POST to the CRM objects tickets path. The HubSpot API create ticket call is the same shape as any other object in the HubSpot CRM tickets API, and the HubSpot API tickets endpoint expects properties plus associations.

How do I authenticate with the HubSpot tickets API?

A private app access token as a bearer token for your own portal, or OAuth for an installable integration. Legacy API keys are no longer supported.

Can I create a ticket and associate a contact in one call?

The CRM objects API supports associations at creation on current versions, and you can also use the associations endpoint straight after. Either way, do it immediately, because orphan tickets never make it into a customer history.

What are the HubSpot API rate limits for tickets?

Limits apply per app over a short rolling window plus a daily cap that varies by subscription tier, and search has its own tighter limit. The exact numbers change, so read the current developer documentation and handle 429s with backoff.

Can I merge tickets through the HubSpot API?

Ticket merging in HubSpot is a UI action from the Actions menu, two records at a time, and it can't be undone. Check the current API reference before assuming any of that's scriptable.

Why is my integration creating duplicate tickets?

Almost always a retry after a timeout on a request that actually succeeded. Store an external reference on a custom property, check it before creating, and make the retry path idempotent.

When the integration doubles up

A timeout and a retry produce two identical tickets that nothing flags. Ticket Merger finds and merges them automatically on Zendesk and Freshdesk today, and HubSpot support is on the roadmap.

Start free trial

14-day free trial. No credit card required.