Browse documentation
Evidence changes: what appeared since, and what you lost
The evidence for an objective now, diffed against the evidence as of an earlier instant — plus whether the URLs you relied on are still there.
The question it answers
“What changed?” is the question a monitoring agent asks, and a scheduled search answers it badly: the same query returns the same links plus a few new ones, and the agent has to work out which are new, which are copies, and whether anything that mattered went away.
changes answers it as evidence. It builds the ground set for an
objective twice — once over everything the index holds, once over only what had been
crawled by since — and diffs the two. Then it answers known_urls the way
why_not would.
curl -sG -H "x-api-key: $UNLOB_API_KEY" https://api.unlob.com/changes \
--data-urlencode 'objective=acme zed acquisition' -d since=7d \
--data-urlencode 'known_urls=https://example.com/a,https://example.org/b'
A call costs 10 credits, however many stories the two reconstructions expanded, and a call that runs and fails costs 1.
The request
| Parameter | Meaning |
|---|---|
objective | What you need evidence for. q is accepted as an alias. |
since | An absolute unix timestamp, a bare number of seconds ago, or a duration ago: 1d, 12h, 2w. Must be in the past. |
known_urls | Comma list of URLs you relied on before. |
claim | Experimental: also report evidence that newly contradicts this claim. |
token_budget, mode, vertical, lang, safe | As on ground. |
The response
{
"status": "changed",
"since": 1757200000,
"new_evidence": [ { "hit": { "…": "…" }, "source_role": "official", "origin_type": "original" } ],
"origins_gained": [ { "id": "o:…", "kind": "original", "owner": "fda.gov" } ],
"roles_gained": ["official"],
"independent_origins": { "before": 1, "after": 2 },
"contradictions_gained": [],
"known_urls": [
{ "url": "https://example.com/a", "status": "present" },
{ "url": "https://example.org/b", "status": "removed", "reason": "superseded", "superseded_by": "…:0", "removed_at": 1757400000 }
],
"coverage": { "…": "the receipt for now" },
"coverage_before": { "…": "the receipt as of since" },
"next_actions": [
{ "action": "get_document", "target": "…:0", "why": "https://example.org/b was superseded; this is its replacement" }
],
"provenance": {
"method": "deterministic",
"experimental": ["evidence_changes"],
"limitations": [
"passages removed after `since` are not reconstructable, so the before-set and its counts are lower bounds",
"as of `since` means crawled by then (fetched_at), not published by then",
"origins are matched by id, which is stable while a story's cluster is; a re-clustered story can show as gained"
]
}
}
| Field | Meaning |
|---|---|
status | changed, unchanged, or partial when either reconstruction was incomplete. |
new_evidence | Evidence items that did not exist as of since. |
origins_gained | Origins present now that were not present then. |
roles_gained | Source roles present now that were missing then — an official source appearing is the case that matters most. |
independent_origins | Before and after. A claim that gained its second independent origin shows here. |
contradictions_gained | With claim: evidence ids that contradict it now and did not then. |
known_urls | Each URL: present, removed with the reason and its replacement, unknown, or error when the lookup failed. |
coverage, coverage_before | Both receipts. |
What it cannot know
The limitations are in the response because they are real. The as-of set is built from
what the index holds today, filtered by crawl time, so passages removed after since
are missing from both sides: the before-counts are lower bounds. “As of” means crawled by
then, not published by then — a page published before since and crawled after it counts
as new. And origins are matched by id, which is stable while a story’s cluster is; a story
that was re-clustered in between can show as gained.
known_urls closes the first gap for the URLs you care about: whether each is still
present, and if it was removed, why and what replaced it.
Using it in a loop
Keep the ids and URLs of the evidence you acted on. On the next pass, call changes with
since set to the previous pass and known_urls set to those URLs. status: unchanged
means nothing to do. roles_gained containing official or new_evidence with a
primary item is the case worth re-reading, and next_actions points at it.
Next
- Grounding — the set being diffed.
- Coverage transparency —
known_urls, one at a time. - Freshness — the same question, asked as a window.
evidence_changesreference