Skip to content

Cheap change signal for a feed

GET
/v1/feeds/{group}/{id}/head
curl --request GET \
--url http://localhost:3000/v1/feeds/example/example/head \
--header 'Authorization: Bearer <token>'

Redis-only head check, and the whole freshness signal in one request. latest is the id of the newest activity fanned out to this feed — an opaque token; compare for equality with the last value acted on and refetch only on change. changed covers what latest structurally cannot: edits, reactions and object writes. Never touches the tenant database.

group
required
string
id
required
string

Current head token.

Media typeapplication/json
object
latest
required

Newest id fanned out to this stream, or null meaning “nothing new”.

string | null
changed
required

Tenant mutation counter. Incremented on every write the head token cannot report — an activity edited, a reaction moved, an object written. Unchanged since your last revalidation means nothing in this tenant has been mutated, so a client can skip re-reading the page and its objects entirely.

0 means nothing has ever been mutated in this tenant. That is a definite answer, not an absent one, so a brand-new or idle tenant gets the same skip as any other.

null means unknown — a counter key that exists but does not parse. Treat unknown as “revalidate”: a wasted read is cheap, a permanently stale feed is not. A Redis outage is not this case; the route fails and the client retries.

Tenant-wide on purpose. An object does not know which feeds reference it, so a per-feed counter would need fan-out on write. The cost is a false positive: one tenant’s write makes every open feed in that tenant revalidate once.

integer | null
Examplegenerated
{
"latest": "example",
"changed": 1
}

Invalid, expired, revoked, or absent token.

Media typeapplication/json
object
error
required
object
code
required
string
Allowed values: VALIDATION_FAILED UNAUTHENTICATED FORBIDDEN NOT_FOUND CONFLICT RATE_LIMITED INTERNAL
message
required
string
requestId
required
string
fields

Present only for VALIDATION_FAILED.

Array<object>
object
path
string
message
string
Example
{
"error": {
"code": "VALIDATION_FAILED"
}
}

Rate limit exceeded.

Media typeapplication/json
object
error
required
object
code
required
string
Allowed values: VALIDATION_FAILED UNAUTHENTICATED FORBIDDEN NOT_FOUND CONFLICT RATE_LIMITED INTERNAL
message
required
string
requestId
required
string
fields

Present only for VALIDATION_FAILED.

Array<object>
object
path
string
message
string
Example
{
"error": {
"code": "VALIDATION_FAILED"
}
}
Retry-After
integer