Skip to main content

Integrating notifications

This guide walks through building an endpoint that receives Podero notifications, verifying that each delivery is authentic, and handling the delivery semantics correctly.

Prerequisites

  1. An API token with admin access for the organization. See Authentication.
  2. A public HTTPS endpoint — a URL reachable from the public internet, with a valid TLS certificate. Podero refuses plain http, embedded credentials, and non-public addresses (loopback, private ranges, link-local, cloud metadata).

Register a webhook

Register your endpoint with the Create Webhook endpoint. The response includes a signing secret — store it securely.
201 Created
The signing secret is returned once in this response and cannot be retrieved again. Store it in a secrets manager immediately. If it is lost, rotate it to get a new one.

1. Receive a delivery

A notification arrives as an HTTP POST with a JSON body and a signature header:
Your endpoint should read the raw request body before doing anything else — you need the exact bytes to verify the signature (see below). Do not verify against a re-serialized copy of the parsed JSON, as key ordering and whitespace will differ.

2. Verify the signature

Every message is signed so you can prove it came from Podero. The X-Podero-Signature header carries a timestamp and an HMAC-SHA256 digest:
To verify a delivery:
1

Parse the header

Split on , and read the t (unix timestamp) and v1 (hex digest) fields.
2

Check freshness

Reject the request if t is more than 300 seconds away from your current time. This bounds how long a captured request can be replayed.
3

Recompute the digest

Compute HMAC-SHA256(secret, "{t}." + raw_body) and compare it to v1 using a constant-time comparison.
Verify against the raw body bytes, exactly as received. Many web frameworks parse the body into an object before your handler runs — configure yours to expose the raw payload (for example, Express’s express.raw() or Flask’s request.get_data()).

3. Acknowledge the delivery

Respond with any 2xx status code to acknowledge the message. Podero reads only the response status — the body is ignored.
Respond quickly. Podero uses tight timeouts (a few seconds) and does not follow redirects — a 3xx is treated as a failed delivery. Acknowledge first, then do slow work asynchronously.
Any non-2xx response, a redirect, a timeout, or a connection error marks the delivery as failed for that attempt.

4. Handle duplicates

Because delivery is at-least-once, you may occasionally receive the same message more than once. The message_id is stable across redeliveries of the same message — use it as an idempotency key:
Persist processed message_ids (with a suitable retention window) so a duplicate that arrives after a restart is still recognised.

5. Fetch the notification content

A webhook message is a signal, not the full story: it tells you a device needs attention, and the Notification Content API tells you exactly what is pending right now. Branch on message_type and fetch the matching list: The message’s data fields feed straight into the list filters — owner_id, device_id, and device_type share one vocabulary across the wire payload and the Content API — so you can scope the fetch to exactly the user and device the message is about:
From here it’s a user-experience problem: showing the items, redirecting the user through a reauthentication, dismissing notices. The Notifications journey covers that end to end, including badge counts via GET /notifications/status.
Resolution-link secrets expire one hour after the response is issued. Fetch the lists when you act on a message rather than caching links from an earlier fetch.

6. Test end to end

Send a test delivery to your webhook with the Test Webhook endpoint. It fires a synthetic sample for one of your subscribed topics, signed exactly like a real notification:
The response tells you the outcome immediately:
If outcome is "delivered" and your signature check passed, you are ready to go live. A "failed" outcome includes a detail field with the transport error.

Best practices

Acknowledge with 2xx immediately and hand off processing to a background queue. Slow handlers risk timing out and being marked as failed.
Reject any request whose signature does not verify or whose timestamp is outside the tolerance window. Never act on an unverified payload.
Within a schema_version, the data object is additive — new fields may appear. Ignore fields you do not recognise rather than failing.
Store the signing secret in a secrets manager, never in source control. If it is exposed, rotate it immediately.

Next steps

Reference

The full message envelope, headers, topics, and delivery semantics