POST /v1/{source}/watches and provide a webhook_url. When matches change, Nephia POSTs an event payload to your endpoint.
webhook_url is optional. A watch created without one polls, bills and records its
matches exactly the same; it simply pushes nothing. Read those matches with
GET /v1/{source}/watches/{id}/events, which is free.
Event types
Payload envelope
Every event uses the same shape. Unused fields arenull.
ai is the agent step’s reading of the event. It is null unless the
watch was created with an ai step — see Agent step on a watch
below.
analysis is the only optional key in the body: it is present when
something read the item, and absent otherwise — see
The analysis key below.
Two dates, and which is which
occurredAt is when Nephia collected the item — the instant the tick that
caught it ran. publishedAt is when the platform says the item was
published.
They are usually minutes apart and sometimes years. A watch polling every 15
minutes that meets a two-year-old Reddit thread on today’s page delivers it with
today’s occurredAt and a 2024 publishedAt.
Use occurredAt to order or de-duplicate a stream you are syncing, and to
filter with since and until — those read occurredAt, so nothing you have
already been delivered can arrive behind you. Use publishedAt to answer “when
was this said”: grouping mentions by day, charting them over time, deciding
whether something is fresh.
publishedAt is null when the source gave no real date. Two cases: an AI
answer has no publication date at all (it is generated the moment we ask, so its
occurredAt is its date), and a YouTube video caught through search reports a
relative age — “4 years ago” — which we will not turn into a timestamp we cannot
stand behind. Fall back to occurredAt when you need a date for every item.
The analysis key
A watch whose owning search has analysis turned on delivers one extra key,
after ai:
Both are read on one pass, so turning analysis on costs one charge and
answers both.
null inside the object means not read — never “we looked and found
nothing”. That verdict has its own value in each vocabulary: neutral for an
item that takes no side, other for an item with no recognisable intent.
The key is absent, not null, on an event nothing classified. Read it as
event.analysis?.intent rather than branching on the key’s existence for
anything else. Every other key in the body is always present, and this one is
the exception on purpose: an object of two nulls on every delivery would say
nothing.
The same object comes back from
GET /v1/{source}/watches/{id}/events, so a replay and a
delivery agree field for field.
X tweet.created
Vinted listing.price_changed
Reddit post.created
Reddit reddit_comment.created
A comment travels in the same post object a submission does, told apart by kind. title is the parent submission’s title, selftext is what the comment said, and id carries Reddit’s t1_ prefix.
post.created never receives one of these: a comment has no submission’s shape to offer it. See Reddit.
Youtube video.created
Bluesky bluesky_post.created
Hacker News hn_item.created
title is the parent story’s title and url is null — hnUrl is where the comment is read. See Hacker News.
RSS article.created
summary is text, never HTML. See RSS & News.
AI answers answer.changed
mentioned and cited are different questions and a brand can be either
without the other — see AI answers. The same shape
arrives on answer.created, term.cited and term.uncited; only type
differs, and on a first run previous is null.
Agent step on a watch
A watch can be created with anai step: one instruction and one flat schema of
your own fields, applied to every event the watch emits. The answer arrives on
the event, in the ai block.
Delivery waits for the reading
A watch with anai step holds its delivery until the step answers, up to
120 seconds. You receive one message per event, with ai filled in — never a
first message without the reading and a second one with it.
The event is never lost. If the step times out or fails, the event is
delivered anyway with ai.output: null and ai.status set to timeout or
failed. Treat a missing reading as “no answer”, not as an error to retry: the
event itself is complete.
Watches without an
ai step are unaffected: they deliver immediately, with
ai: null.
Schema and rates
The schema is a flat object of 1–12 fields, eachstring, number, boolean
or enum. Every field can answer null — that is a real answer, not an error.
See AI for the full subset and the credit rate.
Signature verification
Each delivery includes anX-Signature header of the form t=<unix seconds>,v1=<hex>, where v1 is the HMAC-SHA256 of "<t>.<raw JSON body>" using your account’s webhook signing secret. The timestamp prevents replay attacks: reject deliveries whose t is more than 5 minutes from now.
Your signing secret is per-account — find it on the API Keys page of the dashboard.
With the SDK (recommended):
Retries
Failed deliveries (non-2xx or network error) retry with backoff: immediate, +30s, +120s (3 attempts total).In n8n, the official Nephia Trigger does all of this for
you: it creates and deletes the watch, verifies the signature, and drops the
repeats — with a poll mode for instances that are not reachable from the
internet.
Replay events
Fetch historical events for a watch (free). This is also how you read a watch created without awebhook_url:
Events are kept for 90 days. A
since older than that returns what is left,
not an error — the rest has aged out. The window is the same for every plan and
every source.Ninety days is far longer than a replay needs: a delivery that fails is retried
for 48 hours, and a since you set from your own last-seen event is usually
minutes or hours behind. If you need events beyond that, store them on receipt —
the webhook body and the replay body are the same envelope, so nothing is lost
by writing the one you are already handed.Retention is not the only way events end. A replay still reaches the events of a
retired Query — DELETE /v1/queries/{id} without purge stops the polling
and keeps the record — but not those of a purged one, which
DELETE /v1/queries/{id}?purge=true deletes outright. If you replay against a
Query somebody may delete, store what you receive.