Notification templates

Notification templates are a way of generating notifications: by defining a title and a content templates, they will be filled up with the data provided through the API endpoints.

Notify17 notification templates use the well known Go templates syntax, with the request payload being the context of the template.

You can find extensive documentation, which applies to all the basic syntax of the templates, at https://golang.org/pkg/text/template/ .

Basic example

A notification template can be created in the Notification templates  page.

To trigger a notification using a template, you can send a cURL  request containing your payload (JSON/Form):

curl "https://hook.notify17.net/api/template/TEMPLATE_API_KEY?name=Mr.%20Anderson"
curl -X POST \
  "https://hook.notify17.net/api/template/TEMPLATE_API_KEY" \
  -F name="Mr. Anderson"
curl -X POST \
  "https://hook.notify17.net/api/template/TEMPLATE_API_KEY" \
   --header "Content-Type: application/json" \
   --data "{\"name\":\"Mr. Anderson\"}"

The basic usage of a template is:

Template Payload
This is a greeting!

---

Hello {{ .name }}!
{
  "name": "Mr. Anderson"
}
Rendered
This is a greeting!

---

Hello Mr. Anderson!

Access payload variables

Template Payload
Hello {{ .name }}!

---

You live in {{ .address.city }}.
{
  "name": "John",
  "address": {
    "city": "Toronto"
  }
}
Rendered
Hello John!

---

You live in Toronto.

Delete all the whitespaces!

The little dashes (-) you see around are used to delete the whitespaces and newlines between where they’re used and:

  • {{- <- The word closest to the left of the template block
  • -}} <- The word closest to the right of the template block
Template Payload
Hello    {{ .name }}!

Hello    {{- .name }}!
{
    "name": "General Kenobi"
}
Rendered
Hello    General Kenobi!

HelloGeneral Kenobi!

NOTE: By default Notify17 will remove, from generated notifications, groups of 3+ newlines and collapse them into 2 newlines, to improve content readability.

Delete all the whitespaces!

Comments

You can add a comment using the notation {{/* This is a comment! */}}. Comments will not be rendered in the notification.

To remove whitespaces and newlines around comments, use the {{- /* and */ -}} tags.

Template
Line 1

{{/* 
    We're doing lots of stuff here, so we want some comments.
    
    This is a multiline comment.
*/}}

Line 2

{{/* Single line comment with white space clearing*/ -}}
 
Line 3
Rendered
Line 1

Line 2

Line 3

Conditionals

Template Payload
{{ if eq .success true -}}
Success!
{{- else -}}
Failed!
{{- end }}

{{ if gt .value 5 -}}
The value is bigger than 5!
{{- else -}}
What a small value!
{{- end }}
{
  "success": true,
  "value": 10.1
}
Rendered
Success!

The value is bigger than 5!

Available comparison functions:

  • eq .A .B -> A == B (also existsAndEq)
  • ne .A .B -> A != B (also existsAndNE)
  • lt .A .B -> A < B (also existsAndLT)
  • le .A .B -> A <= B (also existsAndLE)
  • gt .A .B -> A > B (also existsAndGT)
  • ge .A .B -> A >= B (also existsAndGE)

existsAnd- variants

A generic exists functions is available to test if a field is present or not.

The other existsAnd- comparison variants are quite useful when dealing with trigger conditions, whenever you want to check if a field exists before comparing it.

Template Payload
{{ if not (exists .hello) }}
Oh, hello does not exist!
{{ end }}

{{ if existsAndEq .value .invalidOne }}
Wow, really?
{{ else }}
Oh, some values did not exist!
{{ end }}

{{ if existsAndEq .value 10.1 }}
Yay!
{{ end }}
{
  "value": 10.1
}
Rendered
Oh, hello does not exist!

Oh, some values did not exist!

Yay!

Why do we need these variants?

These variants were introduced to solve the problem “how do I trigger a template only if this field exists and is not 0?”.

One may think it is possible to check if a field (e.g. .code) exists and is not 0 by using the following template:

{{ if and (.code) (ne .code 0) }}
It exists!
{{ end }}

The problem with the previous template is that the second argument of the conditional ((ne .code 0)) is evaluated BEFORE the actual and, triggering a comparison error (nil vs 0). Therefore, you need a wrapper to the conditional, that returns false whenever any of the arguments are null or do not exist.

Arrays

Template Payload
Second element: {{ index .myArray 1 }}
{
  "myArray": [
     "I'm first!",
     "I'm second :("
  ]
}
Rendered
Second element: I'm second :(

Loops

Template Payload
The number 3 is perfect:

{{ range $entry := .entries -}}
* {{ $entry.name }}
{{ end }}
{
  "entries": [
    {"name": "Doom 3"},
    {"name": "Half-Life 3 😈"},
    {"name": "Far Cry 3"}
  ]
}
Rendered
The number 3 is perfect:

* Doom 3
* Half-Life 3 😈
* Far Cry 3
Template Payload
Ids:

{{ range $field := .array -}}
- {{ $field }}
{{ end }}
{
  "array": [
    "id-1",
    "id-2",
    "id-3"
  ]
}
Rendered
Ids:

- id-1
- id-2
- id-3

Trigger conditions

If you want your notification templates to generate notifications ONLY if certain conditions are met (e.g. the payload variable status is alerting), you can use the Trigger condition field.

This field can contain one Go-template expression (an expression that you would place inside a if block), which gets checked whenever the notification template is used through the templated notifications API.

Examples:

  • Trigger only if status is alerting:

    eq .status "alerting"

  • Trigger only if the decoded base64 value of signature is report/1234:

    eq (.signature | Base64Decode) "report/1234"

  • Trigger only if timestamp (unix time) is not older than 1 hour (e.g. to prevent old useless/delayed notifications from popping up):

    (.timestamp | ParseUnixTime).After (GetTimeNow.Add (ParseDuration "-1h"))

    Let’s break this one down:

    • .timestamp | ParseUnixTime converts the payload field timestamp to a time.Time  element.
    • ParseDuration "-1h" converts the literal -1h to a time.Duration  element.
    • GetTimeNow.Add (ParseDuration "-1h") subtracts 1 hour from the current time.
    • .After is the actual check for (GetTimeNow.Add (ParseDuration "-1h")) to be after (.timestamp | ParseUnixTime).

You can find more examples in the Conditionals section.

Functions

Notify17 has a set of embedded functions that you can use to process the notification payloads.

Dump

Prints the provided value in a human-readable way.

Template Payload
String: {{ .valueString | Dump }}
Nil: {{ .valueNil | Dump }}

Arrays:
{{ .valueArray | Dump }}

Maps:
{{ .valueMap | Dump }}
{
  "valueString": "hello!",
  "valueNil": null,
  "valueArray": [1, "second", 3],
  "valueMap": {
    "key1": "I'm key 1!",
    "arr": [
      "harr!!!",
      "durr!!!",
      "multiline!!!\nomg!!!"
    ]
  }
}
Rendered
String: hello!
Nil: <no value>

Arrays:
- 1
- second
- 3

Maps:
arr:
- harr!!!
- durr!!!
- |-
  multiline!!!
  omg!!!
key1: I'm key 1!

Indent

Indents the provided string with the desired number of spaces.

Template Payload
Original:
{{ .value }}

Indented:
{{ .value | Indent 4 }}
{
  "value": "Line 1\nLine 2\nLine 3"
}
Rendered
Original:
Line 1
Line 2
Line 3

Indented:
    Line 1
    Line 2
    Line 3

ParseJSON

Parses a JSON string to a map.

Template Payload
{{ $content := .value | ParseJSON }}
Hello {{ $content.name }}!
{
  "value": "{\"name\": \"Mr. Anderson\"}"
}
Rendered
Hello Mr. Anderson!

ParseYAML

Parses a YAML string to a map.

Template Payload
{{ $content := .value | ParseYAML }}
Hello {{ $content.name }}!
{
  "value": "name: Mr. Anderson"
}
Rendered
Hello Mr. Anderson!

GetTimeNow

Returns the current time (UTC) as a time.Time  element, which can be formatted as desired, following Go language time formatting  convention (more examples ).

Template
{{ $time := GetTimeNow -}}

ISO 8601: {{ $time.Format "2006-01-02T15:04:05" }} / yyyy-MM-dd'T'HH:mm:ss
ISO 8601: {{ $time.Format "2006-01-02T15:04:05-0700" }} / yyyy-MM-dd'T'HH:mm:ssZ	
{{ $time.Format "2 Jan 2006 15:04:05" }} / d MMM yyyy HH:mm:ss				
RFC 822: {{ $time.Format "Mon, 2 Jan 2006 15:04:05 MST" }} / EEE, d MMM yyyy HH:mm:ss z
Rendered
ISO 8601: 2019-10-01T08:27:50 / yyyy-MM-dd'T'HH:mm:ss
ISO 8601: 2019-10-01T08:27:50+0000 / yyyy-MM-dd'T'HH:mm:ssZ	
1 Oct 2019 08:27:50 / d MMM yyyy HH:mm:ss				
RFC 822: Tue, 1 Oct 2019 08:27:50 UTC / EEE, d MMM yyyy HH:mm:ss z

Parse unix time

Parses the input value to a time.Time  element.

Template Payload
Result: {{ .result }}!
 
{{ $parsedTimeMs := .timeMs | ParseUnixTimeMs -}}
Time (milliseconds): {{ $parsedTimeMs.String }}

{{ $parsedTimeSeconds := .time | ParseUnixTime -}}
Time (seconds): {{ $parsedTimeSeconds.String }}

We can parse also a string: {{ .timeStr | ParseUnixTime }}
{
  "result": "success",
  
  "timeMs": 1549049482225,
  "time": 1549049482,
  
  "timeStr": "1549049482"
}
Rendered
Result: success!
 
Time (milliseconds): 2019-02-01 21:31:22.225 +0200 EET

Time (seconds): 2019-02-01 21:31:22 +0200 EET

We can parse also a string: 2019-02-01 21:31:22 +0200 EET

Base64 encode/decode

Template
The message says "{{ .valueBase64Std | Base64Decode }}".

I'd like to answer back with "{{ "Hello to you too!" | Base64Encode }}"! 
    
What do we have here? {{ .valueBase64URL | Base64DecodeURL }}
Rendered
The message says "Hello 🐄".

I'd like to answer back with "SGVsbG8gdG8geW91IHRvbyE="! 
    
What do we have here? Oh! Special chars 😁
Payload
{
  "valueBase64Std": "SGVsbG8g8J+QhA=",
  "valueBase64URL": "T2ghIFNwZWNpYWwgY2hhcnMg8J-YgQ="
}

Notify17 also supports encoding/decoding URL-safe base64  with Base64EncodeURL and Base64DecodeURL.