Skip to content
AdCrunch
Esc
↑↓navigate↵open⌘Jpreview
On this page

Edit without overwriting

Change a Skill, a Brand, a Persona, a Campaign Plan, or a Line Item without overwriting an edit that somebody else made after you read it.

People in the console and agents over MCP edit the same rows as your code, at the same time. So the Context API guards each write. You send the revision that you read. AdCrunch refuses the write when the row changed after that revision.

The revision

Skills, Brands, Personas, Campaign Plans, and Line Items each carry a revision. It is an integer, and each write adds one to it. A create answers the first revision. Each read answers the current revision.

A Line Item has its own revision. No operation reads one Line Item. Read its Campaign Plan: lineItems holds each Line Item with its revision.

Send it back

Each write that changes a guarded row needs the revision that you read. Most writes take it as base_revision. The re-import of a Skill takes it as baseRevision, because a request field that Context added later is camelCase (Casing).

Operation Field Where it goes
PATCH base_revision in the body
DELETE base_revision in the query string, for example ?base_revision=4
Approve a Campaign Plan, validate a Line Item base_revision in the body
Re-import a Skill baseRevision in the body
curl -X PATCH https://api.adcrunch.dev/context/brands/acme \
  -H "Authorization: Bearer $ADCRUNCH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "base_revision": 4, "voice": "Warm, direct, and never ironic." }'

In a PATCH, a field that you omit keeps its value. null clears a field that can be empty. The page of each operation shows which fields can be empty.

An approval and a validation also take base_revision. So an approval applies to the content that you read, and not to the content that the row holds at the moment of the approval.

A re-import of a Skill also takes the revision. The re-import replaces the content of the Skill, so the guard keeps it from replacing an edit that you did not read.

When somebody wrote first

The write answers 409, and it changes nothing:

{
  "error": "revision_mismatch",
  "message": "…",
  "currentRevision": 5
}

Do this:

  1. Read the row again.
  2. Apply your change to what you read.
  3. Send the write again, with the new revision as base_revision, or as baseRevision on a re-import.

Do not send currentRevision back without step 1. The write then succeeds, and it overwrites the edit that caused the conflict.

A 409 can also have error: "slug_conflict". A rename gives a slug that another row of the same kind already holds. Branch on error to tell the two apart.

What the API does not guard

Documents and Assets have no revision. A rename of an Asset (PATCH /assets/{id}) and a delete of a Document apply at once.

Was this page helpful?