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

> Asynchronously creates teams and puts already-imported participants in them. Import the bookings first, then send each team with its members' participant ids. Each team is created as a team created at checkout would be, and each member is put in it as an organizer edit from the dashboard would: a participant already in another team is moved, team size limits are not applied, and no emails are sent.

The whole batch is validated synchronously — either every team is accepted (202 with a job to poll) or nothing is (422 with every problem, aggregated by error class). Execution is per-team from there: one team failing never rejects the others.

Imports are create-once per `externalTeamId` within an event occurrence: re-importing the same id with the same details reuses the team and adds any missing members. The same id with a different program, name, privacy or non-participating captain fails that team.

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). A 409 can also mean another request with the same key is still being accepted; retry it shortly to get its job.

> [!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.


## OpenAPI

````yaml /openapi.json post /v0/teams/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: 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/teams/import:
    post:
      tags:
        - Teams
      summary: Import teams
      description: >-
        Asynchronously creates teams and puts already-imported participants in
        them. Import the bookings first, then send each team with its members'
        participant ids. Each team is created as a team created at checkout
        would be, and each member is put in it as an organizer edit from the
        dashboard would: a participant already in another team is moved, team
        size limits are not applied, and no emails are sent.


        The whole batch is validated synchronously — either every team is
        accepted (202 with a job to poll) or nothing is (422 with every problem,
        aggregated by error class). Execution is per-team from there: one team
        failing never rejects the others.


        Imports are create-once per `externalTeamId` within an event occurrence:
        re-importing the same id with the same details reuses the team and adds
        any missing members. The same id with a different program, name, privacy
        or non-participating captain fails that team.


        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). A 409 can also mean another
        request with the same key is still being accepted; retry it shortly to
        get its job.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TeamImportRequest'
      responses:
        '202':
          description: Default Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TeamImportAccepted'
        '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/TeamImportValidationFailure'
        '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:
    TeamImportRequest:
      title: TeamImportRequest
      type: object
      properties:
        teams:
          type: array
          items:
            $ref: '#/components/schemas/TeamImportRow'
          description: The teams to import.
          minItems: 1
          maxItems: 500
      required:
        - teams
      additionalProperties: false
      description: >-
        An asynchronous team import request: the whole batch is accepted or none
        of it. At most 2,000 members across the batch.
    TeamImportAccepted:
      title: TeamImportAccepted
      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: 6628293a4b5c6d7e8f901a2b
        status: queued
    TeamImportValidationFailure:
      title: TeamImportValidationFailure
      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/TeamImportErrorSummary'
        errors:
          type: array
          items:
            $ref: '#/components/schemas/TeamImportRowErrors'
        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 imported. `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`.
    TeamImportRow:
      title: TeamImportRow
      type: object
      properties:
        externalTeamId:
          type: string
          description: >-
            Your stable id for this team, unique per event occurrence. Imports
            are create-once per `externalTeamId`: re-importing the same id with
            the same details reuses the team, reported as `alreadyImported` when
            nothing changed. The same id with a different program, name, privacy
            or non-participating captain fails the row.
          minLength: 1
          maxLength: 255
        teamProgramId:
          type: string
          description: >-
            The team program the team belongs to: the one every member's ticket
            is assigned to.
        teamName:
          type: string
          minLength: 1
          maxLength: 255
        isPrivate:
          type: boolean
          description: >-
            Private teams can only be joined with their invite code. Defaults to
            `false`.
        memberParticipantIds:
          type: array
          items:
            type: string
          description: >-
            The participants to put in the team, as Let's Do This participant
            ids. Import the bookings first, then read their participants. A
            participant already in another team is moved, as an organizer edit
            from the dashboard would. Team size limits are not applied, also as
            for an organizer edit.
          minItems: 1
          maxItems: 100
        captainParticipantId:
          type: string
          description: >-
            The member to make captain. Omit it and the first member to join
            becomes captain, as for a team created at checkout.
        nonParticipatingCaptain:
          $ref: '#/components/schemas/TeamImportNonParticipatingCaptain'
      required:
        - externalTeamId
        - teamProgramId
        - teamName
        - memberParticipantIds
      additionalProperties: false
      description: One team to create, with the participants to put in it.
    TeamImportErrorSummary:
      title: TeamImportErrorSummary
      type: object
      properties:
        code:
          type: string
        fieldId:
          type: string
          description: The row field the class relates to, when field-scoped.
        count:
          type: number
          description: How many times this class occurred across the batch.
        message:
          type: string
          description: A representative message for the class.
        examples:
          type: array
          items:
            $ref: '#/components/schemas/TeamImportErrorLocator'
          description: The first few occurrences, located.
      required:
        - code
        - count
        - message
        - examples
      additionalProperties: false
      description: One validation problem class, aggregated across the batch.
    TeamImportRowErrors:
      title: TeamImportRowErrors
      type: object
      properties:
        externalTeamId:
          type: string
          description: The `externalTeamId` of the row.
        rowIndex:
          type: number
          description: The zero-based position of the row in `teams`.
        errors:
          type: array
          items:
            $ref: '#/components/schemas/TeamImportErrorDetail'
      required:
        - rowIndex
        - errors
      additionalProperties: false
      description: The per-row detail of a failed validation, grouped by row.
    TeamImportNonParticipatingCaptain:
      title: TeamImportNonParticipatingCaptain
      type: object
      properties:
        fullName:
          type: string
          minLength: 1
          maxLength: 255
        emailAddress:
          type: string
          minLength: 3
          maxLength: 320
      required:
        - fullName
        - emailAddress
      additionalProperties: false
      description: A team captain who is not taking part in the event.
    TeamImportErrorLocator:
      title: TeamImportErrorLocator
      type: object
      properties:
        externalTeamId:
          type: string
          description: The `externalTeamId` of the offending row.
        rowIndex:
          type: number
          description: The zero-based position of the offending row in `teams`.
        value:
          type: string
          description: The offending submitted value, when one exists.
      required:
        - rowIndex
      additionalProperties: false
      description: Where in the batch a validation error occurred.
    TeamImportErrorDetail:
      title: TeamImportErrorDetail
      type: object
      properties:
        code:
          type: string
        fieldId:
          type: string
        message:
          type: string
      required:
        - code
        - message
      additionalProperties: false
      description: One occurrence of a validation error.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

````

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