Skip to content

Guide

Send automation notifications from Python

A notification client can stay very small. The important parts are keeping authentication outside the payload, bounding the request and treating rejected input differently from a temporary server or network failure.

Updated 7 min read

Send JSON with the standard library

Bounded Python request
import json
import os
import urllib.error
import urllib.request

NOTIFICATION_PAYLOAD = {
  "title": "Research run completed",
  "body": "The agent finished with 18 verified records and 2 rejected rows.",
  "severity": "success",
  "source": "research-agent",
  "tags": [
    "agent",
    "daily-run"
  ],
  "deduplicationKey": "research-run:2026-07-31",
  "metadata": {
    "accepted": "18",
    "rejected": "2",
    "runId": "run_2026_07_31"
  },
  "actions": [
    {
      "id": "open-run",
      "type": "link",
      "label": "Open run",
      "href": "https://example.com/runs/run_2026_07_31",
      "style": "primary"
    }
  ]
}
request = urllib.request.Request(
    f"{os.environ['NOTIFICATIONS_URL']}/api/v1/notifications",
    data=json.dumps(NOTIFICATION_PAYLOAD).encode("utf-8"),
    headers={
        "Authorization": f"Bearer {os.environ['NOTIFICATIONS_API_KEY']}",
        "Content-Type": "application/json",
    },
    method="POST",
)

try:
    with urllib.request.urlopen(request, timeout=10) as response:
        result = json.load(response)
except urllib.error.HTTPError as error:
    detail = error.read().decode("utf-8", errors="replace")
    raise RuntimeError(f"notification rejected ({error.code}): {detail}") from error

print(result["id"], result["created"])

Use a key derived from the event

The example derives a stable key from the logical run date. A retry can resend the same payload safely; a genuinely new run receives a different key.

  • Use a workflow run identifier when the producer already has one.
  • Include the event type when one run can emit several distinct results.
  • Keep the key stable across transport retries but change it for a new logical event.

Frequently asked questions

Does the producer need a special integration?
No. The examples use an authenticated HTTPS request, so any script, service or visual workflow that can send HTTP can use the same contract.
Should credentials be included in notification data?
No. Keep credentials in the producer's secret store and send only the context needed to understand or locate the event.

Put the pattern to work

Existing accounts can open the inbox and send their next event.

Open your inbox