> ## 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.

# Import reserved entry participants

> Asynchronously assigns already-imported entries to reserved entry groups. Each row names its group and exactly one of `bookingId`, `entryId` or `participantId`; a `bookingId` row is expanded to every participant on that booking, so results are reported per participant and can outnumber the rows submitted.

The whole batch is resolved synchronously and either every row resolves (202 with a job to poll) or nothing is imported (422 with every problem).

Assignments are create-once and scoped to `(reservedEntryGroupId, participantId)`: re-importing a participant already holding a place in that group reports `alreadyImported` and consumes no place, and a participant already placed in a *different* group is reported as `ALREADY_ASSIGNED_ELSEWHERE` rather than moved.

Send an `Idempotency-Key` header to make the submission replayable: retrying the same key and body returns the original job; reusing a key with a different body is rejected (409).

<Warning>This endpoint is restricted and not generally available: organizations that have not been enabled receive a `403`. Contact your Let's Do This representative if you'd like access.</Warning>


## OpenAPI

````yaml /openapi.json post /v0/reserved-entries/participants/import
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: 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: 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.
paths:
  /v0/reserved-entries/participants/import:
    post:
      tags:
        - ReservedEntries
      summary: Import reserved entry participants
      description: >-
        Asynchronously assigns already-imported entries to reserved entry
        groups. Each row names its group and exactly one of `bookingId`,
        `entryId` or `participantId`; a `bookingId` row is expanded to every
        participant on that booking, so results are reported per participant and
        can outnumber the rows submitted.


        The whole batch is resolved synchronously and either every row resolves
        (202 with a job to poll) or nothing is imported (422 with every
        problem).


        Assignments are create-once and scoped to `(reservedEntryGroupId,
        participantId)`: re-importing a participant already holding a place in
        that group reports `alreadyImported` and consumes no place, and a
        participant already placed in a *different* group is reported as
        `ALREADY_ASSIGNED_ELSEWHERE` rather than moved.


        Send an `Idempotency-Key` header to make the submission replayable:
        retrying the same key and body returns the original job; reusing a key
        with a different body is rejected (409).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ReservedEntryParticipantImportRequest'
      responses:
        '202':
          description: Default Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReservedEntryParticipantImportAccepted'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                description: Bad request
                type: object
                properties:
                  statusCode:
                    type: number
                    enum:
                      - 400
                  error:
                    type: string
                  message:
                    type: string
        '409':
          description: Conflict
          content:
            application/json:
              schema:
                description: Conflict
                type: object
                properties:
                  statusCode:
                    type: number
                    enum:
                      - 409
                  error:
                    type: string
                  message:
                    type: string
        '413':
          description: Payload too large
          content:
            application/json:
              schema:
                description: Payload too large
                type: object
                properties:
                  statusCode:
                    type: number
                    enum:
                      - 413
                  error:
                    type: string
                  message:
                    type: string
        '422':
          description: Default Response
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/ReservedEntryParticipantImportValidationFailure
        '429':
          description: Rate limit exceeded
          headers:
            retry-after:
              schema:
                type: integer
              description: Seconds to wait before retrying the request.
            x-ratelimit-limit:
              schema:
                type: integer
              description: Requests permitted in the current window.
            x-ratelimit-remaining:
              schema:
                type: integer
              description: Requests still permitted in the current window.
            x-ratelimit-reset:
              schema:
                type: integer
              description: Seconds until the current window resets.
          content:
            application/json:
              schema:
                description: Rate limit exceeded
                type: object
                properties:
                  statusCode:
                    type: number
                    enum:
                      - 429
                  error:
                    type: string
                  message:
                    type: string
components:
  schemas:
    ReservedEntryParticipantImportRequest:
      title: ReservedEntryParticipantImportRequest
      type: object
      properties:
        assignments:
          type: array
          items:
            $ref: '#/components/schemas/ReservedEntryParticipantImportRow'
          description: >-
            The assignments to make. A row naming a `bookingId` expands to one
            assignment per participant on that booking, so a batch may produce
            more assignments than it has rows.
          minItems: 1
          maxItems: 1000
        expandCapacity:
          type: boolean
          description: >-
            Whether to raise a group's `maxCapacity` to fit the batch rather
            than rejecting it. Off by default. When several groups are short,
            each is raised by its own shortfall. A group's capacity is the
            number of places in it, so raising it creates the additional places.


            Every raise is reported in `capacityChanges` on the job status, so
            the resulting block sizes can be audited from the API.
      required:
        - assignments
      additionalProperties: false
      description: >-
        An asynchronous request to assign already-imported entries to reserved
        entry groups: the whole batch validates or none of it is queued.
    ReservedEntryParticipantImportAccepted:
      title: ReservedEntryParticipantImportAccepted
      type: object
      properties:
        jobId:
          type: string
          description: The id of the queued import job.
        status:
          type: string
          enum:
            - queued
      required:
        - jobId
        - status
      additionalProperties: false
      description: The accepted import job. Poll the job endpoint for progress and results.
      example:
        jobId: 664a4b5c6d7e8f901a2b3c4d
        status: queued
    ReservedEntryParticipantImportValidationFailure:
      title: ReservedEntryParticipantImportValidationFailure
      type: object
      properties:
        error:
          type: string
          enum:
            - validation_failed
        message:
          type: string
          description: A human summary of the failure.
        totalRows:
          type: number
          description: How many rows the batch contained.
        rowsWithErrors:
          type: number
          description: How many rows had at least one error.
        errorCount:
          type: number
          description: How many errors were found in total.
        summary:
          type: array
          items:
            $ref: '#/components/schemas/ReservedEntryParticipantImportErrorSummary'
        errors:
          type: array
          items:
            $ref: '#/components/schemas/ReservedEntryParticipantImportRowErrors'
        truncated:
          type: boolean
          description: Whether `errors` was capped. `summary` is never capped.
      required:
        - error
        - message
        - totalRows
        - rowsWithErrors
        - errorCount
        - summary
        - errors
        - truncated
      additionalProperties: false
      description: >-
        The whole-batch validation failure: nothing was queued. `summary` is the
        load-bearing part — every error class, uncapped, ordered by frequency.
        `errors` carries capped per-row detail; `truncated` refers to `errors`
        only, never `summary`. Counts are of submitted rows, not of the
        assignments they expand to, matching the `rowIndex` used by every
        locator.
    ReservedEntryParticipantImportRow:
      title: ReservedEntryParticipantImportRow
      type: object
      properties:
        reservedEntryGroupId:
          type: string
          description: The reserved entry group to assign into.
        bookingId:
          type: string
          description: >-
            Assign **every** participant on this booking. The cheapest form: it
            needs no participant lookup, and one row expands to one assignment
            per participant.
        entryId:
          type: string
          description: >-
            Assign a single start list entry — the `id` of a participant from
            `GET /v0/bookings/{id}/participants`.
        participantId:
          type: string
          description: >-
            Assign a single participant — the `participantId` of a participant
            from `GET /v0/bookings/{id}/participants`. This is the id the
            reserved entry is linked by, so it is the durable one to store.
        reservationCode:
          type: string
          description: >-
            Consume a specific reservation in the group rather than any free
            one. Rarely needed; omit to take the next available place.
      required:
        - reservedEntryGroupId
      additionalProperties: false
      description: >-
        One assignment of an already-imported entry to a reserved entry group.


        Supply exactly one of `bookingId`, `entryId` or `participantId`. They
        are declared optional here because the batch validator reports a row
        that names none or several as a located `422`, alongside every other
        problem in the batch — a schema-level constraint would collapse that
        into an unlocated `400` naming only the first bad row.
    ReservedEntryParticipantImportErrorSummary:
      title: ReservedEntryParticipantImportErrorSummary
      type: object
      properties:
        code:
          type: string
        count:
          type: number
          description: How many times this class occurred across the batch.
          minimum: 0
          multipleOf: 1
        message:
          type: string
          description: A representative message for the class.
        examples:
          type: array
          items:
            $ref: '#/components/schemas/ReservedEntryParticipantImportErrorLocator'
          description: The first few occurrences, located.
      required:
        - code
        - count
        - message
        - examples
      additionalProperties: false
      description: One validation problem class, aggregated across the batch.
    ReservedEntryParticipantImportRowErrors:
      title: ReservedEntryParticipantImportRowErrors
      type: object
      properties:
        rowIndex:
          type: number
          description: The zero-based position of the row in `assignments`.
        reservedEntryGroupId:
          type: string
          description: The reserved entry group the row named.
        errors:
          type: array
          items:
            $ref: '#/components/schemas/ReservedEntryParticipantImportErrorDetail'
      required:
        - rowIndex
        - errors
      additionalProperties: false
      description: The per-row detail of a failed validation, grouped by row.
    ReservedEntryParticipantImportErrorLocator:
      title: ReservedEntryParticipantImportErrorLocator
      type: object
      properties:
        rowIndex:
          type: number
          description: The zero-based position of the offending row in `assignments`.
        reservedEntryGroupId:
          type: string
          description: The reserved entry group the offending row named.
        bookingId:
          type: string
          description: Whichever of the three ids the offending row supplied.
        entryId:
          type: string
        participantId:
          type: string
        value:
          type: string
          description: The offending submitted value, when one exists.
      required:
        - rowIndex
      additionalProperties: false
      description: Where in the batch a validation error occurred.
    ReservedEntryParticipantImportErrorDetail:
      title: ReservedEntryParticipantImportErrorDetail
      type: object
      properties:
        code:
          type: string
        message:
          type: string
      required:
        - code
        - message
      additionalProperties: false
      description: >-
        One occurrence of a validation error.


        `code` names the cause so it can be acted on without reading the
        message. `INVALID_ASSIGNMENT` means the assignment itself was not
        usable, so resubmitting it unchanged cannot succeed, and `INTERNAL`
        means the cause could not be named. The others describe the state that
        blocked the assignment, which may no longer hold:
        `NO_CAPACITY_REMAINING` clears when a place frees or the group is
        raised, so whether a retry can help depends on the code.


        `BOOKING_SPANS_SEVERAL_GROUPS` means one booking's participants were
        assigned to different reserved entry groups. A booking records one
        group, so resubmitting it unchanged cannot succeed: split those
        participants across separate bookings, or send them to one group.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

````