How to get changed fields from Sanity History API for diffing?
The History API's /data/history/:dataset/transactions/:id endpoint does give you access to transaction data with the actual content changes, which allows you to do field-level diffs. The key is understanding which parameters to use and how to interpret the response.
Getting Field-Level Changes
When you call the transactions endpoint, the response is in NDJSON format and includes mutations for each transaction. These mutations show the actual changes made to documents.
Key Parameters
excludeContent (boolean, default: false, required)
- Keep this as
false(the default) to get the actual document content and changes - Setting it to
truewould only give you transaction metadata without the changes themselves
effectFormat (string, default: "mendoza")
- This controls how changes are expressed
- Mendoza is Sanity's efficient format specifically designed for expressing differences between JSON documents
- This is essentially a diff format built into the API!
Practical Approach
// Fetch transactions with full content
const response = await fetch(
`https://${projectId}.api.sanity.io/v2023-02-01/data/history/${dataset}/transactions/${documentId}?excludeContent=false&effectFormat=mendoza`,
{
headers: {
Authorization: `Bearer ${token}`
}
}
)
// Response is NDJSON - each line is a transaction
const ndjson = await response.text()
const transactions = ndjson.trim().split('\n').map(line => JSON.parse(line))
// Each transaction contains mutations showing what changed
transactions.forEach(transaction => {
console.log('Transaction ID:', transaction.id)
console.log('Timestamp:', transaction.timestamp)
console.log('Mutations:', transaction.mutations)
// Mutations contain the actual changes
transaction.mutations.forEach(mutation => {
if (mutation.patch) {
// Patch operations show field-level changes
console.log('Patched fields:', mutation.patch)
}
if (mutation.create || mutation.createOrReplace) {
// Full document on create
console.log('Created document:', mutation.create || mutation.createOrReplace)
}
})
})Understanding the Mutations
The mutations array in each transaction contains operations that show exactly what changed:
patchoperations show field-level modifications withset,unset,inc, etc.create/createOrReplaceoperations include the full documentdeleteoperations show document removal
For patch operations specifically, you'll see the exact fields being modified, which gives you the field-level diff you're looking for.
Additional Filtering
The endpoint also supports:
fromTime/toTime- Filter by timestamp rangefromTransaction/toTransaction- Filter by transaction ID rangereverse- Get transactions in reverse chronological orderlimit- Limit number of transactions returned
These parameters help you narrow down to specific time periods or transaction ranges when building your diff functionality.
Show original thread6 replies
Sanity β Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.