Content API

Mutations and transactions

create, createIfNotExists, createOrReplace, patch and delete — applied as one Postgres transaction, with optimistic concurrency and constraint enforcement.

Every mutation request is one Postgres transaction. Either all of it applies or none of it does.

ts
await client
  .transaction()
  .createIfNotExists({ _id: 'author-jane', _type: 'author', name: 'Jane' })
  .create({
    _id: 'post-new',
    _type: 'post',
    title: 'A new post',
    author: { _type: 'reference', _ref: 'author-jane' },
  })
  .commit()

That works on an empty database because the constraint check counts the transaction's own effects as state: the reference resolves against the author the same transaction is creating.

The operations

OperationBehaviour
createFails if the id exists.
createIfNotExistsReturns the existing document untouched.
createOrReplaceWrites unconditionally.
patchApplies set, setIfMissing, unset, inc, dec, insert and diffMatchPatch.
deleteBy id, or by query.

Patching arrays

Array members are addressed by _key, not by index, which is what makes concurrent editing of a long array safe:

ts
await client
  .patch('home')
  .set({ 'sections[_key=="hero"].heading': 'A new heading' })
  .commit()

diffMatchPatch

The Studio sends text edits as diff-match-patch payloads rather than whole values, so two people editing different paragraphs of one field do not clobber each other.

Optimistic concurrency

ts
await client.patch('post-1', { ifRevisionID: knownRev }).set({ title: 'Renamed' }).commit()

A revision mismatch is reported as a conflict. Without one, last write wins — which is occasionally what you want and usually not.