Webhook (HTTP POST 2, Jinja)

Webhook (HTTP POST 2, post2)

Same idea as the simple HTTP POST webhook, but post2 lets you use Jinja2 in http_post2_payload and http_post2_headers so values can reference fields from the match (including nested keys via _data and jinja_root_name).

In YAML key/value form, prefer single quotes around values that contain Jinja so parsing stays predictable.

Options walks through each post2 key; Full working example at the bottom is a complete rule that shows Jinja in the payload and headers.

Options

Keys below match the ElastAlert 2 alerter. Shared rule fields such as alert_subject apply as described in Subject & body. Example fragments from the ElastAlert 2 reference appear indented under the option they illustrate (add your own name, type, index, and filter to make a full rule).

Required

  • http_post2_url — The URL to POST.

Incorrect usage with double quotes

 alert: post2
 http_post2_url: "http://example.com/api"
 http_post2_payload:
   # this will result in an error as " is escaped to \"
   description: 'hello {{ _data["name"] }}'
   # this will result in an error as " is escaped to \"
   state: '{{ ["low","medium","high","critical"][event.severity] }}'
 http_post2_headers:
   authorization: Basic 123dr3234
   X-custom-type: '{{type}}'

Correct usage with single quotes

 alert: post2
 http_post2_url: "http://example.com/api"
 http_post2_payload:
   description: hello {{ _data['name'] }}
   state: "{{ ['low','medium','high','critical'][event.severity] }}"
 http_post2_headers:
   authorization: Basic 123dr3234
   X-custom-type: '{{type}}'

Example usage

 alert: post2
 http_post2_url: "http://example.com/api"
 http_post2_payload:
   description: "An event came from IP {{clientip}}"
   username: "{{user.name}}"
 http_post2_raw_fields:
   ip: clientip
 http_post2_headers:
   authorization: Basic 123dr3234
   X-custom-type: '{{type}}'

Example usage with json string formatting

 alert: post2
 jinja_root_name: _new_root
 http_post2_url: "http://example.com/api"
 http_post2_payload: |
   {
     "description": "An event came from IP {{ _new_root["client.ip"] }}",
     "username": "{{ _new_root['username'] }}"
     {%- for k, v in some_field.items() -%}
     ,"{{ k }}": "changed_{{ v }}"
     {%- endfor -%}
   }
 http_post2_raw_fields:
   ip: clientip
 http_post2_headers: |
   {
     "authorization": "Basic 123dr3234",
     "X-custom-{{key}}": "{{type}}"
   }

Optional

  • http_post2_payload — A JSON string or list of key:value pairs to use for the HTTP POST payload. You can use {{ field }} (Jinja2 template) in both keys and values to reference any field in matched events (including nested ES fields and nested payload keys). If not defined, all Elasticsearch keys are sent. Example: "description_{{ my_field }}": "Type: {{ type }}\nSubject: {{ title }}". When field names use dot notation or reserved characters, _data can be used to access them. If _data conflicts with your top-level data, use jinja_root_name to change its name.

  • http_post2_raw_fields — List of key:value pairs to use as POST content. Example: ip: clientip maps the clientip Elasticsearch field to the JSON key ip. This field overwrites keys with the same name in http_post2_payload.

  • http_post2_headers — A JSON string or list of key:value pairs to use as HTTP POST headers. You can use {{ field }} (Jinja2 template) in both keys and values to reference matched-event fields (including nested fields). Example: "Authorization": "{{ user }}". Headers "Content-Type": "application/json" and "Accept": "application/json;charset=utf-8" are present by default; override them only if needed. When field names use dot notation or reserved characters, _data can be used to access them. If _data conflicts with your top-level data, use jinja_root_name to change its name.

  • http_post2_proxy — Proxy URL, if required. Only HTTPS is supported.

  • http_post2_all_values — Boolean of whether or not to include every key value pair from the match in addition to those in http_post2_payload and http_post2_static_payload. Defaults to True if http_post2_payload is not specified, otherwise False.

  • http_post2_timeout — The timeout value, in seconds, for making the post. The default is 10. If a timeout occurs, the alert will be retried next time elastalert cycles.

  • http_post2_ca_certs — Set this option to True or a path to a CA cert bundle or directory (eg: /etc/ssl/certs/ca-certificates.crt) to validate the SSL certificate.

  • http_post2_ignore_ssl_errors — By default ElastAlert 2 verifies the TLS certificate. Set to True to skip verification. Note: Disabling verification exposes the rule to man-in-the-middle risk on untrusted networks—use only for debugging or when you explicitly trust the endpoint (for example a private CA you control).

Full working example

name: Example custom webhook (HTTP POST 2)
type: any
index: "*-*"
filter:
  - query:
      query_string:
        query: "level:error OR log.level:error"
alert:
  - "post2"
http_post2_url: "https://your-service.example/hooks/elastalert"
http_post2_payload:
  source: logit
  summary: "Error from ElastAlert rule"
http_post2_raw_fields:
  host: host.name
http_post2_headers:
  Content-Type: application/json

Use Jinja in payload or header values when you need match data, for example summary: '{{ host.name }}' or keys like description_{{ type }} (see ElastAlert 2 rules for quoting).