Skip to content

Hooks (incoming)

Many systems can only send a webhook to a URL. A hook turns that webhook into a notific.me event, with no code on your side. Each hook has a slug and a YAML mapping with rules that read the incoming body, headers and query string.

POST https://api.notific.me/v0/hooks/<slug>?token=<service token with events:write>
  • The token can go in the Authorization: Bearer header or, for systems that only let you set a URL, in ?token=. The server moves it out of the URL before logging.
  • The event belongs to the service that owns the token.
  • ?dry_run=1 returns the event that would be created, without ingesting it.

The Hooks page in app.notific.me builds the URL for you, combining the slug with a token of the chosen service.

source: github # default: the hook slug
hmac: # optional: validates the sender's signature
header: X-Hub-Signature-256
algorithm: sha256 # sha1 | sha256 | sha512
encoding: hex # hex | base64
prefix: "sha256="
secret: "shared-secret"
rules: # in order; the first one that matches wins
- name: workflow-failed
match: # every condition must hold (AND)
"$header.X-GitHub-Event": workflow_run
workflow_run.conclusion: failure
event:
type: ci.failed
severity: high
summary: "CI failed: {{ repository.name }} ({{ workflow_run.head_branch }})"
title: CI failed
text: "{{ workflow_run.name }} failed on {{ workflow_run.head_branch }}. {{ workflow_run.html_url }}"
dedup_key: "ci/{{ repository.name }}/{{ workflow_run.head_branch }}"
- name: workflow-ok
match:
"$header.X-GitHub-Event": workflow_run
workflow_run.conclusion: success
event:
type: ci.ok
severity: info
summary: "CI passed: {{ repository.name }}"

When no rule matches, the hook answers 200 {"status":"ignored"}.

Body fields separated by dots (data.app.name, items.0.id). Special paths: $header.<Name>, $query.<name>, $slug and $now.

A scalar means equals, a list means in. The map form accepts equals, in, not, regex, prefix, suffix, contains and exists:

match:
type: { regex: "(?i)^deploy[._-]?(success|done)$" }
status: [done, success]
"$header.X-Event": { exists: true }

{{ path }} with optional filters chained by |: default "x", lower, upper, trim, truncate 80 and json. A missing value becomes an empty string.

The event of a rule accepts type, severity (default info), summary, title and text (they build a simple card), id (idempotency, for example "{{ $header.X-GitHub-Delivery }}"), dedup_key, card_id, ttl, expires_when, retention, to and payload, all with templates.

Some systems have a ready-made mapping. Today: dokploy (deploy succeeded, deploy failed and a generic notification). To adjust a preset, save your own mapping with the same slug: it takes precedence, and deleting it brings the preset back.

  1. In app.notific.me, open Hooks and create a hook (or start from a preset).
  2. Write the mapping. Use Dry run with a sample body, headers and query to see the event that would be generated and whether it is valid.
  3. Pick the service and copy the hook URL.
  4. Paste the URL in the other system (Dokploy, GitHub, Stripe…). If it signs its webhooks, add the hmac block with the shared secret.