> For the complete documentation index, see [llms.txt](https://docs.ebbot.ai/ebbot-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ebbot.ai/ebbot-docs/integrations/automations-integrations/integration-setup-guides/hubspot-integration-in-automations/incoming-hubspot-ticket-webhook.md).

# Incoming HubSpot Ticket Webhook

**Trigger identifier:** `incoming_hubspot_ticket_webhook`.

Starts a workflow from HubSpot ticket events. HubSpot sends events to the callback of an installed trigger; the connector verifies the request, applies the event-type filter and dispatches each matching event separately.

## Install the trigger

1. Create a [HubSpot connection](/ebbot-docs/integrations/automations-integrations/integration-setup-guides/hubspot-integration-in-automations/connection-setup.md), including its client secret.
2. Create an instance of this trigger in Automations and select the connection.
3. Set the event-type filter described below and note the installed trigger's callback URL.
4. Open the matching HubSpot app's Webhooks settings and set its target URL to your trigger's callback URL. See **Callback URL and subscription ID** below for the exact URL format and which ID to use.
5. Enable the required HubSpot ticket subscriptions. For property-change subscriptions, select the properties your workflow needs.
6. Send a test event or perform a controlled ticket operation. Verify a run with the expected ticket ID and event fields. Merely saving the URL does not create an event.

Multiple event subscriptions can share the app's target URL. Configure both sides: the HubSpot subscription controls what is sent; the trigger option controls what is dispatched to the workflow.

## Callback URL and subscription ID

Example target URL, using a fictitious subscription ID:

```
https://hubspot.wf.ebbot.eu/hubspot-ticket-events/12345678-1234-4123-8123-123456789abc
```

The URL consists of:

| Part                                   | Meaning                                            |
| -------------------------------------- | -------------------------------------------------- |
| `https://hubspot.wf.ebbot.eu`          | The HubSpot Workflow Server address                |
| `/hubspot-ticket-events/`              | The endpoint that receives HubSpot ticket webhooks |
| `12345678-1234-4123-8123-123456789abc` | An example Ebbot **trigger subscription ID**       |

The server calls the final path parameter `subscriptionId`. Use the subscription ID shown after installing your trigger in Automations. It identifies the installed Ebbot trigger subscription whose connection settings and event filter the server uses, and to which it dispatches matching events.

HubSpot also calls its event registrations *subscriptions*. Their IDs are separate from the Ebbot subscription ID in this URL. The URL does not take a HubSpot ticket ID or an Automations workflow ID.

For your setup, use:

```
https://hubspot.wf.ebbot.eu/hubspot-ticket-events/<YOUR-EBBOT-TRIGGER-SUBSCRIPTION-ID>
```

Replace the final placeholder with your installed trigger's subscription ID; do not reuse the example UUID. Use the callback host provided for your environment if it differs from the address above.

## Trigger option

| Field                            | Default      | Accepted configuration values                                                                       |
| -------------------------------- | ------------ | --------------------------------------------------------------------------------------------------- |
| `event_type` / Event Type Filter | Empty string | `ticket.creation`, `ticket.propertyChange`, `ticket.deletion`, `ticket.associationChange`, or empty |

A non-empty filter dispatches only exact matches. Empty disables event-type filtering for the receiving subscription. Use explicit downstream eligibility checks rather than assuming that an empty filter protects against unrelated events.

This option does **not** filter by property name, property value, source or owner. Add those conditions in the workflow.

## Output

| Field            | Type   | Meaning                                               |
| ---------------- | ------ | ----------------------------------------------------- |
| `id`             | string | Ticket object ID, converted from HubSpot's `objectId` |
| `event_type`     | string | HubSpot `subscriptionType`                            |
| `property_name`  | string | `propertyName`, or empty if absent                    |
| `property_value` | string | `propertyValue`, or empty if absent                   |
| `change_source`  | string | `changeSource`, or empty if absent                    |
| `source_id`      | string | `sourceId`, or empty if absent                        |

The dispatched output does not expose the raw `occurredAt`, event ID, retry attempt or portal ID. A subsequent Get Ticket reads the **current** record; it may already differ from the value carried by this event.

Illustrative output, using synthetic identifiers:

```json
{
  "id": "123456",
  "event_type": "ticket.propertyChange",
  "property_name": "hs_pipeline_stage",
  "property_value": "YOUR_STAGE_ID",
  "change_source": "CONVERSATIONS",
  "source_id": ""
}
```

Do not reuse the example stage value. Read actual values in the connected portal.

## Prevent a flow from reacting to its own writes

One ticket operation can produce several property-change events. A flow that writes status can generate events that would otherwise start the same logic again.

Put eligibility conditions before expensive classification and writes:

1. Check the relevant `event_type` and `property_name`.
2. Check `change_source` and, when justified by observed events, `source_id`.
3. Read the ticket and check the solution's ownership/state convention.
4. Identify the actual message or change being acted on.
5. Perform the intended action only when all conditions hold.

For example, a solution following conversation-originated status changes might require `property_name = hs_pipeline_stage` and `change_source = CONVERSATIONS`, then its automation-owner check. These values describe an example business design, not a universal HubSpot rule. `CONVERSATIONS` identifies a source subsystem, not proof that a particular end customer authored the event.

A run ending without action can be expected. These conditions do not deduplicate qualifying events or provide exactly-once execution. See [Workflow patterns](/ebbot-docs/integrations/automations-integrations/integration-setup-guides/hubspot-integration-in-automations/workflow-patterns.md).

## Request validation and delivery limits

The endpoint requires `X-HubSpot-Signature-v3` and `X-HubSpot-Request-Timestamp`. It verifies the signature with the connection's client secret and the public callback URL. It rejects stale timestamps; the documented implementation permits a five-minute age window with a small clock-skew tolerance.

Missing/invalid signature headers or a rejected timestamp return 401. Missing configured client secret is a server-configuration error. Invalid JSON or a body that is not an array returns 400.

Events arrive in a batch. Matching events are dispatched separately; filtered events are counted as ignored. The acknowledgement contains `status`, `dispatched` and `ignored`. A batch acknowledgement is not proof that each workflow completed: malformed entries can be skipped and dispatch failures are logged while the batch still receives an acknowledgement. Verify the individual Automations run when diagnosing missing work.

See [Troubleshooting](/ebbot-docs/integrations/automations-integrations/integration-setup-guides/hubspot-integration-in-automations/troubleshooting.md) for callback, authentication and repeated-event checks.
