---
title: "Update a Persona"
method: PATCH
path: "/context/brands/{slug}/personas/{personaSlug}"
tags: ["Personas"]
---

# Update a Persona

`PATCH /context/brands/{slug}/personas/{personaSlug}`

## Request

- Base URL: `https://api.adcrunch.dev`
- URL: `https://api.adcrunch.dev/context/brands/{slug}/personas/{personaSlug}`
- Auth: HTTP bearer

Updates a Persona. Send the `base_revision` you read. Omit a section or an age bound to keep it. Send `null` to clear it. AdCrunch checks the age range on the result of the merge. Therefore a call that sends only `age_min` can still fail, if the result is inverted. The slug changes only when you send a `slug`: a new `name` alone never moves the handle. The answer is `409` with `error=revision_mismatch` if the Persona changed after you read it. It is `409` with `error=slug_conflict` if another Persona of this Brand already holds the `slug` you send.

## Path parameters

- `personaSlug` string, required
- `slug` string, required

## Request body

- object
  - `age_max` integer, nullable: Upper age bound; null clears it ("and older").
  - `age_min` integer, nullable: Lower age bound; null clears it ("and younger").
  - `base_revision` integer, required: The revision last read via GET — guards concurrent edits.
  - `description` string
  - `frictions` string, nullable: Objections and barriers; null clears it.
  - `language` string, nullable: The audience's own words — not a locale; null clears it.
  - `motivations` string, nullable: Jobs, triggers, outcomes; null clears it.
  - `name` string
  - `profile` string, nullable: Who they are; null clears it.
  - `slug` string: Optional new slug handle (a deliberate rename).

## Response `200`

The Persona as it now stands, at the next `revision`. Send that one back on your next edit.

- object
  - `ageMax` number, nullable, required
  - `ageMin` number, nullable, required: Each bound is independently optional, so "35+" is expressible.
  - `brandId` string, required
  - `createdAt` number, required: Milliseconds since the Unix epoch, UTC.
  - `createdBy` string, required
  - `description` string, required
  - `frictions` string, nullable, required: Objections, doubts, what stops them.
  - `id` string, required
  - `language` string, nullable, required: The words *they* use for the problem, in their own register. Not a locale, despite the name.
  - `motivations` string, nullable, required: What they want, and what triggers them.
  - `name` string, required
  - `profile` string, nullable, required: Who they are, and their situation.
  - `revision` number, required: Increments on every write. Send it back as `base_revision` to edit; a stale one answers 409.
  - `slug` string, required
  - `updatedAt` number, nullable, required: Milliseconds since the Unix epoch, UTC.

## Other responses

- `400`: The request does not match the schema of this operation: a field is missing or has the wrong type, or the body is not valid JSON. `error` is `invalid_request`, and `issues` names each field. Nothing was changed.
- `401`: No API key, or one that does not resolve. See the security scheme. `error` is `unauthorized`.
- `402`: The organization has no active subscription. An owner subscribes at `paywallUrl`. `error` is `organization_unentitled`.
- `403`: The caller does not hold `brand:write`. `error` is `forbidden`.
- `404`: No such Brand, or no Persona with that slug inside it. `error` is `not_found`.
- `409`: `error` tells the two conflicts apart: `revision_mismatch` and `slug_conflict`.
- `422`: `invalid_slug`, or `invalid_age_range`. The age range is checked against the **merged** result, so sending only `age_min` can still be rejected as inverted.

---

[API](https://skmtc.dev/adcrunch/apis/adcrunch-api.md) · [All operations](https://skmtc.dev/adcrunch/apis/adcrunch-api/llms.txt) · [OpenAPI document](https://skmtc.dev/adcrunch/apis/adcrunch-api/revisions/a420ba80914f?raw)
