GraphQL
GraphQL is a Pro feature. On Lite nothing is registered at all, so Live's queries are absent from the schema rather than present and answering with an error.
The API is shaped like the JavaScript client rather than a generic element API: a headless front end polls one cheap query and fetches updates only when the sequence has moved.
Poll liveFeed
liveFeed reads the post's head row — one indexed row, no element query:
{
liveFeed(postId: 923) {
seq
state
isLive
isFollowable
count
pinnedId
startedAt
endedAt
}
}
postId is the entry's ID. fieldId is optional — most entries carry one Live field and Live finds
it — and siteId defaults to the current site.
Fetch what you are missing
When seq has moved past what you hold, ask for everything after it:
{
liveUpdates(postId: 923, since: 412, orderBy: "seq asc") {
id
seq
rev
body
postedAt
typeHandle
... on goal_LiveUpdate {
scorer
}
}
}
Each update type has its own GraphQL type, <handle>_LiveUpdate, carrying its field layout's
fields.
liveUpdate returns one update and liveUpdateCount counts them. All three take the same
arguments:
| Argument | Narrows to |
|---|---|
postId | Updates on a given entry |
fieldId | Updates posted through a given Live field |
type / typeId | One or more update types, by handle or ID |
seq | Specific sequence numbers |
since | Updates after this sequence number — the polling query |
before | Updates below this sequence number — loading older ones |
pinned | The pinned update, or everything but it |
highlight | Key moments |
authorId | Updates by a given author |
plus the usual element arguments — limit, offset, orderBy, id.
Fields on an update
| Field | |
|---|---|
seq, rev | Sequence number, and revision (bumped on every edit) |
postId, fieldId | Where it belongs |
typeHandle, typeName, color, icon | Its update type |
body | Purified HTML |
source | What the editor typed, before it became HTML |
excerpt | A plain-text summary |
html | The update rendered through the site's own live/_update.twig |
pinned, highlight | Pinned, key moment |
postedAt | When it was posted |
authorId, authorName | Who posted it |
html is the same markup the server would have produced, which is useful when a JavaScript front
end wants the site's card rather than its own. It costs a template render per update, so it is only
produced when you ask for it.
Handling edits and deletions
An edited update keeps its seq and increments rev. A front end that keys on seq alone will
show the original wording forever: keep rev alongside, re-fetch an update when its rev changes,
and replace it in place.
The field on its entry
The Live field appears on its owner's GraphQL type and returns the same shape as liveFeed, with
an updates field that takes the arguments above:
{
entry(id: 923) {
... on liveMatch_Entry {
commentary {
seq
state
updates(limit: 20) {
seq
body
}
}
}
}
}
Schemas and tokens
Each update type is its own schema component, listed under Live in the schema editor as
Query for "Goal" live updates (liveupdatetypes.<uid>:read). A token can be given the match
commentary without being given the newsroom's internal feed.
A type outside the schema isn't merely filtered out of results: its GraphQL type doesn't exist for
that token at all. A token that can read none of the types on a post gets null from liveFeed,
so it can't learn the post's state either.
Grant read access to the update types a token needs, and nothing more. The schema decides what a token can read, so treat a Live update type the way you would an entry section.