---
title: "Validate Webhook"
method: POST
path: "/api/v2/webhooks/validate"
tags: ["Webhooks"]
---

# Validate Webhook

`POST /api/v2/webhooks/validate`

## Request

- Base URL: `/` (relative, and the document was published on a file host, not at the API’s origin)
- URL: `/api/v2/webhooks/validate`
- Auth: HTTP bearer

Validates a webhook body against the same schema, URL rules, and body
template check used by POST /api/v2/webhooks. The webhook is **never
persisted**. Use this endpoint at plan time (e.g. from a Terraform
provider) to check that a webhook configuration is valid before
applying it. Name uniqueness is not checked.

## Request body

- WebhookInput: Webhook create/update body. `body`, `headers`, and `queryParams` only take effect for services that issue a templated HTTP request (`generic`, `incidentio`). The `slack` service posts a fixed payload to its incoming-webhook URL and ignores them, so supplying any of these fields on a `slack` webhook is rejected. `headers` and `queryParams` are write-only — they are accepted here but never returned by any read endpoint, so secrets such as auth tokens do not leak. On update (PUT), omitted readable fields (`description`, `titleEmoji`, `body`) are cleared, while omitted `headers`/`queryParams` are preserved — send an explicit `{}` to clear them. Exception: if the destination (`url` or `service`) changes, omitted `headers`/`queryParams` are cleared rather than preserved, so stored secrets are never forwarded to a new destination; re-supply them for the new destination.
  - `name` string, required: Webhook name. Must be unique per service within the team.
  - `service` 'slack' | 'incidentio' | 'generic', required: Webhook service type.
  - `url` string, uri, required: Webhook destination URL.
  - `description` string: Webhook description, shown in the UI.
  - `titleEmoji` boolean: Set to false to omit the state emoji prefix from notification titles sent through this webhook. Unset or true keeps the default prefix.
  - `body` string: Optional Handlebars request body template. Only for generic/incidentio; rejected for slack. Rejected with a 400 if it does not compile or calls a helper other than `eq` and the Handlebars built-ins.
  - `headers` object: Write-only. Custom HTTP headers sent with the webhook request. Never returned on read. Only for generic/incidentio; rejected for slack. Each value is capped at 4096 characters.
  - `queryParams` object: Write-only. Query parameters appended to the webhook URL. Never returned on read. Only for generic/incidentio; rejected for slack. Each value is capped at 4096 characters.

## Response `200`

Validation result. HTTP 200 is always returned for valid **and**
invalid bodies — a non-200 response means the request itself
failed (auth, server error, etc.).

- object
  - `valid` boolean, required: True when the body passes all validation rules.
  - `errors` object[], required: Validation errors. Empty when valid is true.
    - `path` string, required: Dot-separated field path, or empty string for top-level errors.
    - `message` string, required: Human-readable error description.
  - `normalized` object, nullable, required: The parsed webhook body, without the write-only `headers` and `queryParams`. Populated when valid is true, null when valid is false.

## Other responses

- `401`: Unauthorized
- `403`: Forbidden

## Changes

- **2026-11-02** `1514a6c7371e`: 1 info
  - added the new optional request property `titleEmoji`
- **2026-10-14** `de62620a0d2b`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/hyperdxio/apis/hyperdx-external-api/changes/api/v2/webhooks/validate/post.md)

---

[API](https://skmtc.dev/hyperdxio/apis/hyperdx-external-api.md) - [All operations](https://skmtc.dev/hyperdxio/apis/hyperdx-external-api/llms.txt) - [OpenAPI document](https://skmtc.dev/hyperdxio/apis/hyperdx-external-api/revisions/a7cac1e12b89?raw)
