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

# Update a booking

> Edits a booking by its 1club id: reschedule it, move it to another area, attach or remove an instructor, reassign the contact, change its notes or price, or make it recur. Send only the fields that change. Reaches the same bookings as cancel: an API key only those it created, a staff member through an authorized 1club assistant any of the organization's.

The edit follows the admin portal's rules. A cancelled booking is final, and a booking on a class takes its time and price from the class. As on create, the club's member-facing policy (operating hours, instructor availability) is not applied, but an occupied or blocked court, or a coach who is already booked, is refused with `details.conflicts[]`.

Money follows the edit. `amount` reprices the booking to your figure. Without it, a booking this API created keeps its price, and a booking taken through 1club is re-quoted when the slot, area, instructor or contact changes. The charge is then reconciled: an increase on a paid booking leaves the difference outstanding, and a decrease below what was paid needs a refund, which this endpoint does not perform. Payment status cannot be changed here.

Recurring bookings. `recurrence` on a one-off booking makes it the first occurrence of a series. On an occurrence of a series, `scope=all_future` applies the edit to every occurrence that has not started yet, from the earliest upcoming one: a new `startTime`/`endTime` gives each that time of day on its own date (the weekday changes only through `recurrence.daysOfWeek`), a new area or instructor is checked against every date, and a new `recurrence` rewrites the cadence or end condition; days dropped from a weekly pattern are cancelled with their refund. A series bound to a recurring class follows the class and cannot be re-timed, and a booking an API key created cannot be made to recur at all (`RECURRENCE_NOT_AVAILABLE_TO_MANAGING_KEY`): 1club would be generating occurrences that key never created, so each one is its own booking. An edit whose series has already run touches nothing.




## OpenAPI

````yaml /openapi-platform.json patch /v1/platform/bookings/{id}
openapi: 3.0.0
info:
  title: 1club Platform API
  version: 1.0.0
  description: >-
    The 1club Platform API lets you programmatically access and manage your
    organization's data.


    ## Official API Contract


    This documentation is the official source of truth for the 1club Platform
    API.

    If an integration relies on undocumented endpoints, fields, response shapes,
    or internal behavior outside this spec, we can't guarantee backward
    compatibility.

    Build against what's documented here to stay stable as the platform evolves.


    ## Authentication


    All requests require a customer API key passed as a Bearer token:


    ```

    Authorization: Bearer 1club_sk_live_...

    ```


    Generate API keys from the admin portal under **Settings > API Tokens**.

    The key is tied to your organization - all responses are scoped to your
    org's data.


    ## Rate Limiting


    - **100 requests per minute** per API key

    - When exceeded, the API returns `429 Too Many Requests` with a
    `Retry-After` header

    - Rate limit headers are included in every response:
      - `X-RateLimit-Limit` - max requests per window
      - `X-RateLimit-Remaining` - requests remaining
      - `X-RateLimit-Reset` - seconds until the window resets

    ## Errors


    | Status | Meaning |

    |--------|---------|

    | `400` | Invalid request parameters |

    | `401` | Missing or invalid API key |

    | `404` | Resource not found (or doesn't belong to your organization) |

    | `429` | Rate limit exceeded |

    | `500` | Internal server error |
  contact:
    name: 1club API Support
    email: support@1club.ai
servers:
  - url: https://api.1club.ai
    description: Production API
security:
  - customerApiAuth: []
tags: []
paths:
  /v1/platform/bookings/{id}:
    patch:
      tags:
        - Bookings
      summary: Update a booking
      description: >
        Edits a booking by its 1club id: reschedule it, move it to another area,
        attach or remove an instructor, reassign the contact, change its notes
        or price, or make it recur. Send only the fields that change. Reaches
        the same bookings as cancel: an API key only those it created, a staff
        member through an authorized 1club assistant any of the organization's.


        The edit follows the admin portal's rules. A cancelled booking is final,
        and a booking on a class takes its time and price from the class. As on
        create, the club's member-facing policy (operating hours, instructor
        availability) is not applied, but an occupied or blocked court, or a
        coach who is already booked, is refused with `details.conflicts[]`.


        Money follows the edit. `amount` reprices the booking to your figure.
        Without it, a booking this API created keeps its price, and a booking
        taken through 1club is re-quoted when the slot, area, instructor or
        contact changes. The charge is then reconciled: an increase on a paid
        booking leaves the difference outstanding, and a decrease below what was
        paid needs a refund, which this endpoint does not perform. Payment
        status cannot be changed here.


        Recurring bookings. `recurrence` on a one-off booking makes it the first
        occurrence of a series. On an occurrence of a series, `scope=all_future`
        applies the edit to every occurrence that has not started yet, from the
        earliest upcoming one: a new `startTime`/`endTime` gives each that time
        of day on its own date (the weekday changes only through
        `recurrence.daysOfWeek`), a new area or instructor is checked against
        every date, and a new `recurrence` rewrites the cadence or end
        condition; days dropped from a weekly pattern are cancelled with their
        refund. A series bound to a recurring class follows the class and cannot
        be re-timed, and a booking an API key created cannot be made to recur at
        all (`RECURRENCE_NOT_AVAILABLE_TO_MANAGING_KEY`): 1club would be
        generating occurrences that key never created, so each one is its own
        booking. An edit whose series has already run touches nothing.
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: integer
          description: 1club booking id
        - in: query
          name: scope
          schema:
            type: string
            enum:
              - this_instance
              - all_future
            default: this_instance
          description: >-
            For an occurrence of a recurring booking, whether the edit applies
            to it alone or to every not-yet-started occurrence of the series
            (see the description)
        - in: header
          name: Idempotency-Key
          schema:
            type: string
            maxLength: 255
          description: >-
            Retry-safe key; a repeat of the same request replays the first
            response
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PlatformBookingUpdate'
      responses:
        '200':
          description: >-
            The booking after the edit - for a series edit, the occurrence you
            named
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformBooking'
        '400':
          description: >
            Invalid request, or an edit that cannot hold: `BOOKING_CANCELLED`,
            `BOOKING_ON_CLASS_NOT_RESCHEDULABLE`, `BOOKING_NEEDS_RESOURCE`,
            `BOOKING_COVERED_CANNOT_PRICE`, `CLASS_AT_CAPACITY`,
            `AREA_NOT_FOUND`, `CONTACT_NOT_FOUND`,
            `RECURRENCE_REQUIRES_SERIES_SCOPE` (a `recurrence` sent to an
            occurrence without `scope=all_future`),
            `RECURRENCE_NOT_AVAILABLE_TO_MANAGING_KEY`, or a taken slot, which
            carries `details.conflicts[]` as on create.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformError'
        '401':
          $ref: '#/components/responses/PlatformUnauthorized'
        '403':
          description: API key is missing the required `bookings:write` scope
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformError'
        '404':
          $ref: '#/components/responses/PlatformNotFound'
        '409':
          description: >
            The booking is managed by another API key that owns its own records
            (`BOOKING_EXTERNALLY_MANAGED`, with the managing integration's name
            in `details.managedBy`); or the new price is below what has already
            been paid on the booking (`BOOKING_CHARGE_OVERPAID`), which needs a
            refund rather than an edit; or a part-paid or invoiced charge cannot
            be rewritten (`BOOKING_CHARGE_NEEDS_ADJUSTMENT`); or an
            `Idempotency-Key` was reused with a different request body.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformError'
        '429':
          $ref: '#/components/responses/PlatformRateLimited'
      security:
        - customerApiAuth: []
components:
  schemas:
    PlatformBookingUpdate:
      type: object
      description: >-
        An edit to a booking. Every field is optional; send only what changes. A
        body with nothing but `notifyCustomer` is refused.
      properties:
        startTime:
          type: string
          format: date-time
          description: >-
            New start. With `scope=all_future`, every later occurrence takes
            this time of day on its own date; change the weekday with
            `recurrence.daysOfWeek`.
        endTime:
          type: string
          format: date-time
          description: New end. Must be after the start, stored or sent.
        areaId:
          type: integer
          description: >-
            Move the booking to this area (from GET /v1/platform/areas). Must be
            an area this API can sell, as on create.
        instructorId:
          type: integer
          nullable: true
          description: >-
            Attach this instructor to the session (from GET
            /v1/platform/instructors), or `null` to take the instructor off it.
            Must be free at the time.
        contactId:
          type: integer
          description: >-
            Reassign the booking to this contact (from GET
            /v1/platform/contacts). The outstanding charge, if any, moves with
            it.
        notes:
          type: string
          maxLength: 2000
        amount:
          type: number
          maximum: 1000000
          description: >-
            The booking's new price, before tax, in the club's currency - your
            own figure, kept as sent. Omit it to keep the price you recorded on
            a booking this API created, or to have a booking taken through 1club
            re-quoted by the club's pricing engine when the slot, area,
            instructor or contact changes. Cannot be set on a booking a
            membership covers.
        recurrence:
          type: object
          description: >-
            Make a one-off booking recur, or (with `scope=all_future`) rewrite
            the cadence or end condition of an existing series. The series
            starts at the booking's own start time, so there is no start date
            here. `daysOfWeek` is required for a weekly pattern, and a day
            repeated in it counts once. Not accepted on a booking an API key
            created.
          required:
            - frequency
            - interval
          properties:
            frequency:
              type: string
              enum:
                - daily
                - weekly
                - monthly
            interval:
              type: integer
              minimum: 1
              description: Every N days / weeks / months
            daysOfWeek:
              type: array
              items:
                type: string
                enum:
                  - sunday
                  - monday
                  - tuesday
                  - wednesday
                  - thursday
                  - friday
                  - saturday
              description: For a weekly pattern, the days it runs on
            endDate:
              type: string
              format: date-time
              description: 'Last date of the series, with `ends.type: until`'
            ends:
              type: object
              required:
                - type
              properties:
                type:
                  type: string
                  enum:
                    - until
                    - after
                    - never
                  description: >-
                    `until` runs to `endDate`, `after` runs for `occurrences`
                    sessions, `never` extends on a rolling window
                occurrences:
                  type: integer
                  minimum: 1
                  maximum: 520
                  description: >-
                    With `after`: how many sessions the series holds, counted
                    from its start
        notifyCustomer:
          type: boolean
          description: >-
            Tell the customer their booking changed - email with the updated
            calendar invite plus the in-app and WhatsApp notification. Only sent
            when the edit names a time, area, instructor or class. Off by
            default for an API key, on by default over an OAuth connection, as
            on create.
    PlatformBooking:
      type: object
      description: >-
        A booking created through the platform API. Recorded with a booking
        transaction so it counts for revenue, marked paid (settled against a
        payment method named after the caller's API key, so the club can
        reconcile what each partner collected) or unpaid (outstanding) per the
        caller. Collection stays with the caller; what it collected and what it
        gave back on cancellation are reported in `payment`.
      properties:
        bookingId:
          type: integer
          description: 1club booking id
        bookingUuid:
          type: string
          format: uuid
          description: >-
            Stable unguessable identifier. Prefer this over `bookingId` when
            storing a reference.
        status:
          type: string
          description: Booking status (e.g. confirmed, cancelled)
        areaId:
          type: integer
          nullable: true
          description: Area id
        classId:
          type: integer
          nullable: true
          description: >-
            The class occurrence this booking attends, when it is a class
            booking. Every attendee holds their own booking row against the same
            `classId`, and `classes` rows are per-occurrence - so this is what
            tells two classes running in the same hour apart. Join it against
            GET /v1/platform/classes, or read the roster with GET
            /v1/platform/classes/{id}/bookings.
        eventId:
          type: integer
          nullable: true
          description: The event this booking attends, when it is an event booking
        instructorId:
          type: integer
          nullable: true
          description: Instructor leading the session, when one is attached
        contactId:
          type: integer
          nullable: true
          description: Contact the booking is for
        startTime:
          type: string
          format: date-time
        endTime:
          type: string
          format: date-time
        customer:
          allOf:
            - $ref: '#/components/schemas/PlatformContact'
          nullable: true
          description: >-
            The booking's customer, identical to what GET
            /v1/platform/contacts/{id} returns. Present only when the request
            passes `include=customer`, which additionally requires the
            `contacts:read` scope; `null` when the booking has no contact. Use
            it to import a window of bookings without a contact lookup per row.
        payment:
          type: object
          properties:
            status:
              type: string
              enum:
                - paid
                - unpaid
                - no_charge
              description: >-
                `no_charge` means there is nothing to collect: either nothing
                was ever owed (a free area, an amount of 0) or an entitlement
                covers it - a membership or external program the attendee
                already holds, which is why a covered booking can carry a price
                and still owe nothing. `paid` counts every financially closed
                transaction status (`paid`, `settled`, `refunded`), and every
                charge type, not only the one this API records.
            amount:
              type: number
              nullable: true
              description: >-
                The booking's recorded price in the organization's currency;
                `status` is what says whether anything was collectable. Where
                the price is 0 but a real charge exists - an external program's
                per-visit fee lives entirely in its transaction - the ledger
                total is reported instead.
            paidAmount:
              type: number
              description: >-
                What has been collected on the booking, gross, before any
                refund. `0` when nothing has.
            refundedAmount:
              type: number
              description: >-
                What has been returned to the customer, across every refund
                recorded. `paidAmount - refundedAmount` is what the club kept.
            reference:
              type: string
              nullable: true
              description: >-
                The collecting partner's own id for the payment, when one
                reported it through this API (`payment.reference`); null for
                money 1club collected itself.
            fee:
              type: number
              nullable: true
              description: >-
                What the collecting partner kept out of the amount, when it
                reported one (`payment.fee`).
    PlatformError:
      type: object
      properties:
        error:
          type: string
    PlatformContact:
      type: object
      description: >-
        A contact (customer) in the organization. Reference the `id` as
        `contactId` when creating a booking.
      properties:
        id:
          type: integer
        uuid:
          type: string
          format: uuid
          description: >-
            Stable unguessable identifier. Prefer this over `id` when storing a
            reference.
        name:
          type: string
        firstName:
          type: string
        lastName:
          type: string
          nullable: true
        email:
          type: string
          nullable: true
        phone:
          type: string
          nullable: true
        type:
          type: string
          nullable: true
          description: >-
            Derived contact type (e.g. contact, member, lead). `archived` marks
            a retired contact - hidden from the list and from search, but still
            readable by id.
        createdAt:
          type: string
          format: date-time
  responses:
    PlatformUnauthorized:
      description: Invalid or missing API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/PlatformError'
    PlatformNotFound:
      description: The requested resource does not exist in this organization
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/PlatformError'
    PlatformRateLimited:
      description: Rate limit exceeded
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/PlatformError'
  securitySchemes:
    customerApiAuth:
      type: http
      scheme: bearer
      description: >-
        Organization-scoped bearer credential: a customer API key
        (1club_sk_live_...) or an MCP OAuth access token.

````