litehook Docs Sign in

Sending events

How to reach Litehook, what to send, and what comes back.

Source addresses

New sources use signed requests unless you turn signing off when you create them. A URL token source accepts events two ways. Both take the same JSON body.

UseSource address
Services that only take a URLPOST https://litehook.app/hook/SOURCE_ID/SOURCE_SECRET
Your own codePOST https://litehook.app/api/ingest/SOURCE_ID with Authorization: Bearer SOURCE_SECRET

Send Content-Type: application/json. The /hook address holds the secret. Keep it private.

Signed requests

A signed source has one source address, POST https://litehook.app/api/v1/sources/SOURCE_ID/events, and a signing secret that starts with whsec_. Each request carries three Standard Webhooks headers:

HeaderValue
webhook-idA unique ID for this event. A retry reuses it and isn't stored twice.
webhook-timestampSeconds since 1970. Must be within 5 minutes of now; a source can set 30 seconds to 15 minutes.
webhook-signaturev1, then the base64 HMAC-SHA256 of ID.TIMESTAMP.BODY, keyed with the base64-decoded secret after whsec_.

Most languages have a Standard Webhooks library that signs for you. From a shell:

export LITEHOOK_SECRET='whsec_…'
BODY='{"title":"Hello from my app","level":"success"}'
ID="msg_$(date +%s%N)"; TS=$(date +%s)
KEY=$(printf '%s' "${LITEHOOK_SECRET#whsec_}" | base64 -d | od -An -tx1 | tr -d ' \n')
SIG=$(printf '%s' "$ID.$TS.$BODY" | openssl dgst -sha256 -mac HMAC -macopt "hexkey:$KEY" -binary | base64)
curl -X POST 'https://litehook.app/api/v1/sources/SOURCE_ID/events' \
  -H 'Content-Type: application/json' \
  -H "webhook-id: $ID" -H "webhook-timestamp: $TS" -H "webhook-signature: v1,$SIG" -d "$BODY"

Signed sources also accept plain text and form data. For senders that can’t sign, such as Coolify or Home Assistant, use a URL token source.

Fields

FieldTypeNotes
titletext, up to 120The notification's headline. Falls back to event, then the source name.
messagetext, up to 2,000Optional detail. body is accepted too.
levelinfo, success, warning, errorDefaults to info. Warnings and errors are labelled in the inbox.
successtrue or falseSets the level to success or error when level is not given.
grouptext, up to 80Collapses repeats. See Grouping.
idempotency_keytext, up to 120URL token sources: marks a repeat as a duplicate. See Duplicates.

Title and message are trimmed to fit. Unknown fields are ignored.

Grouping

Give related events from one source the same group to get one notification instead of many. In the inbox they collapse into the latest event with a count, like Disk at 92% ×3. On your phone each new one replaces the previous notification.

{"title":"Disk at 92%","level":"warning","group":"disk-space"}

Opening a grouped notification marks the whole group read.

Duplicates

A signed request is identified by its webhook-id for 7 days: a retry with the same ID and body is accepted but not saved again, and the response includes "duplicate": true. The same ID with a different body is refused with 409. For a URL token source, an Idempotency-Key header works the same way. An idempotency_key field marks any repeat as a duplicate, without the 409.

Responses and errors

StatusMeaning
202Accepted. Signed sources answer {"accepted":true,"event_id":"…","duplicate":false}; URL token sources answer {"accepted":true,"id":123,"event_id":"…"}, or "duplicate":true for a repeat.
400The body cannot be parsed, or a field is invalid. The error says which.
401The secret or signature is wrong, missing or out of date, or the source does not exist. On URL token sources, a disabled or deleted source gets the same answer.
403The workspace is paused, or the sender's IP address is not on the source's allowlist.
404Wrong URL: extra path segments, or a workspace address instead of litehook.app.
409A signed source that has never been published, or an event ID reused with a different body.
410A signed source with receiving turned off.
413The body is over 64 KiB.
415The content type is not accepted: application/json for URL token sources; JSON, plain text or form data for signed sources, as the source allows.
422The body does not match the source's payload schema.
429Too many events: over 300 a minute for one source or 1,200 for a workspace or IP address, the source is cooling off, or 1.5× the monthly allowance is used. Wait for Retry-After when given.
503Busy. Retry after Retry-After.
508The event looped through Litehook 3 times.

Your phone's operating system decides when a notification is shown, so test a source before relying on it for urgent alerts.