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

# Choose the billing cadence of an offering on your brand

> Chooses how members are billed for one offering on one of your brands: `monthly` (a charge every month of the medication's supply) or `upfront` (one charge for the whole term). Only a cadence that is compatible with the offering's supply and its shipping rules is accepted; any other is refused with the reason and the cadences you can choose instead. You never set the shipping cadence: it always follows the offering's supply, and a body that names one is refused. When exactly one billing cadence is compatible, the platform sets it for you when the offering is enabled and already has its copy, or when its copy is adopted, so this call is needed only when you have a choice. The offering must be enabled on the brand and have its copy (adopt the starter merchandising, or publish your own) before a cadence can be chosen. Choosing again replaces your earlier choice; the platform never overwrites a choice you made. Every change is recorded in your brand's audit trail, attributed to your account. Repeating a completed request with the same Idempotency-Key returns the original result.



## OpenAPI

````yaml /openapi/public-openapi.json put /v1/account/brands/{brand_id}/offerings/{offering_ref}/billing-cadence
openapi: 3.1.0
info:
  title: Purple API
  version: 0.0.0
servers:
  - url: https://api.staging.purplelabelmd.com
security: []
tags:
  - description: >-
      Browser redirects that begin, complete and end a sign-in on the API host.
      Patients sign in on your member portal instead, at
      https://{MEMBER_HOST}/auth/login?returnTo=/home.
    name: Sessions & authentication
  - description: Run the server-driven intake questionnaire question by question.
    name: Intake
  - description: Address autocomplete for the intake flow.
    name: Addresses
  - description: Read the public status of a patient's enrollment.
    name: Enrollment
  - description: Track a client's onboarding progress.
    name: Onboarding
  - description: Read back the platform configuration stored for your brand.
    name: Brand configuration
  - description: Enable offerings for your brand and set their display copy.
    name: Offering configuration
  - description: Start and track payments for an order.
    name: Payments
  - description: Subscribe to platform events and manage delivery endpoints.
    name: Webhooks
paths:
  /v1/account/brands/{brand_id}/offerings/{offering_ref}/billing-cadence:
    put:
      tags:
        - Offering configuration
      summary: Choose the billing cadence of an offering on your brand
      description: >-
        Chooses how members are billed for one offering on one of your brands:
        `monthly` (a charge every month of the medication's supply) or `upfront`
        (one charge for the whole term). Only a cadence that is compatible with
        the offering's supply and its shipping rules is accepted; any other is
        refused with the reason and the cadences you can choose instead. You
        never set the shipping cadence: it always follows the offering's supply,
        and a body that names one is refused. When exactly one billing cadence
        is compatible, the platform sets it for you when the offering is enabled
        and already has its copy, or when its copy is adopted, so this call is
        needed only when you have a choice. The offering must be enabled on the
        brand and have its copy (adopt the starter merchandising, or publish
        your own) before a cadence can be chosen. Choosing again replaces your
        earlier choice; the platform never overwrites a choice you made. Every
        change is recorded in your brand's audit trail, attributed to your
        account. Repeating a completed request with the same Idempotency-Key
        returns the original result.
      operationId: setOwnBillingCadence
      parameters:
        - description: >-
            The brand the offering is enabled on. Must be one of your account's
            own brands.
          in: path
          name: brand_id
          required: true
          schema:
            type: string
        - description: The offering code, as listed for your brand.
          in: path
          name: offering_ref
          required: true
          schema:
            type: string
        - $ref: '#/components/parameters/CatalogIdempotencyKey'
        - $ref: '#/components/parameters/BrandIdHeader'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SetOwnBillingCadenceRequest'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                properties:
                  data:
                    $ref: '#/components/schemas/OwnBillingCadence'
                type: object
          description: >-
            the billing cadence you chose, with the shipping cadence it follows;
            or an idempotent replay of the original result
        '400':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/CatalogProblem'
          description: >-
            missing Idempotency-Key, or a malformed body (billing must be
            monthly or upfront, and nothing else may be sent)
        '401':
          $ref: '#/components/responses/CatalogServiceIdentityRequired'
        '404':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/CatalogProblem'
          description: >-
            no such brand for this account (an unknown brand and another
            account's brand are one indistinguishable refusal), the offering is
            not enabled on the brand, or the offering has no copy yet — nothing
            was set
        '409':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/CatalogProblem'
          description: >-
            Idempotency-Key reused with a materially different request (code
            IDEMPOTENCY_CONFLICT)
        '422':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/CatalogProblem'
          description: >-
            the billing cadence is not compatible with the offering's supply or
            its shipping rules (CADENCE_INCOMPATIBLE), its compatibility cannot
            be measured yet (CADENCE_NOT_MEASURED), or the body names a shipping
            cadence, which always follows the offering's supply
            (CADENCE_SHIPPING_DERIVED). The problem carries
            `compatible_billing`, the cadences you can choose instead. Nothing
            was set.
        '501':
          $ref: '#/components/responses/CatalogCollectionUnavailable'
        '503':
          $ref: '#/components/responses/CatalogStateUnconfirmed'
      security:
        - apiKey: []
components:
  parameters:
    CatalogIdempotencyKey:
      description: >-
        Required on every mutation. Replaying the same request with the same key
        returns the original result; reusing the key with a materially different
        request is rejected 409 with machine code IDEMPOTENCY_CONFLICT.
      in: header
      name: Idempotency-Key
      required: true
      schema:
        minLength: 1
        type: string
    BrandIdHeader:
      description: >-
        Your brand id (`brd_...`). It must be one of the brands your API key's
        account owns; with a publishable key it must be the one brand the key
        was issued for. A missing or malformed value is refused with `400`, and
        an unknown or foreign brand with `404`.
      in: header
      name: X-Brand-Id
      required: true
      schema:
        pattern: ^brd_[A-Za-z0-9][A-Za-z0-9_-]*$
        type: string
  schemas:
    SetOwnBillingCadenceRequest:
      additionalProperties: false
      description: >-
        The billing cadence you choose for the offering. Nothing else rides the
        body: the shipping cadence always follows the offering's supply, and the
        brand and offering come from the path.
      properties:
        billing:
          description: >-
            `monthly` charges every month of the medication's supply; `upfront`
            charges once for the whole term.
          enum:
            - monthly
            - upfront
          type: string
      required:
        - billing
      type: object
    OwnBillingCadence:
      description: >-
        The billing cadence now set for the offering, and the shipping cadence
        it follows.
      properties:
        billing:
          enum:
            - monthly
            - upfront
          type: string
        billing_frequency:
          description: how often a member is charged
          enum:
            - monthly
            - quarterly
            - semiannual
            - annual
          type: string
        brand_id:
          type: string
        offering_ref:
          type: string
        shipping_frequency:
          description: >-
            how often the offering ships, when its supply matches one of these
            exactly
          enum:
            - none
            - weekly
            - biweekly
            - monthly
            - quarterly
          type: string
        shipping_interval_days:
          description: >-
            days between shipments (the supply's days), when the offering ships
            on a schedule
          type: integer
      required:
        - brand_id
        - offering_ref
        - billing
        - billing_frequency
      type: object
    CatalogProblem:
      description: >-
        RFC 7807 problem+json (a 409 idempotency conflict carries
        code=IDEMPOTENCY_CONFLICT)
      properties:
        adoption:
          $ref: '#/components/schemas/CatalogNormalizationSummary'
        code:
          description: machine-readable error code, e.g. IDEMPOTENCY_CONFLICT
          type: string
        detail:
          type: string
        instance:
          type: string
        reason:
          description: >-
            machine-readable reason beside the code, present only where a
            refusal has one (a PRICE_FLOOR_UNRESOLVABLE refusal carries the
            price check's typed reason, e.g. no_platform_price_binding). Key on
            this member, never on the detail's words.
          pattern: ^[a-z][a-z0-9_]{0,63}$
          type: string
        status:
          type: integer
        title:
          type: string
        type:
          type: string
      required:
        - title
        - status
      type: object
    CatalogNormalizationSummary:
      properties:
        applied:
          type: boolean
        counts:
          properties:
            rows_examined:
              minimum: 0
              type: integer
            rows_written:
              minimum: 0
              type: integer
            values_written:
              minimum: 0
              type: integer
          required:
            - rows_examined
            - rows_written
            - values_written
          type: object
        mode:
          enum:
            - dry-run
            - apply
          type: string
        receipt:
          $ref: '#/components/schemas/CatalogNormalizationReceipt'
        refused:
          type: boolean
        report_ref:
          properties:
            adoption_run_id:
              type: string
            medication_sku:
              type: string
          required:
            - medication_sku
            - adoption_run_id
          type: object
        run_id:
          type: string
      required:
        - run_id
        - mode
        - applied
        - report_ref
        - counts
      type: object
    CatalogNormalizationReceipt:
      additionalProperties: false
      properties:
        at:
          format: date-time
          type: string
        groups_digest:
          pattern: ^[a-f0-9]{64}$
          type: string
        preview_digest:
          pattern: ^[a-f0-9]{64}$
          type: string
        request_digest:
          pattern: ^[a-f0-9]{64}$
          type: string
        run_id:
          type: string
        served_digest:
          pattern: ^[a-f0-9]{64}$
          type: string
      required:
        - run_id
        - at
        - served_digest
        - request_digest
        - groups_digest
        - preview_digest
      type: object
  responses:
    CatalogServiceIdentityRequired:
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/CatalogProblem'
      description: >-
        No verified service identity for this request. Absent, malformed,
        forged, expired, wrong issuer/audience/alg, an unlisted caller, a
        missing platform_service scope, and a caller not permitted this route or
        these identity headers ALL answer this one byte-identical refusal
        (machine code SERVICE_IDENTITY_REQUIRED). It names no caller and no
        accepted identity. Only returned when the deployment enforces caller
        authentication.
    CatalogCollectionUnavailable:
      content:
        application/problem+json:
          schema:
            allOf:
              - $ref: '#/components/schemas/CatalogProblem'
              - properties:
                  collection:
                    description: the document collection the Postgres catalog does not hold
                    type: string
                type: object
      description: >-
        Under the Postgres catalog store (PURPLE_CATALOG_STORE=postgres) only:
        the write would add or change a record the Postgres catalog does not
        hold yet (machine code CATALOG_COLLECTION_UNAVAILABLE; the `collection`
        member names it). No change was activated.
    CatalogStateUnconfirmed:
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/CatalogProblem'
      description: >-
        Under the Postgres catalog store (PURPLE_CATALOG_STORE=postgres) only,
        retryable. Machine code CATALOG_STATE_UNCONFIRMED: the per-request check
        that the served catalog is current could not run; nothing was served or
        written. Machine code CATALOG_STATE_STALE (writes only): another catalog
        task wrote first, so this write was derived from a superseded state; no
        change was activated, and the next request reloads.
  securitySchemes:
    apiKey:
      description: 'Per-client API key (M2M). Presented as `Authorization: Bearer <key>`.'
      scheme: bearer
      type: http

````

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