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

# List membership seats

> Returns the membership seats of the organizer associated with your key. A seat is one person's place on a membership policy: the primary member, or a secondary member on a plan that covers more than one person.

Send exactly one of these; a request with neither, or with both, is refused with `400`:

- `list=all` returns every seat, whatever its status, a page at a time.
- `emailAddress` returns the primary and secondary seats held under that address, matched case-insensitively.

**Listing every seat.** Send `list=all` with every page, set `page[size]` up to 500, and pass `page.next` as `page[after]` until it comes back empty. Seats come in seat id order, or by `sort[createdAt]` or `sort[updatedAt]` (`1` ascending, `-1` descending, one at a time). A page cursor only works under the sort it came from. Removed seats aren't listed.

**Only what changed.** `createdAt[after]`, `createdAt[before]`, `updatedAt[after]` and `updatedAt[before]` narrow the list. Bounds are exclusive, and a `createdAt` filter together with an `updatedAt` filter returns seats matching either.

**Keeping status current.** `updatedAt` moves when a seat's details, tier or plan, holder or place on the policy change. `status`, `entitled`, `expiresAt` and `renewalDate` are worked out when you ask and don't move it, so a membership that has since ended or frozen won't show up in an `updatedAt` filter: read the whole list again to refresh them. Use `entitled` to decide whether a member has access.

The date filters and sorts work only with `list=all`, and are refused with `emailAddress`. Any other query parameter is refused with `400`, so a misspelt one is never silently ignored.

> [!NOTE]
>
> This endpoint is in beta: its request and response contract can still change while it's being developed.


## OpenAPI

````yaml /openapi.json get /v0/membership-seats
openapi: 3.1.0
info:
  title: Let's Do This API
  version: 0.1.0
  description: >
    The full reference — getting started, pagination, error responses, rate
    limits and the changelog — lives at

    [partner-help.letsdothis.com/api-reference](https://partner-help.letsdothis.com/api-reference/overview).

    This page is the interactive OpenAPI view of the same specification.


    # Authentication


    Create an API key from **Settings** → **Credentials** in your Let's Do This
    account and send it as a bearer token:


    ```bash

    curl --request GET \
     --url "https://api.letsdothis.com/v0/participants" \
     --header "Authorization: Bearer YOUR-API-KEY"
    ```


    Keep the key secret: it identifies your organization, so do not ship it in a
    website or native app. If a key is exposed,

    revoke it from the same section and create a replacement.


    # OpenAPI schema


    Download the [OpenAPI schema](https://api.letsdothis.com/documentation/json)
    to use with Postman or an OpenAPI client

    generator.
servers:
  - url: https://api.letsdothis.com
    description: Production
  - url: https://api.staging.letsdothis.com
    description: Staging
security:
  - bearerAuth: []
tags:
  - name: Events
    x-group: Events
    description: Events that participants can register for.
  - name: EventOccurrences
    x-group: Event occurrences
    description: >-
      Event occurrences scoped to the organizer associated with your Public API
      credentials. Unlike the public Events catalog, results are limited to your
      own events.
  - name: Races
    x-group: Races
    description: >-
      Races within an event occurrence. An event occurrence may have one or more
      races, for example a 5K and a 10K within the same race day.
  - name: Tickets
    x-group: Tickets
    description: Tickets that are available for events.
  - name: BookingForms
    x-group: Booking forms
    description: >-
      Booking forms define the questions a booker answers when registering for a
      ticket. A ticket usually references a single booking form, so expect zero
      or one, while a booking form may be shared across multiple tickets.
  - name: BookingFormFields
    x-group: Booking form fields
    description: >-
      Booking form fields are the individual questions on a booking form — their
      type, label, options, and whether an answer is required. A field can be
      reused across multiple forms.
  - name: Bookings
    x-group: Bookings
    description: >-
      Bookings are the transaction record for a registration. A booking may
      contain one or more participants (entries).
  - name: Membership
    x-group: Memberships
    description: >-
      Membership schemes, purchased policies and the seats on them, owned by
      your organizer. Policies are billing contracts; a seat is one person's
      place on a policy.
  - name: Participant
    x-group: Participants
    description: Participants are users who successfully booked an event.
  - name: LineItem
    x-group: Line items
    description: Financial details related to individual items within transactions.
  - name: AddOns
    x-group: Add-ons
    description: >-
      Organizer-owned products that can be purchased and allocated to
      participants. Imported products retain stable external identities.
  - name: DiscountCodes
    x-group: Discount codes
    description: >-
      Discount codes participants enter at checkout to reduce the price of a
      booking.
  - name: Credits
    x-group: Credits
    description: >-
      Credits are balances participants can spend at checkout, identified by
      their email address.
  - name: Referrals
    x-group: Referrals
    description: >-
      Referral programs, the referrers registered on them, and asynchronous
      imports of historical referrals.
  - name: Teams
    x-group: Teams
    description: >-
      Teams group participants of an event occurrence under a team program.
      Teams can be imported for participants whose bookings were imported.
  - name: Application
    x-group: Applications
    description: >-
      Applications are created when a user applies for tickets that are set up
      to require an application process, such as balloted or "Good For Age"
      entries.
  - name: Partner
    x-group: Partners
    description: >-
      Partners that were created by the organization who can have Reserved
      Entries assigned to them.
  - name: ReservedEntries
    x-group: Reserved entries
    description: >-
      Reserved Entries are entries that are reserved for a partner. After being
      assigned, the partner can then allocate these entries to participants.
  - name: Timing
    x-group: Timing
    description: >-
      Timing providers push bib numbers and bib-pack shipments back to Let's Do
      This for the startlist entries they received. Available to select timing
      partners only.
  - name: Identity
    x-group: API key
    description: >-
      What your API key can reach. Available to every key, including scoped
      ones.
paths:
  /v0/membership-seats:
    get:
      tags:
        - Membership
      summary: List membership seats
      description: >-
        Returns the membership seats of the organizer associated with your key.
        A seat is one person's place on a membership policy: the primary member,
        or a secondary member on a plan that covers more than one person.


        Send exactly one of these; a request with neither, or with both, is
        refused with `400`:


        - `list=all` returns every seat, whatever its status, a page at a time.

        - `emailAddress` returns the primary and secondary seats held under that
        address, matched case-insensitively.


        **Listing every seat.** Send `list=all` with every page, set
        `page[size]` up to 500, and pass `page.next` as `page[after]` until it
        comes back empty. Seats come in seat id order, or by `sort[createdAt]`
        or `sort[updatedAt]` (`1` ascending, `-1` descending, one at a time). A
        page cursor only works under the sort it came from. Removed seats aren't
        listed.


        **Only what changed.** `createdAt[after]`, `createdAt[before]`,
        `updatedAt[after]` and `updatedAt[before]` narrow the list. Bounds are
        exclusive, and a `createdAt` filter together with an `updatedAt` filter
        returns seats matching either.


        **Keeping status current.** `updatedAt` moves when a seat's details,
        tier or plan, holder or place on the policy change. `status`,
        `entitled`, `expiresAt` and `renewalDate` are worked out when you ask
        and don't move it, so a membership that has since ended or frozen won't
        show up in an `updatedAt` filter: read the whole list again to refresh
        them. Use `entitled` to decide whether a member has access.


        The date filters and sorts work only with `list=all`, and are refused
        with `emailAddress`. Any other query parameter is refused with `400`, so
        a misspelt one is never silently ignored.
      parameters:
        - schema:
            type:
              - number
              - 'null'
            minimum: 1
            maximum: 500
            example: 100
          in: query
          name: page[size]
          required: false
          description: >-
            The number of entries to return per page. Range between 1 - 500,
            defaults to 100
        - schema:
            type:
              - string
              - 'null'
          in: query
          name: page[after]
          required: false
          description: >-
            Accepts an existing page cursor. For more details see the definition
            of PageCursor in the response.
        - schema:
            type:
              - string
              - 'null'
          in: query
          name: page[before]
          required: false
          description: >-
            Accepts an existing page cursor. For more details see the definition
            of PageCursor in the response.
        - schema:
            type:
              - string
              - 'null'
            enum:
              - '1'
              - '-1'
              - null
            example: '1'
          in: query
          name: sort[updatedAt]
          required: false
          description: Sort by update date. 1 for ascending, -1 for descending.
        - schema:
            type:
              - string
              - 'null'
            enum:
              - '1'
              - '-1'
              - null
            example: '1'
          in: query
          name: sort[createdAt]
          required: false
          description: Sort by creation date. 1 for ascending, -1 for descending.
        - schema:
            type:
              - string
              - 'null'
            format: date-time
            example: '2020-01-01T20:15:00.000Z'
          in: query
          name: createdAt[after]
          required: false
          description: Only return entries created after this date.
        - schema:
            type:
              - string
              - 'null'
            format: date-time
            example: '2020-01-01T20:15:00.000Z'
          in: query
          name: createdAt[before]
          required: false
          description: Only return entries created before this date.
        - schema:
            type:
              - string
              - 'null'
            format: date-time
            example: '2020-01-01T20:15:00.000Z'
          in: query
          name: updatedAt[after]
          required: false
          description: Only return entries updated after this date.
        - schema:
            type:
              - string
              - 'null'
            format: date-time
            example: '2020-01-01T20:15:00.000Z'
          in: query
          name: updatedAt[before]
          required: false
          description: Only return entries updated before this date.
        - schema:
            type: string
            format: email
            maxLength: 320
          in: query
          name: emailAddress
          required: false
          description: >-
            Find one member's seats by the address they are held under. Send
            this or `list`, not both.
        - schema:
            type: string
            enum:
              - all
          in: query
          name: list
          required: false
          description: >-
            Send `all` to list every seat, on every page. Send this or
            `emailAddress`, not both.
      responses:
        '200':
          description: Default Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PagedMembershipSeats'
        '400':
          description: Default Response
          content:
            application/json:
              schema:
                type: object
                required:
                  - code
                  - statusCode
                  - message
                properties:
                  code:
                    type: string
                    enum:
                      - MEMBERSHIP_RESOURCE_NOT_FOUND
                      - MEMBERSHIP_INVALID_REQUEST
                      - MEMBERSHIP_PORTAL_CONFIGURATION_REQUIRED
                      - MEMBERSHIP_BILLING_UNAVAILABLE
                      - MEMBERSHIP_FROZEN
                      - MEMBERSHIP_ALREADY_CANCELLED
                      - MEMBERSHIP_PRIMARY_MEMBER_ONLY
                      - MEMBERSHIP_OFFERING_CHANGE_REFUSED
                      - MEMBERSHIP_OFFERING_CHANGES_UNAVAILABLE
                      - MEMBERSHIP_IDEMPOTENCY_KEY_REUSED
                      - MEMBERSHIP_FEATURE_NOT_ENABLED
                      - MEMBERSHIP_WAITLIST_ENTRY_NOT_SELECTABLE
                      - MEMBERSHIP_WAITLIST_CHARGING_PAUSED
                    description: >-
                      Stable error identifier. RESOURCE_NOT_FOUND covers missing
                      and foreign resources alike. INVALID_REQUEST covers
                      malformed input or fields that cannot be edited.
                      PORTAL_CONFIGURATION_REQUIRED requires account setup;
                      BILLING_UNAVAILABLE means billing cannot be resolved or
                      reached. FROZEN and ALREADY_CANCELLED are reserved for
                      future lifecycle writes. PRIMARY_MEMBER_ONLY means only
                      the primary member of the policy can do this.
                      OFFERING_CHANGE_REFUSED means the scheme’s rules, the
                      household or a pending change or cancellation don’t allow
                      the offering change; reasons says which.
                      OFFERING_CHANGES_UNAVAILABLE means offering changes are
                      switched off for now; retry later. IDEMPOTENCY_KEY_REUSED
                      means the Idempotency-Key was already used for a different
                      request. FEATURE_NOT_ENABLED means the endpoint is
                      restricted and not enabled for your organisation.
                      WAITLIST_ENTRY_NOT_SELECTABLE means the waitlist entry was
                      withdrawn or refused. WAITLIST_CHARGING_PAUSED means
                      selection is paused; try again later.
                  statusCode:
                    type: integer
                  message:
                    type: string
                  reasons:
                    type: array
                    items:
                      type: string
                    description: >-
                      Only with OFFERING_CHANGE_REFUSED: each reason, such as
                      NOT_PRIMARY_MEMBER, RULE_FORBIDS, LEAD_TIME_TOO_SHORT,
                      SEATS_EXCEED_TARGET, PAYMENT_IN_PROGRESS,
                      SWITCH_IN_PROGRESS, CANCELLATION_PENDING,
                      TARGET_UNAVAILABLE or OTHER_SCHEME. More may be added.
components:
  schemas:
    PagedMembershipSeats:
      title: PagedMembershipSeats
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/MembershipSeat'
        page:
          $ref: '#/components/schemas/PageCursor'
      required:
        - data
        - page
      additionalProperties: false
    MembershipSeat:
      title: MembershipSeat
      type: object
      properties:
        id:
          type: string
        policyId:
          type: string
          description: >-
            The policy the seat is on, shared by every seat on a plan that
            covers more than one person.
        offeringId:
          type: string
          description: The offering the seat is on.
        memberType:
          type: string
          enum:
            - PRIMARY
            - SECONDARY
          description: >-
            `PRIMARY` for the member who holds the policy, `SECONDARY` for the
            others on it.
        planType:
          type: string
        tier:
          anyOf:
            - type: object
              properties:
                id:
                  type: string
                title:
                  type: string
              required:
                - id
                - title
              additionalProperties: false
            - type: 'null'
          description: The offering's tier; null when it has none.
        plan:
          anyOf:
            - type: object
              properties:
                id:
                  type: string
                title:
                  type: string
              required:
                - id
                - title
              additionalProperties: false
            - type: 'null'
          description: The offering's plan; null when it has none.
        status:
          type: string
          enum:
            - ACTIVE
            - CANCELLED_RUNNING
            - FROZEN
            - ENDED
          description: >-
            As on the policy's status. `ACTIVE` grants access,
            `CANCELLED_RUNNING` keeps access until the paid period ends,
            `FROZEN` is paused while a renewal payment is pending or retried,
            and `ENDED` has ended. Use `entitled` for access decisions.
        entitled:
          type: boolean
          description: Whether the member has access now, as on the policy's status.
        emailAddress:
          type: string
          description: The address the seat is held under.
        firstName:
          type:
            - string
            - 'null'
        lastName:
          type:
            - string
            - 'null'
        createdAt:
          type: string
          description: >-
            When the seat was created: when its member joined, with exceptions.
            A member added by a bulk import has the import's date. A seat
            transferred to someone else keeps its date, and a member who lets a
            membership end and buys again gets a new seat with a new date.
        updatedAt:
          type: string
          description: >-
            When the seat record last changed: its member's details, tier or
            plan, holder or place on the policy. Status, entitlement, expiresAt
            and renewalDate are worked out when you ask and don't move it.
        expiresAt:
          type:
            - string
            - 'null'
          description: 'As on the policy''s status: when the paid period ends.'
        renewalDate:
          type:
            - string
            - 'null'
          description: 'As on the policy''s status: when the next renewal is due.'
      required:
        - id
        - policyId
        - offeringId
        - memberType
        - planType
        - tier
        - plan
        - status
        - entitled
        - emailAddress
        - firstName
        - lastName
        - createdAt
        - updatedAt
        - expiresAt
        - renewalDate
      additionalProperties: false
      description: >-
        One person's place on a policy: the primary member or a secondary
        member.
    PageCursor:
      title: PageCursor
      type: object
      properties:
        totalResults:
          type: number
          description: The total number of results available.
        first:
          type: string
          description: The cursor for the first page of results.
        last:
          type: string
          description: The cursor for the last page of results.
        prev:
          type: string
          description: The cursor for the previous page of results.
        next:
          type: string
          description: The cursor for the next page of results.
      required:
        - totalResults
        - first
        - last
        - prev
        - next
      additionalProperties: false
      description: >-
        **Cursor details for pagination**.

        - In scenarios with large amounts of data, it's common to return only a
        subset of data in a single request, known as a "page".

        - Most API responses include two objects: a 'data' object with the query
        results, and a 'PageCursor' object detailing the current page.

        - Cursors can be used to navigate to earlier or later pages in the set
        of results. For instance, passing the 'next' cursor from 'PageCursor'
        fetches the next set of results.

        - Cursors are base64 encoded strings.
      example:
        totalResults: 506
        first: >-
          eyJpZCI6IjYzOTljMjAwMTVkNjBhZTNmZjI4ZjI0YyIsInVwZGF0ZWRBdCI6IjIwMjItMTItMTRUMTI6MzA6NTkuMjE3WiJ9
        last: >-
          eyJpZCI6IjY1NGNkZDIxZDlhMTU3ODdiNzFkMTM0YSIsInVwZGF0ZWRBdCI6IjIwMjMtMTEtMTNUMTU6MTE6MTIuNzI0WiJ9
        prev: ''
        next: >-
          eyJpZCI6IjY0NzBkNTkwM2RjOWE5OWJhMTA0Y2ZhYiIsInVwZGF0ZWRBdCI6IjIwMjMtMTEtMTNUMTU6MTE6MTIuNjE4WiJ9
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

````

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