> For the complete documentation index, see [llms.txt](https://docs.enate.net/enate-help/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.enate.net/enate-help/integrations/enate-integrations/webhooks/api-webhook-subscription.md).

# API Webhook Subscription

Webhook subscriptions are managed entirely through the API. There's no screen for them in Builder or Work Manager.

Two **GET** operations and three **POST** operations are available under Webhook Subscription. These are the APIs you use to create, view, amend and remove your Webhook subscriptions.

![](https://3859925423-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MWYnDNwe3Cuo4zlGbs5%2F-MWnb30vDLQE7_ULyA2F%2F-MWnb6C1NkNl5Kwq6Mgs%2Fimage.png?alt=media\&token=78c0c101-2c53-4b24-98f0-abcedaea719a)

### Which API to Use

These operations live in the **Configuration API**, alongside the rest of Enate's configuration endpoints. The base address for your instance is the same one you use for the Configuration Swagger page:

```
https://yourplatform/configuration/WebHookSubscription/<operation>
```

See the APIs page for how to find your Swagger URL and how to authenticate with Application Credentials.

#### API versions

The Configuration API is versioned, and you choose a version with the `api-version` query string parameter:

```
https://yourplatform/configuration/WebHookSubscription/GetAllWebhookSubscriptions?api-version=3
```

| Version | `api-version` value | Status                                                                        |
| ------- | ------------------- | ----------------------------------------------------------------------------- |
| 1       | `1`                 | Available, superseded                                                         |
| 2       | `2`                 | Available, superseded                                                         |
| 3       | `3`                 | Current. This is the version you get if you don't supply `api-version` at all |
| 4       | `4-preview`         | Published as a preview version                                                |

All five operations behave the same way across versions 1 to 4. The differences are in the shared API version conventions rather than in the Webhook subscription operations themselves.

{% hint style="info" %}
Note: the older 2024.1 legacy Enate API also exposes Webhook subscriptions, but only **SubscribeToWebhook** and **Unsubscribe**. The Get, Get all and Update operations aren't available there. Use the Configuration API if you need them. There's one other behavioural difference, covered under Subscribing to an event on a closed work item.
{% endhint %}

#### A note on JSON format

Requests and responses use PascalCase field names, and enumerations are sent and returned as **integer values, not names**. Send `"Webhook": 0`, not `"Webhook": "PacketCreated"`. The Configuration API rejects a request that supplies an enumeration as a string.

### GET Operations <a href="#get-all-webhook-subscriptions" id="get-all-webhook-subscriptions"></a>

* Get All Webhook Subscriptions - use this to list the Webhook subscriptions in your Enate instance.
* Get Webhook Subscription - use this to get the detail of one subscription.

#### Get All Webhook Subscriptions <a href="#get-all-webhook-subscriptions-2" id="get-all-webhook-subscriptions-2"></a>

Path: `/WebHookSubscription/GetAllWebhookSubscriptions`

* Type: GET
* Function: returns every Webhook subscription in your Enate instance, not just the ones your account created
* No parameters required
* Response code: 200

Each subscription in the list has these fields:

| Field                 | Type          | Required/Optional                             | Description                                                                                                                                                                       |
| --------------------- | ------------- | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **GUID**              | String (GUID) | Always present                                | The identifier of the subscription. Use it for Get, Update and Unsubscribe.                                                                                                       |
| **Webhook**           | Integer       | Always present                                | The event subscribed to. 0 = PacketCreated, 1 = PacketUpdated, 2 = NewCommunication, 3 = BusinessObjectCreated, 4 = SpecificBusinessObjectUpdated, 5 = BusinessObjectTypeUpdated. |
| **FilterObjectGUID**  | String (GUID) | Null for type-scoped subscriptions            | The object the subscription is scoped to.                                                                                                                                         |
| **FilterObjectType**  | Integer       | Always present                                | The type of object being filtered by, from the EnateObjects enum.                                                                                                                 |
| **SubscriberURL**     | String        | Always present                                | The URL Enate posts messages to.                                                                                                                                                  |
| **Signature**         | String (GUID) | Always present                                | The value Enate sends in the `x-enate-signature` header for this subscription.                                                                                                    |
| **CustomHeader**      | String        | Empty when no custom header was supplied      | The custom HTTP header name, with spaces replaced by hyphens.                                                                                                                     |
| **CustomHeaderValue** | String        | Null when no custom header value was supplied | The value sent in the custom header.                                                                                                                                              |

Expected response, a list of subscriptions in the following format:

```json
[
  {
    "GUID": "c14a9f02-6b53-4d88-b0e7-91f3a2c5d640",
    "Webhook": 0,
    "FilterObjectGUID": "3b5e7c9a-0d21-4e68-9f14-7c2a8b6d5e03",
    "FilterObjectType": 31,
    "SubscriberURL": "https://integrations.globex.example.com/enate/new-work-items",
    "Signature": "7e41b0c6-5a82-4f39-9d17-0b6c38e2a541",
    "CustomHeader": "Globex-source",
    "CustomHeaderValue": "enate-packet-created"
  },
  {
    "GUID": "9d2f61b8-3c47-4a05-8e93-25fb70c4a1de",
    "Webhook": 2,
    "FilterObjectGUID": "878409be-7886-eb11-b9ad-e86a64437383",
    "FilterObjectType": 81,
    "SubscriberURL": "https://integrations.globex.example.com/enate/communications",
    "Signature": "b6083d1f-47c2-4e5a-a930-1c8de4f60b27",
    "CustomHeader": "",
    "CustomHeaderValue": null
  }
]
```

#### Get Webhook Subscription <a href="#get-webhook-subscription" id="get-webhook-subscription"></a>

Path: `/WebHookSubscription/GetWebhookSubscription`

* Type: GET
* Function: returns the detail of a single Webhook subscription
* Parameter to set: `webhookSubscriptionGUID`, passed in the query string
* Parameter value: the GUID returned when the subscription was created

Example request:

```
GET https://yourplatform/configuration/WebHookSubscription/GetWebhookSubscription?webhookSubscriptionGUID=c14a9f02-6b53-4d88-b0e7-91f3a2c5d640&api-version=3
```

Response code 200, returning a single subscription with the fields listed above:

```json
{
  "GUID": "c14a9f02-6b53-4d88-b0e7-91f3a2c5d640",
  "Webhook": 0,
  "FilterObjectGUID": "3b5e7c9a-0d21-4e68-9f14-7c2a8b6d5e03",
  "FilterObjectType": 31,
  "SubscriberURL": "https://integrations.globex.example.com/enate/new-work-items",
  "Signature": "7e41b0c6-5a82-4f39-9d17-0b6c38e2a541",
  "CustomHeader": "Globex-source",
  "CustomHeaderValue": "enate-packet-created"
}
```

If no subscription exists with that GUID, the response code is 404.

### POST Operations

* Subscribe to Webhook - create a new subscription.
* Update Webhook Subscription - amend an existing subscription.
* Unsubscribe - permanently delete a subscription.

#### Subscribe to Webhook API <a href="#subscribe-to-webhook-api" id="subscribe-to-webhook-api"></a>

Path: `/WebHookSubscription/SubscribeToWebhook`

* Type: POST
* Function: creates a new subscription and returns the details of the subscription created

The request body takes these fields:

| Field                 | Type          | Required/Optional                                                                                                   | Description                                                                                          |
| --------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| **Webhook**           | Integer       | Required                                                                                                            | The event to subscribe to, sent as its integer value.                                                |
| **FilterObjectType**  | Integer       | Required                                                                                                            | The type of object being filtered by, from the EnateObjects enum.                                    |
| **FilterObjectGUID**  | String (GUID) | Required for PacketCreated, PacketUpdated, NewCommunication and SpecificBusinessObjectUpdated. Not used by the rest | The object to scope the subscription to.                                                             |
| **SubscriberURL**     | String        | Required                                                                                                            | An absolute `http` or `https` URL that can receive the Webhook message.                              |
| **CustomHeader**      | String        | Optional                                                                                                            | A custom HTTP header name to add to every message. Spaces are replaced with hyphens when it's saved. |
| **CustomHeaderValue** | String        | Optional                                                                                                            | The value to send in that custom header.                                                             |

Request body:

```json
{
  "Webhook": 0,
  "FilterObjectGUID": "3b5e7c9a-0d21-4e68-9f14-7c2a8b6d5e03",
  "FilterObjectType": 31,
  "SubscriberURL": "https://integrations.globex.example.com/enate/new-work-items",
  "CustomHeader": "Globex source",
  "CustomHeaderValue": "enate-packet-created"
}
```

Response code 200, with the new subscription under `Result`:

```json
{
  "Result": {
    "GUID": "c14a9f02-6b53-4d88-b0e7-91f3a2c5d640",
    "Webhook": 0,
    "FilterObjectGUID": "3b5e7c9a-0d21-4e68-9f14-7c2a8b6d5e03",
    "FilterObjectType": 31,
    "SubscriberURL": "https://integrations.globex.example.com/enate/new-work-items",
    "Signature": "7e41b0c6-5a82-4f39-9d17-0b6c38e2a541",
    "CustomHeader": "Globex-source",
    "CustomHeaderValue": "enate-packet-created"
  },
  "Messages": []
}
```

Two things to note in that response. `Signature` is generated by Enate and is the value it will send in the `x-enate-signature` header of every message for this subscription, so store it. And `CustomHeader` came back as `Globex-source`, because spaces in a header name are replaced with hyphens.

If validation fails, the response code is 400, `Result` is null, and `Messages` holds the reasons. This is the response to a request whose `SubscriberURL` was `globex-integrations` rather than a full URL:

```json
{
  "Result": null,
  "Messages": [
    {
      "IsError": true,
      "MessageDescription": "The supplied subscription URL is not valid.",
      "Parameters": [],
      "RelatedObjectGUID": "0198f4c2-7a61-7d3e-9b05-6c41e8d23f7a",
      "RelatedObjectType": 990,
      "MessageID": 990296
    }
  ]
}
```

`RelatedObjectType` 990 is the Webhook Subscription object type, and `MessageID` identifies the specific rule that failed. `MessageDescription` is the readable form of the same thing, with any values substituted into it from `Parameters`. `RelatedObjectGUID` is the identifier Enate allocated to the subscription it was trying to create. Because the request failed, nothing was saved under it, so there's no point storing it.

See Rules Applied When You Subscribe for the full set of checks and the message each one produces.

{% hint style="info" %}
Note: the subscriber URL is the address of the system that will receive the Webhook messages. If you just want to see what a message looks like before you build anything, a request bin service such as <https://webhook.site/> will give you a URL you can point a subscription at.
{% endhint %}

**Subscribing to an event on a closed work item**

You can't create a **PacketUpdated** subscription against a work item that is already Closed. The two APIs handle the attempt differently:

| API                          | What happens                                                                       |
| ---------------------------- | ---------------------------------------------------------------------------------- |
| Configuration API (v1 to v4) | Response code 400, with the body `Cannot create subscription for a closed packet.` |
| 2024.1 legacy API            | Response code 200 with no validation messages, but no subscription is created      |

If you're using the legacy API, check for the subscription afterwards rather than relying on the 200.

#### Update Webhook Subcription <a href="#update-webhook-subcription" id="update-webhook-subcription"></a>

Path: `/WebHookSubscription/UpdateWebhookSubscription`

* Type: POST
* Function: amends an existing subscription

The request body is the same as SubscribeToWebhook plus the `GUID` of the subscription to update:

```json
{
  "GUID": "c14a9f02-6b53-4d88-b0e7-91f3a2c5d640",
  "Webhook": 0,
  "FilterObjectGUID": "3b5e7c9a-0d21-4e68-9f14-7c2a8b6d5e03",
  "FilterObjectType": 31,
  "SubscriberURL": "https://integrations.globex.example.com/enate/v2/new-work-items",
  "CustomHeader": "Globex source",
  "CustomHeaderValue": "enate-packet-created"
}
```

The response has the same shape as SubscribeToWebhook.

{% hint style="warning" %}
**Updating a subscription does not change its signature.** The signature is generated once, when the subscription is created, and stays the same for the life of that subscription. If you need a new signature, unsubscribe and subscribe again.
{% endhint %}

This operation isn't available in the 2024.1 legacy API. To change a subscription there, unsubscribe and create a new one.

#### Unsubscribe (Delete Webhook Subscription) <a href="#delete-webhook-subscription" id="delete-webhook-subscription"></a>

Path: `/WebHookSubscription/Unsubscribe`

* Type: POST
* Takes a Webhook subscription GUID as the only parameter, passed in the query string
* Permanently deletes the subscription. There's no retire or deactivate option, and no reactivation. To start receiving the event again you create a new subscription, which gets a new GUID and a new signature

Example request:

```
POST https://yourplatform/configuration/WebHookSubscription/Unsubscribe?webHookSubscriptionGUID=c14a9f02-6b53-4d88-b0e7-91f3a2c5d640&api-version=3
```

Response code 200:

```json
{
  "Result": true,
  "Messages": []
}
```

### General API Validations <a href="#general-api-validations" id="general-api-validations"></a>

#### Authorization <a href="#authorization" id="authorization"></a>

Every one of these operations requires an authenticated account with a Builder role. A request with no bearer token, or with an expired one, is rejected with a 401. A request from an account that's authenticated but doesn't hold a Builder role is rejected with a 403.

![](https://3859925423-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MWYnDNwe3Cuo4zlGbs5%2F-MWnb30vDLQE7_ULyA2F%2F-MWnc1MM21rFTndNjZ3c%2Fimage.png?alt=media\&token=0c85f281-0743-4b6e-ab0e-c4caf7e14a60)

Quick steps to check authorization behaviour:

1. Open the Swagger UI.
2. Don't log in to the test instance.
3. Send a request with all the valid details.
4. The API rejects the request as unauthorized.
5. Log in to the test instance.
6. Retry the same request.
7. The API returns a successful response, because the request is now authorized.

#### Invalid Requests <a href="#invalid-requests" id="invalid-requests"></a>

An invalid request returns a 400 Bad Request. There are two kinds:

* The request body couldn't be read at all, for example malformed JSON, an enumeration supplied as a string, or a field the API doesn't recognise. You get a 400 with no `Messages` array.
* The request was read but failed Enate's validation rules. You get a 400 with the reasons in the `Messages` array, as shown under Subscribe to Webhook API.

![](https://3859925423-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MWYnDNwe3Cuo4zlGbs5%2F-MWnb30vDLQE7_ULyA2F%2F-MWnc8YyoAVD60fvx_8F%2Fimage.png?alt=media\&token=8dedc586-05c9-4710-8d86-519259e2dd0e)

Common causes of a bad request:

* An incorrect GUID value
* Syntax errors in the request JSON
* An enumeration value Enate doesn't recognise


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.enate.net/enate-help/integrations/enate-integrations/webhooks/api-webhook-subscription.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
