Webhook alert method
The webhook alert method sends alerts through an HTTP callback handler that is triggered by an event. You can create webhooks and configure them to handle different incident notifications using either custom or predefined notification templates.
Adding the Webhook alert method
Alternatively, utilize the SLOs-as-code approach by:
- Applying an alert method YAML configuration with the
sloctl applycommand. - Configuring the Webhook alert method definition programmatically using the Nobl9 Terraform provider.
Nobl9 Web
To set up the alert method on the Nobl9 Web, follow these steps:
- Navigate to Integrations > Alert methods.
- Click
.
- Select Webhook.
-
Enter the URL (mandatory).
Your webhook endpoint HTTP POST requests will be sent to.
The URL must start withhttps://. -
Select a Project (mandatory).
Projects provide the structure for organizing Nobl9 resources and managing access permissions.
If a project is not specified, Nobl9 assigns the default project value automatically. -
Enter a Display Name (optional).
Spaces are allowed. -
Enter a Name (mandatory).
It can only contain lowercase, alphanumeric characters, and dashes (for example,my-alert-method-1). Nobl9 auto-populates this field based on the display name you enter, transforming it into the supported format. You can edit the result. -
Enter a Description (optional).
Provide extra details, such as the purpose and responsible personnel.
Up to 1050 characters. -
In the Custom headers block, you can add customized headers to be sent along with Webhook notifications (optional). To add a custom header:
- Click
.
- Enter Key and Value
- For Key, use only letters, numbers, hyphens (-), and underscores (_). It must start with a letter or number.
- Click
-
Configure Notification details to define the response payload details (mandatory):
-
Nobl9: select at least one field from the list of predefined details.
-
Custom: create a custom payload or click Insert to use templated field values. Only JSON is accepted:
- Enclose each field name in double quotes (
"<field_name>") - Indicate variables with
$, use lowercase letters, and separate words with_ - When you expect to receive an array, add square brackets (
[]) after the value
For example{"policy": $alert_policy_conditions[],"message": "Your SLO $slo_name needs attention!"} - Enclose each field name in double quotes (
-
- Click Add alert method
YAML configuration
YAML for the webhook integration supports custom notification message templates. The template can be specified in two ways:
- Only variables are specified, and the notification message is generated automatically
- A full message template is specified, with variables in the form
$<variable_name>
- YAML
- Example with variables
- Full message template example
apiVersion: n9/v1alpha
kind: AlertMethod
metadata:
name: string # Mandatory
displayName: string # Optional
project: default # Mandatory
# Optional
# The key value: only alphanumeric characters, `-`, `_`, or `.` are allowed.
# The key value must start and end with an alphanumeric character.
# An optional DNS subdomain prefix followed by `/` is allowed.
annotations:
key: value
spec:
description: string # Optional
webhook:
url: string # Mandatory, must start with https://
# Either `templateFields` or `template` must be specified, but not both.
templateFields: # array of strings
- string1
- string2
# Replace the `templateFields` with `template` if a full template is used
# template: string
# Webhook Alert Method with template
- apiVersion: n9/v1alpha
kind: AlertMethod
metadata:
name: webhook
displayName: Webhook Alert Method
project: default
annotations:
area: latency
env: prod
region: us
team: sales
spec:
description: Example Webhook Alert Method
webhook:
url: https://123.execute-api.eu-central-1.amazonaws.com/default/putReq2S3
template: |-
{
"message": "Your SLO $slo_name needs attention!",
"timestamp": "$timestamp",
"severity": "$severity",
"slo": "$slo_name",
"project": "$project_name",
"organization": "$organization",
"alert_policy": "$alert_policy_name",
"alerting_conditions": $alert_policy_conditions[],
"service": "$service_name",
"labels": {
"slo": "$slo_labels_text",
"service": "$service_labels_text",
"alert_policy": "$alert_policy_labels_text"
}
}
headers:
- name: Authorization
value: very-secret
isSecret: true
- name: X-User-Data
value: "{\"data\":\"is here\"}"
isSecret: false
# Webhook Alert Method with templateFields
- apiVersion: n9/v1alpha
kind: AlertMethod
metadata:
name: webhook
displayName: Webhook Alert Method
project: default
annotations:
area: latency
env: prod
region: us
team: sales
spec:
description: Example Webhook Alert Method
webhook:
url: https://123.execute-api.eu-central-1.amazonaws.com/default/putReq2S3
templateFields:
- project_name
- service_name
- organization
- alert_policy_name
- alert_policy_description
- alert_policy_conditions[]
- alert_policy_conditions_text
- severity
- slo_name
- objective_name
- timestamp
- no_data_alert_after
- anomaly_type
headers:
- name: Authorization
value: very-secret
isSecret: true
- name: X-User-Data
value: "{\"data\":\"is here\"}"
isSecret: false
This configuration yields a notification message like:
{
"slo_name": "Test SLO",
"slo_details_link": "<https://main.nobl9.dev/slo/details?project=proj1&name=test_slo">
}
- apiVersion: n9/v1alpha
kind: AlertMethod
metadata:
name: webhook
displayName: Webhook Alert Method
project: default
annotations:
area: latency
env: prod
region: us
team: sales
spec:
description: Example Webhook Alert Method
webhook:
url: https://123.execute-api.eu-central-1.amazonaws.com/default/putReq2S3
template: |-
{
"message": "Your SLO $slo_name needs attention!",
"timestamp": "$timestamp",
"severity": "$severity",
"slo": "$slo_name",
"project": "$project_name",
"organization": "$organization",
"alert_policy": "$alert_policy_name",
"alerting_conditions": $alert_policy_conditions[],
"service": "$service_name",
"labels": {
"slo": "$slo_labels_text",
"service": "$service_labels_text",
"alert_policy": "$alert_policy_labels_text"
},
"no_data_alert_after": "$no_data_alert_after",
"anomaly_type": "$anomaly_type"
}
headers:
- name: Authorization
value: very-secret
isSecret: true
- name: X-User-Data
value: "{\"data\":\"is here\"}"
isSecret: false
The supported variables are as follows:
| Variable name | Description |
|---|---|
alert_id | Unique identifier of the alert |
alert_policy_conditions[] | Conditions defined for the alert policy that uses this alert method (JSON format) |
alert_policy_conditions_text | Conditions of the associated alert policy (string format) |
alert_policy_description | Description of the associated alert policy |
alert_policy_labels_text | Labels attached to the associated alert policy |
alert_policy_name | Name identifier of the alert policy that triggered the alert |
anomaly_type | Type of anomaly. The noData type is returned, indicating that the SLO reports no data for 15 minutes |
objective_name | Name identifier of the SLO objective that triggered the alert |
iso_timestamp | Timestamp (ISO format) when the alert was triggered |
no_data_alert_after | The interval Nobl9 waits for missing data from an SLO before alerting on no data Currently, this interval is fixed at 15m |
organization | Name identifier of the Nobl9 organization where the alert was triggered |
project_name | Name identifier of the project associated with this alert method |
service_labels_text | Labels attached to the service holding the SLO that triggered the alert |
service_name | Name identifier of the associated service |
severity | Severity level of the alert policy (high, medium, or low) |
slo_details_link | Link to the SLO that triggered the alert |
slo_labels_text | Labels attached to the associated SLO |
slo_name | Name identifier of the SLO that triggered the alert |
timestamp | Timestamp when the alert was triggered |
Important notes:
-
In your Webhook YAML definition, define either of the following objects:
-
spec.webhook.template -
spec.webhook.templateFields
-
-
The difference between
alert_policy_conditions[]andalert_policy_conditions_textis thatalert_policy_conditions[]creates a valid JSON array of conditions as strings, whereasalert_policy_conditions_textcreates a single string field. For example:{"text": "Remaining error budget is 10%, Error budget would be exhausted in 15 minutes and this condition lasts for 1 hour","array": ["Remaining error budget is 10%","Error budget would be exhausted in 15 minutes and this condition lasts for 1 hour"]} -
slo_labels_text,service_labels_text, andalert_policy_labels_textare comma-separated key:value pairs. For example:-
slo:ratio, slo:calendar -
project:myproject -
alert:low, alert:high
-
Testing the webhook alert policy in the UI
- Navigate to Integrations > Alert methods.
- Click the required alert method.
Its Details page opens. - Click Test under the alert method name:

- When the configuration is correct, Nobl9 displays Test completed successfully! under the button.
- Otherwise, the Test failed message appears. It contains the details of incorrect settings.
Verifying webhook signatures
Nobl9 signs all webhook notifications with HTTP Message Signatures. Use the signature to verify that a webhook notification came from Nobl9 and that the signed request fields and body were not changed in transit.
Signed webhook requests include the following HTTP headers:
| Header | Description |
|---|---|
Content-Digest | SHA-256 digest of the raw request body. |
Signature-Input | RFC 9421 sig1 metadata: covered components, creation time, key ID, and signing algorithm. |
Signature | Ed25519 signature for the signature base described by Signature-Input. |
The Signature-Input header uses the sig1 label.
It includes keyid and alg="ed25519" parameters,
and covers the following request components:
@method
@authority
@path
content-digest
content-type
The query string is not covered by the signature. If your webhook URL includes query parameters, do not use them as signed data.
To verify a webhook notification, implement the following checks in your endpoint:
-
Read the raw request body before parsing it.
-
Calculate the SHA-256 digest of the raw body and compare it with the
Content-Digestheader. -
Fetch the active Nobl9 public key for your environment:
Instance Endpoint EU (app) GET https://app.nobl9.com/api/notifications/v1/webhook-http-signature/public-keyUS (us1) GET https://us1.nobl9.com/api/notifications/v1/webhook-http-signature/public-key -
Check that the response
keyIdmatches thekeyidvalue in theSignature-Inputheader. -
Rebuild the RFC 9421 signature base from the covered components listed in
Signature-Input. -
Verify the
Signatureheader with the public key and Ed25519 algorithm. -
Process the notification only when both the body digest and the signature are valid.
For example, if your endpoint receives the raw body {}
with this request target and headers:
POST https://example.com/nobl9/webhook?source=nobl9
Content-Type: application/json
Content-Digest: sha-256=:RBNvo1WzZ4oRRq0W9+hknpT7T8If536DEMBg9hyq/4o=:
Signature-Input: sig1=("@method" "@authority" "@path" "content-digest" "content-type");created=1778498701;keyid="nobl9-webhook-prod-ed25519-v1";alg="ed25519"
then build the signature base as this exact newline-separated string:
"@method": POST
"@authority": example.com
"@path": /nobl9/webhook
"content-digest": sha-256=:RBNvo1WzZ4oRRq0W9+hknpT7T8If536DEMBg9hyq/4o=:
"content-type": application/json
"@signature-params": ("@method" "@authority" "@path" "content-digest" "content-type");created=1778498701;keyid="nobl9-webhook-prod-ed25519-v1";alg="ed25519"
Verify the Signature header against the UTF-8 bytes of this string.
The query string, ?source=nobl9 in this example,
is not included in @path.
The public key endpoint returns a JSON response similar to this:
{
"keyId": "nobl9-webhook-prod-ed25519-v1",
"algorithm": "ed25519",
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n"
}
Your verifier must build the signature base from the request as received
by your endpoint.
If you use a proxy, make sure it preserves the original host,
port, path, Content-Digest, and Content-Type values used for verification.