> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-parallel-read-in-order-multi-part.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Validate Webhook

> 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.




## OpenAPI

````yaml https://raw.githubusercontent.com/hyperdxio/hyperdx/refs/heads/main/packages/api/openapi.json post /api/v2/webhooks/validate
openapi: 3.0.0
info:
  title: HyperDX External API
  description: API for managing HyperDX alerts and dashboards
  version: 2.0.0
servers:
  - url: /
    description: Your HyperDX instance (http://<host>:<port>)
security:
  - BearerAuth: []
tags:
  - name: Dashboards
    description: Endpoints for managing dashboards and their visualizations
  - name: Alerts
    description: Endpoints for managing monitoring alerts
  - name: Charts
    description: Endpoints for querying chart data
  - name: Connections
    description: Endpoints for managing ClickHouse connections
  - name: Sources
    description: Endpoints for managing data sources
  - name: Webhooks
    description: Endpoints for managing webhooks
  - name: Search
    description: Endpoints for querying raw data from log and trace sources
paths:
  /api/v2/webhooks/validate:
    post:
      tags:
        - Webhooks
      summary: Validate Webhook
      description: |
        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.
      operationId: validateWebhook
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookInput'
      responses:
        '200':
          description: |
            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.).
          content:
            application/json:
              schema:
                type: object
                required:
                  - valid
                  - errors
                  - normalized
                properties:
                  valid:
                    type: boolean
                    description: True when the body passes all validation rules.
                  errors:
                    type: array
                    description: Validation errors. Empty when valid is true.
                    items:
                      type: object
                      required:
                        - path
                        - message
                      properties:
                        path:
                          type: string
                          description: >-
                            Dot-separated field path, or empty string for
                            top-level errors.
                        message:
                          type: string
                          description: Human-readable error description.
                  normalized:
                    type: object
                    nullable: true
                    description: |
                      The parsed webhook body, without the write-only
                      `headers` and `queryParams`. Populated when valid is
                      true, null when valid is false.
              examples:
                valid:
                  summary: Valid webhook body
                  value:
                    valid: true
                    errors: []
                    normalized:
                      name: Alerts
                      service: generic
                      url: https://example.com/webhooks/alerts
                      body: '{"alert": "{{title}}"}'
                invalid:
                  summary: Body template that does not compile
                  value:
                    valid: false
                    errors:
                      - path: body
                        message: >-
                          Invalid webhook body template (line 1, column 12):
                          Parse error on line 1: ...
                    normalized: null
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                message: Unauthorized access. API key is missing or invalid.
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    WebhookInput:
      type: object
      required:
        - name
        - service
        - url
      description: |
        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`, `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.
      properties:
        name:
          type: string
          maxLength: 1024
          description: Webhook name. Must be unique per service within the team.
          example: Production Alerts
        service:
          type: string
          enum:
            - slack
            - incidentio
            - generic
          description: Webhook service type.
          example: slack
        url:
          type: string
          format: uri
          maxLength: 2048
          description: Webhook destination URL.
          example: >-
            https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
        description:
          type: string
          maxLength: 2048
          description: Webhook description, shown in the UI.
          example: 'Sends critical alerts to the #incidents channel'
        body:
          type: string
          maxLength: 16384
          description: >-
            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.
          example: '{"alert": "{{title}}", "severity": "{{level}}"}'
        headers:
          type: object
          maxProperties: 100
          description: >-
            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.
          additionalProperties:
            type: string
            maxLength: 4096
          example:
            Authorization: Bearer secret-token
        queryParams:
          type: object
          maxProperties: 100
          description: >-
            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.
          additionalProperties:
            type: string
            maxLength: 4096
    Error:
      type: object
      properties:
        message:
          type: string
          description: Human-readable error message.
          example: 'NOT_FOUND: Alert not found'
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API Key

````