> ## Documentation Index
> Fetch the complete documentation index at: https://api.fanvue.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Update one of your experiences for this creator

> Updates an experience your app published for the creator whose token is calling. Only the fields sent change. Re-pricing mints a new price; fans who already paid keep what they bought. `actions` re-prices the actions listed and withdraws every other active one — declaring a new action is a publish, not an update.

    Hiding a published experience that fans have paid for answers 409 with the impact, exactly as a publish does. An experience owned by another app answers 404.

> [!NOTE]
>
> **Required scope**
>
> * `write:experience` — Request that the creator publish or unpublish a fan-facing experience. The app mints a request token; the creator confirms and Fanvue performs the change.


## OpenAPI

````yaml /openapi-v1.json patch /v1/experiences/{experienceUuid}
openapi: 3.1.0
info:
  title: Fanvue API
  version: '0.1'
servers:
  - url: https://api.fanvue.com
security: []
paths:
  /v1/experiences/{experienceUuid}:
    patch:
      summary: Update one of your experiences for this creator
      description: >-
        Updates an experience your app published for the creator whose token is
        calling. Only the fields sent change. Re-pricing mints a new price; fans
        who already paid keep what they bought. `actions` re-prices the actions
        listed and withdraws every other active one — declaring a new action is
        a publish, not an update.

            Hiding a published experience that fans have paid for answers 409 with the impact, exactly as a publish does. An experience owned by another app answers 404.
      operationId: updateExperience
      parameters:
        - $ref: '#/components/parameters/ApiVersionHeader'
        - schema:
            type: string
            format: uuid
            example: 00000000-0000-4000-8000-000000000010
          required: true
          name: experienceUuid
          in: path
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                appUuid:
                  type: string
                  format: uuid
                  description: Your app's UUID.
                title:
                  type: string
                  minLength: 1
                  maxLength: 100
                description:
                  type: string
                  maxLength: 500
                imageUrl:
                  type:
                    - string
                    - 'null'
                  maxLength: 2048
                  format: uri
                  description: >-
                    Replaces the cover. `null` clears it; omit to leave it
                    alone. One that cannot be fetched leaves the current cover
                    in place.
                  example: https://example.com/covers/photography-101.jpg
                accessMode:
                  type: string
                  enum:
                    - FREE
                    - SUBSCRIPTION
                    - PAID
                    - HIDDEN
                  description: >-
                    Moving an experience that is not PAID to `PAID` requires
                    `priceCents`; an experience that is PAID already keeps its
                    price unless re-priced.
                deliveryMode:
                  type: string
                  enum:
                    - EMBEDDED
                    - EXTERNAL
                externalUrl:
                  type:
                    - string
                    - 'null'
                  maxLength: 2048
                  format: uri
                  description: >-
                    Where an `EXTERNAL` experience opens. Must be https (checked
                    here). The platform additionally refuses Fanvue, localhost,
                    IP and dev-tunnel hosts; such a URL answers 400 with a
                    `message` naming the field.
                  example: https://example.com/experiences/photography-101
                hidden:
                  type: boolean
                  description: >-
                    Keep the experience off the creator's profile. Ignored when
                    accessMode is HIDDEN, which always hides.
                priceCents:
                  type: integer
                  minimum: 300
                  maximum: 50000
                  description: >-
                    Re-prices a PAID experience (send `accessMode: "PAID"`
                    alongside). Fans who already paid keep what they bought.
                  example: 1500
                priceRecurring:
                  type: boolean
                  description: >-
                    With `priceCents`: bill monthly as an app subscription
                    instead of a one-off unlock. Omitted, the experience keeps
                    the cadence of its current price.
                experienceType:
                  type: string
                  enum:
                    - LIVE_STREAM
                    - LIVE_AUDIO
                    - VIDEO
                    - AUDIO
                    - GAME
                    - CHALLENGE
                    - QUIZ
                    - EVENT
                    - OTHER
                  description: >-
                    What kind of experience this is. Decides how it presents
                    itself where it is embedded (for example the category tag on
                    a chat card). Omit for the generic `OTHER`.
                  example: GAME
                actions:
                  type: array
                  items:
                    type: object
                    properties:
                      externalActionId:
                        type: string
                        minLength: 1
                        maxLength: 255
                        example: spin
                      priceCents:
                        type: integer
                        minimum: 300
                        maximum: 50000
                        description: Price in USD cents, between 300 and 50000.
                        example: 1500
                    required:
                      - externalActionId
                      - priceCents
                  maxItems: 10
                  description: >-
                    Re-prices the actions listed and withdraws every other
                    active one. Only actions that already exist on the
                    experience may appear; declaring a new one is a publish.
                acknowledgePaidImpact:
                  type: boolean
                  description: >-
                    Set to `true` on a retry to accept the paid impact a
                    previous attempt answered 409 with. Send the 409's `impact`
                    alongside as `acknowledgedImpact`.
                  example: true
                acknowledgedImpact:
                  allOf:
                    - $ref: '#/components/schemas/ExperiencePaidImpact'
                    - description: >-
                        The `impact` the previous 409 reported, echoed back
                        verbatim.
              required:
                - appUuid
      responses:
        '200':
          description: The experience as it now stands
          content:
            application/json:
              schema:
                type: object
                properties:
                  experience:
                    $ref: '#/components/schemas/AppExperience'
                required:
                  - experience
              example:
                experience:
                  uuid: 00000000-0000-4000-8000-000000000010
                  appUuid: 00000000-0000-4000-8000-000000000001
                  creatorUuid: 00000000-0000-4000-8000-000000000002
                  externalExperienceId: course-photography-101
                  title: Photography 101
                  description: Six lessons, shot on film.
                  imageUrl: >-
                    https://cdn.fanvue.com/app-experiences/00000000-0000-4000-8000-000000000002/3f2a9c1d8e7b6a50.webp
                  accessMode: PAID
                  experienceType: VIDEO
                  deliveryMode: EMBEDDED
                  externalUrl: null
                  hidden: false
                  priceCents: 1500
                  priceRecurring: false
                  publishedAt: '2026-10-07T10:00:00.000Z'
                  suspendedAt: null
                  reviewStatus: approved
                  reviewRejection: null
                  pendingReviewSubmittedAt: null
                  isNsfw: false
                  url: https://www.fanvue.com/ava/experiences/photography-101
        '400':
          description: >-
            Bad Request - API version not supported OR validation failed OR
            invalid UUID OR a field was refused by the platform (its message
            names the field)
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/UnsupportedVersionError'
                  - $ref: '#/components/schemas/ValidationError'
                  - type: object
                    properties:
                      message:
                        type: string
                    required:
                      - message
                    additionalProperties: false
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          description: >-
            Three refusals, told apart by their shape. A named refusal the app
            can act on carries `error` and `message`: the creator is outside the
            fan-experiences rollout, has not installed the app, the app cannot
            carry experiences, or Fanvue has removed this experience
            (`experience_suspended`, lifted on reinstatement). The token lacking
            `write:experience` carries `error` alone (`Insufficient scopes`).
            The app named in `appUuid` not being the calling app carries
            `message` alone (`Forbidden`).
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '#/components/schemas/ExperienceWriteError'
                  - type: object
                    properties:
                      error:
                        type: string
                    required:
                      - error
                    additionalProperties: false
                  - type: object
                    properties:
                      message:
                        type: string
                    required:
                      - message
                    additionalProperties: false
        '404':
          description: Experience not found, or not your app's
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
        '409':
          description: >-
            Fans have paid for access this change takes away.
            `paid_impact_acknowledgement_required` is retried with the
            acknowledgement fields; `blocked_active_subscriptions` cannot
            proceed from the API
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExperiencePaidImpactConflict'
              example:
                error: paid_impact_acknowledgement_required
                message: >-
                  Fans have paid for access this would take away; acknowledge
                  the paid impact to proceed.
                impact:
                  affectedFanCount: 3
                  activeSubscriptionCount: 0
                  pendingSubscriptionInvoiceCount: 0
                  oneTimePurchaseCount: 3
                  pendingPurchaseCount: 0
        '410':
          $ref: '#/components/responses/SunsetVersionResponse'
        '429':
          $ref: '#/components/responses/RateLimitResponse'
        '502':
          description: The write could not be completed against the upstream
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
        '503':
          description: Developer API upstream is not configured
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
      security:
        - BearerAuth:
            - write:experience
components:
  parameters:
    ApiVersionHeader:
      name: X-Fanvue-API-Version
      in: header
      required: true
      schema:
        type: string
        default: '2025-06-26'
        example: '2025-06-26'
      description: API version to use for the request
  schemas:
    ExperiencePaidImpact:
      type: object
      properties:
        affectedFanCount:
          type: integer
          minimum: 0
          description: >-
            Distinct fans holding paid access right now, across subscriptions
            and purchases.
          example: 3
        activeSubscriptionCount:
          type: integer
          minimum: 0
          description: >-
            Subscriptions that still grant access. Any at all blocks the change
            outright.
          example: 0
        pendingSubscriptionInvoiceCount:
          type: integer
          minimum: 0
          description: >-
            In-flight initial subscription charges. Block, like a settled
            subscription.
          example: 0
        oneTimePurchaseCount:
          type: integer
          minimum: 0
          description: >-
            Distinct fans holding a settled one-off purchase. Needs
            acknowledging.
          example: 3
        pendingPurchaseCount:
          type: integer
          minimum: 0
          description: >-
            In-flight one-off purchase attempts. Need acknowledging, like a
            settled purchase.
          example: 0
      required:
        - affectedFanCount
        - activeSubscriptionCount
        - pendingSubscriptionInvoiceCount
        - oneTimePurchaseCount
        - pendingPurchaseCount
    AppExperience:
      type: object
      properties:
        uuid:
          type: string
          format: uuid
        appUuid:
          type: string
          format: uuid
        creatorUuid:
          type: string
          format: uuid
        externalExperienceId:
          type: string
          description: Your own stable id for the experience, as you published it.
          example: course-photography-101
        title:
          type: string
        description:
          type: string
        imageUrl:
          type:
            - string
            - 'null'
          description: >-
            Public URL of the cover Fanvue stored, or `null` when none was kept
            (none sent, or the one sent could not be fetched).
        accessMode:
          type: string
          enum:
            - FREE
            - SUBSCRIPTION
            - PAID
            - HIDDEN
        experienceType:
          type: string
          enum:
            - LIVE_STREAM
            - LIVE_AUDIO
            - VIDEO
            - AUDIO
            - GAME
            - CHALLENGE
            - QUIZ
            - EVENT
            - OTHER
          description: What kind of experience this is; `OTHER` when nothing declared one.
        deliveryMode:
          type: string
          enum:
            - EMBEDDED
            - EXTERNAL
        externalUrl:
          type:
            - string
            - 'null'
          description: Where an `EXTERNAL` experience opens; `null` for `EMBEDDED`.
        hidden:
          type: boolean
          description: >-
            Share-link only, never listed on the creator's profile. Always
            `true` for `HIDDEN`.
        priceCents:
          type:
            - integer
            - 'null'
          description: >-
            Price in USD cents behind a `PAID` experience; `null` for every
            other mode.
          example: 1500
        priceRecurring:
          type: boolean
          description: >-
            Whether that price bills monthly as an app subscription rather than
            once.
        publishedAt:
          type:
            - string
            - 'null'
          description: When it was published (ISO 8601); `null` while unpublished.
          example: '2026-10-07T10:00:00.000Z'
        suspendedAt:
          type:
            - string
            - 'null'
          format: date-time
          description: >-
            When Fanvue removed it for a policy reason (ISO 8601); `null` for a
            live or merely unpublished experience. A suspended experience is not
            listed, cannot be launched and refuses a publish or update with
            `experience_suspended` until Fanvue reinstates it; keep your record
            of it rather than deleting it.
          example: null
        reviewStatus:
          type: string
          enum:
            - pending_review
            - approved
            - rejected
          description: >-
            Where the experience stands in Fanvue's review. Publishing submits
            it for review (`pending_review`); fans see it once `approved`, while
            it is also published and not suspended. Editing the title,
            description, cover, delivery mode or external link of an approved
            experience keeps the approved version live for fans and submits the
            edit for review, shown by `pendingReviewSubmittedAt`; price, access
            and visibility changes are not reviewed. A `rejected` experience is
            offline and goes back into review when you publish it again. Its
            creator, and Fanvue staff testing it, can open it in every state.
          example: approved
        reviewRejection:
          $ref: '#/components/schemas/ExperienceReviewRejection'
        pendingReviewSubmittedAt:
          type:
            - string
            - 'null'
          format: date-time
          description: >-
            When an edit to an approved experience was submitted for review (ISO
            8601); `null` when no edit is waiting. Fans keep seeing the approved
            version until Fanvue decides; the fields returned here are the
            edited ones.
          example: null
        isNsfw:
          type: boolean
          description: >-
            Whether the experience is NSFW, because its creator's profile is not
            marked safe for work or the app is rated NSFW. Fans must pass age
            verification to open an NSFW experience, and a fan in safe mode is
            warned first.
          example: false
        url:
          type: string
          description: >-
            The share link fans land on: `/{handle}/experiences/{slug}` for a
            listed experience, keyed by the uuid instead when `hidden` so the
            link stays unguessable. Chat cards and link previews recognise it.
          example: https://www.fanvue.com/ava/experiences/summer-yoga-course
      required:
        - uuid
        - appUuid
        - creatorUuid
        - externalExperienceId
        - title
        - description
        - imageUrl
        - accessMode
        - experienceType
        - deliveryMode
        - externalUrl
        - hidden
        - priceCents
        - priceRecurring
        - publishedAt
        - suspendedAt
        - reviewStatus
        - reviewRejection
        - pendingReviewSubmittedAt
        - isNsfw
        - url
    UnsupportedVersionError:
      type: object
      properties:
        error:
          type: string
        message:
          type: string
      required:
        - error
        - message
      description: API version not supported
    ValidationError:
      type: object
      properties:
        errors:
          type: array
          items:
            type: string
      required:
        - errors
      description: Request validation failed
    ExperienceWriteError:
      type: object
      properties:
        error:
          type: string
          enum:
            - fan_experiences_not_enabled
            - app_not_installed
            - app_not_available
            - experience_suspended
          description: >-
            `fan_experiences_not_enabled`: the creator is outside the
            fan-experiences rollout. `app_not_installed`: the creator has not
            installed your app. `app_not_available`: your app is not approved,
            suspended or archived, so it cannot carry experiences.
            `experience_suspended`: Fanvue removed this experience for a policy
            reason; it refuses writes until Fanvue reinstates it.
        message:
          type: string
      required:
        - error
        - message
    ExperiencePaidImpactConflict:
      type: object
      properties:
        error:
          type: string
          enum:
            - paid_impact_acknowledgement_required
            - blocked_active_subscriptions
          description: >-
            `paid_impact_acknowledgement_required`: fans have paid for access
            this change takes away; retry with `acknowledgePaidImpact: true` and
            the `impact` below as `acknowledgedImpact`.
            `blocked_active_subscriptions`: fans hold live recurring access, so
            the change cannot proceed from the API at all.
        message:
          type: string
        impact:
          $ref: '#/components/schemas/ExperiencePaidImpact'
      required:
        - error
        - message
        - impact
    ExperienceReviewRejection:
      type:
        - object
        - 'null'
      properties:
        reasonCodes:
          type: array
          items:
            type: string
          description: >-
            The listing requirement sections Fanvue cited, such as `7.3`; see
            the App Store listing requirements.
          example:
            - '7.3'
        message:
          type: string
          description: Fanvue's explanation, written for the creator.
          example: The cover and title do not match what the experience shows fans.
      required:
        - reasonCodes
        - message
      description: >-
        Why Fanvue rejected the experience; `null` unless `reviewStatus` is
        `rejected`.
  responses:
    UnauthorizedResponse:
      description: Unauthorized Response
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
            required:
              - error
    SunsetVersionResponse:
      description: API version no longer supported (sunset)
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
              message:
                type: string
              nextVersion:
                type: string
            required:
              - error
              - message
    RateLimitResponse:
      description: Too many requests - rate limit exceeded
      headers:
        Retry-After:
          description: Number of seconds to wait before retrying the request
          schema:
            type: integer
        X-RateLimit-Limit:
          description: The maximum number of requests allowed in the current window
          schema:
            type: integer
        X-RateLimit-Remaining:
          description: The number of requests remaining in the current window
          schema:
            type: integer
        X-RateLimit-Reset:
          description: The Unix timestamp (seconds) when the rate limit window resets
          schema:
            type: integer
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
            required:
              - error
  securitySchemes:
    BearerAuth:
      type: oauth2
      description: >-
        OAuth 2.0 access token, presented as a JWT bearer token in the
        `Authorization` header. Obtain a token via the authorization-code flow;
        the scopes granted to the token determine which operations it may call.
      flows:
        authorizationCode:
          authorizationUrl: https://auth.fanvue.com/oauth2/auth
          tokenUrl: https://auth.fanvue.com/oauth2/token
          refreshUrl: https://auth.fanvue.com/oauth2/token
          scopes:
            read:self: >-
              Access your own user profile information, including basic account
              details and settings.
            read:chat: >-
              Read chat conversations, messages, and chat-related data. This
              includes viewing chat lists and message history.
            write:chat: >-
              Create new chats and send messages. This scope is required for any
              chat-related actions that modify data.
            read:experience: >-
              Exchange a fan's experience token for the resolved experience and
              the fan's identity, so an embedded fan-facing experience can
              render the right content.
            write:experience: >-
              Request that the creator publish or unpublish a fan-facing
              experience. The app mints a request token; the creator confirms
              and Fanvue performs the change.
            read:fan: Access fan-related data and information within the platform.
            read:post: Read posts, including post details, comments, likes, and tips.
            write:post: Create, edit, and manage posts and content on behalf of users.
            read:media: Access media files, images, videos, and other content assets.
            write:media: >-
              Upload, modify, and manage media files and content assets. Also
              required for vault folder management.
            read:creator: >-
              Access creator profiles, content, and creator-specific
              information.
            write:creator: Modify creator profiles, settings, and creator-specific data.
            read:insights: >-
              Access analytics, metrics, and insights data for performance
              tracking.
            read:tracking_links: >-
              Read tracking links and the users associated with them, including
              per-user tracking metadata.
            write:tracking_links: Create and delete tracking links.
            read:agency: Read agency information, including the agency's team members.
            write:agency: >-
              Manage agency team members and invites, including inviting new
              team members and creators.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.