✨Discover storytelling in the AI age with Pixar's Matthew Luhn at Sanity Connect, May 8th—register now


Listening for content changes through the API.

The listen endpoint can be used to receive events whenever documents are modified:

GET /v2021-06-07/data/listen/<dataset>?query=<GROQ-query>

This endpoint follows the server-sent events protocol using the mime-type text/event-stream. The backend will hold the connection open and stream events as they occur for any documents matching the GROQ query.


The number of concurrent listeners is defined by your project plan. See the technical limits for details.


  • querystring

    The GROQ-query used to filter the events. Only the top-level filter portion of the query will be used, anything else including projection, subqueries, slicing or aggregation will be ignored.

  • $-params

    Parameters to the query, if any (see the /data/query endpoint for details).

  • includeResultboolean

    Include the resulting document in addition to the changes.

  • includePreviousRevisionboolean

    Include the document as it looked before the change.

  • visibilitystring

    Specifies whether events should be sent as soon as a transaction has been committed (transaction, default), or only after they are available for queries (query). Note that this is best-effort, and listeners with query may in certain cases (notably with deferred transactions) receive events that are not yet visible to queries. The visibility event field will indicate the actual visibility.

  • evs_preamble

    Send a prolog of 2056 no-op characters for compatibility with older browsers.


A line starting with a colon is a comment and should be ignored. You will occasionally receive a single line with just one colon, as this is used for keep-alive.

welcome event

Sent when the listener is set up and ready to serve mutations:

event: welcome
data: {"listenerName": "Ua6BR3GwQ14cnZXrgwCdsF"}

mutation events

Sent whenever a document matching the listener's query is mutated:

event: mutation
id: lqgiok-skp-eja-k6z-9wrng7k5e#38123cba-286c-45a0-a6d1-3cc4dc43748a
data: <JSON-payload on a single line>

The payload is one single line of JSON, which in expanded form looks like this:

  // eventId: A unique id for this event, comprised of the transaction id and the document id
  "eventId": "pzeuul-awl-b69-ij3-g8862vgf3#drafts.38123cba-286c-45a0-a6d1-3cc4dc43748a",

  // documentId: The document changed by these mutations
  "documentId": "drafts.38123cba-286c-45a0-a6d1-3cc4dc43748a",

  // transactionId: The id of the transaction (one transaction may touch several documents, 
  // so you may get several messages with the same transactionId)
  "transactionId": "pzeuul-awl-b69-ij3-g8862vgf3",

  // transition: "update" means the document was updated, "appear" means the document just now started
  // matching your query. "disappear" means the document now left your scope. Appear/disappear may mean
  // the document is created/deleted, but it may also mean the properties of your document started/stopped
  // matching your query.
  "transition": "update",
  // identity: The identifier of the user submitting the changes
  "identity": "pJNdYiKyA",
  // mutations: an array of mutations as they were submitted in a call to /data/mutate. There may be several,
  // but they will all be from the same transaction, and they will all pertain to the document specified in
  // documentId.
  "mutations": [],
  // result: if includeResult url-parameter was submitted, this will contain the entire document as it looks after
  // the mutations.
  "result": {},
  // previous: if includePreviousRevision url-parameter was submitted, this will contain the document as it looked
  // before the mutations.
  "previous": {},
  // previousRev: The previous revision tag of the document before the changes (the current revision tag is always stored with
  // the document under the _rev key)
  "previousRev": "08p48x-bog-ro2-8sh-brvd69hcd",
  // resultRev: The revision tag after the changes. Due to the distributed nature of the Sanity backend, mutation events may 
  // appear out of order, in a very correct client the mutations must be reassembled to an unbroken chain where previousRev 
  // matches the resultRev of the previous mutation event.
  "resultRev": "pzeuul-awl-b69-ij3-g8862vgf3",
  // timestamp: The timestamp of the transaction causing this change
  "timestamp": "2017-11-22T10:24:01.801339Z",
  // visibility: Whether the change that triggered this event is visible to queries (query) or only to
  // subsequent transactions (transaction). The listener client can specify a preferred visbility through
  // the visibility parameter.
  "visibility": "transaction"

channelError events

Sent when there is an error during processing, typically when there is a syntax error in the query.

event: channelError
message: {"message": <the error message>}

disconnect events

Sent when the client should disconnect and stay disconnected, typically following a fatal channelError event (e.g. query syntax error) where reconnecting would simply repeat the error.

event: disconnect
data: {"reason": <a string describing the reason>}

Was this article helpful?