TempoLife

TempoLifeFeaturesAutomations and webhooks › raw-webhooks

Raw webhooks

Register an https endpoint, verify an HMAC-SHA256 signature over the raw body, handle retries idempotently. Registration is open; deliveries begin when the worker ships.

Your own endpointSignature: HMAC-SHA256Checked 2026-09-02

No deliveries are being sent. The delivery worker is not built, so a webhook registered today records your URL, your event and your signing secret and then sits there — TempoLife makes no outbound request to it, not even a test ping. Registering now is only worth doing if you want the secret ahead of time so you can write and unit-test your verification code. Deliveries begin when the worker ships.

What a raw webhook gets you

No intermediary, no per-task pricing, no data leaving your infrastructure through a third party. TempoLife posts JSON to a URL you control, signed so you can prove it came from TempoLife, and you do whatever you like with it: write a row, update a dashboard, send yourself a message, feed a model. The cost is that you own the endpoint, the retries and the deduplication.

If you have not built a webhook receiver before, the shape is smaller than it sounds. An HTTPS route that reads the raw body, checks one header, returns 200 quickly and queues the real work. Everything hard about webhooks is in that word "quickly", and in remembering that the same event can arrive twice.

Requirements for your endpoint

RequirementDetail
Schemehttps only. An http URL is refused at registration — a signature proves origin, it does not hide the body from the network.
HostA public, fully qualified domain name. Private, loopback, link-local and internal addresses are refused, and so are bare IPs.
PortThe default https port. Registration refuses anything else.
ResponseAny 2xx within 10 seconds. Redirects count as failures.
Body handlingRead the raw bytes before parsing. The signature covers exactly what was sent.
IdempotencyDeduplicate on the envelope id. Retries reuse it.

Those rules are enforced by the registration form on this page, not merely recommended. They exist because a webhook target is a URL a user gives a server and asks it to fetch — the classic server-side-request-forgery shape. Refusing internal addresses at registration is the first line of that defence; the delivery worker will re-check the resolved address at send time, because a hostname that is public today can be repointed at an internal address tomorrow.

A complete receiver

Verify, acknowledge, then work. In that order.

<?php
// POST /tempolife-webhook
declare(strict_types=1);

const TOLERANCE = 300;
$secret = (string)getenv('TEMPOLIFE_WEBHOOK_SECRET');
$raw    = (string)file_get_contents('php://input');
$header = (string)($_SERVER['HTTP_X_TEMPOLIFE_SIGNATURE'] ?? '');

function tl_verify(string $secret, string $header, string $raw): bool {
    if (preg_match('/(?:^|,)\s*t=(\d{1,12})\s*(?:,|$)/', $header, $mt) !== 1) return false;
    if (preg_match('/(?:^|,)\s*v1=([0-9a-f]{64})\s*(?:,|$)/i', $header, $mv) !== 1) return false;
    if (abs(time() - (int)$mt[1]) > TOLERANCE) return false;
    return hash_equals(hash_hmac('sha256', $mt[1] . '.' . $raw, $secret), strtolower($mv[1]));
}

if (!tl_verify($secret, $header, $raw)) { http_response_code(401); exit; }

$event = json_decode($raw, true);
if (!is_array($event) || !isset($event['id'], $event['type'])) { http_response_code(400); exit; }

// Idempotency before side effects.
if (already_seen($event['id'])) { http_response_code(200); exit; }
remember($event['id']);

http_response_code(200);          // acknowledge first
fastcgi_finish_request();         // then do the slow part off the request

match ($event['type']) {
    'meal.logged'        => on_meal($event['data']),
    'weight.updated'     => on_weight($event['data']),
    'steps.goal_reached' => on_goal($event['data']),
    'fast.completed'     => on_fast($event['data']),
    default              => null, // unknown types are normal; ignore them
};

Note the default => null. New event types will appear, and a receiver that throws on one it has never seen will start failing deliveries for events it does not even care about.

Common ways this goes wrong

Register a webhook

Webhooks belong to an account. Sign in to register one — everything else on this page is public and does not need an account.

Sign inCreate an account

Frequently asked questions

Do I need an account to register a webhook?

Yes. A webhook is tied to the account whose events it carries, so you have to be signed in to create one.

Can I point one webhook at several events?

No. One event per registration. Register the same URL more than once if you want several events, which also lets you disable one without losing the others.

What if my endpoint is behind a firewall?

It has to be reachable from the public internet on the default https port. Private and internal addresses are refused at registration, and re-checked at delivery time.

Source: TempoLife platform specification — event, signature and retry policy · checked 2026-09-02

Other platforms

Zapier

Setup steps and the honest status.

No TempoLife app published

Make

Setup steps and the honest status.

No TempoLife module published

IFTTT

Setup steps and the honest status.

No TempoLife service published

Payloads, signing and the retry policy · Developer API

Automations need something to automate

Log meals, weight, steps and fasts in the app and the events on this page will have something real to carry.

Create a free accountGet the app