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

# Upsert courses

> Create or update multiple courses in the LMS.

<Accordion title="Supported integrations" icon="list-check">
  This feature is currently available for the following integrations:

  <ul>
    <li class="flex items-center"><img src="https://storage.googleapis.com/kombo-assets/integrations/successfactors/icon.svg" height="16px" width="16px" class="m-0 mr-2" /><a href="/lms/connectors/successfactors">SAP SuccessFactors</a></li>
    <li class="flex items-center"><img src="https://storage.googleapis.com/kombo-assets/integrations/cornerstoneondemand/icon.svg" height="16px" width="16px" class="m-0 mr-2" /><a href="/lms/connectors/cornerstoneondemand">Cornerstone OnDemand</a></li>
    <li class="flex items-center"><img src="https://storage.googleapis.com/kombo-assets/integrations/workday/icon.svg" height="16px" width="16px" class="m-0 mr-2" /><a href="/lms/connectors/workday">Workday</a></li>
    <li class="flex items-center"><img src="https://storage.googleapis.com/kombo-assets/integrations/sandbox/icon.svg" height="16px" width="16px" class="m-0 mr-2" /><a href="/lms/connectors/sandbox">Kombo Sandbox</a></li>
    <li class="flex items-center"><img src="https://storage.googleapis.com/kombo-assets/integrations/360learning/icon.svg" height="16px" width="16px" class="m-0 mr-2" /><a href="/lms/connectors/360learning">360Learning</a></li>
    <li class="flex items-center"><img src="https://storage.googleapis.com/kombo-assets/integrations/talentlms/icon.svg" height="16px" width="16px" class="m-0 mr-2" /><a href="/lms/connectors/talentlms">TalentLMS</a></li>
    <li class="flex items-center"><img src="https://storage.googleapis.com/kombo-assets/integrations/moodle/icon.svg" height="16px" width="16px" class="m-0 mr-2" /><a href="/lms/connectors/moodle">Moodle</a></li>
  </ul>

  You'd like to see this feature for another integration? Please reach out!
  We're always happy to discuss extending our coverage.
</Accordion>

<Info>
  **Note:** This endpoint is asynchronous – it returns a `task_id` immediately and processes the request in the background. Use the corresponding `GET` endpoint to poll for the task status until it reaches `COMPLETED` or `FAILED`. Learn more in our [async endpoints guide](/lms/guides/async-endpoints).
</Info>

<Note>
  This endpoint requires the permission **Upsert courses** to be enabled in [your scope config](/scopes).
</Note>

### Example Request Body

```json theme={null}
{
  "items": [
    {
      "origin_id": "course-1",
      "course": {
        "type": "EXTERNAL",
        "title": "Building LMS integrations with Kombo",
        "description": "Learn how to build and integrate Learning Management System (LMS) integrations with Kombo. This course covers the unified LMS API, course management, user enrollment, progress tracking, and best practices for building robust LMS connectors.",
        "course_url": "https://docs.kombo.dev/lms/introduction",
        "thumbnail_url": "https://kombo.dev/images/courses/lms-integrations-thumbnail.png",
        "duration": 45,
        "languages": [
          "en",
          "de-CH"
        ]
      }
    },
    {
      "origin_id": "course-2",
      "course": {
        "type": "EXTERNAL",
        "title": "Introduction to TypeScript",
        "description": "Learn one of the most popular programming languages of the recent years quickly and efficiently. Results guaranteed!",
        "course_url": "https://example.com",
        "thumbnail_url": "https://example.com/images/thumbnail.jpg",
        "duration": 60,
        "languages": [
          "en-US",
          "pl-PL"
        ]
      }
    }
  ]
}
```


## OpenAPI

````yaml POST /lms/courses/bulk
openapi: 3.1.0
info:
  title: Kombo API
  version: 1.0.0
servers:
  - url: https://api.kombo.dev/v1
    description: Kombo EU API
  - url: https://api.us.kombo.dev/v1
    description: Kombo US API
security:
  - ApiKey: []
tags:
  - name: General
  - name: Kombo Connect
    description: >-
      Endpoints for Kombo Connect, our end-user-facing flow for setting up new
      integrations.
  - name: Unified HRIS API
    description: Unified endpoints to access all the HR concepts you might need.
  - name: Unified ATS API
    description: Unified endpoints to access all the ATS concepts you might need.
  - name: Unified ATS (Assessment & Background Check) API
    description: >-
      Unified endpoints to operate Assessments and Background Checks for many
      applicant tracking systems.
  - name: Unified LMS API
    description: Unified endpoints to access all the LMS concepts you might need.
  - name: AI Apply
    description: Endpoints for AI-powered job application features.
  - name: Custom Endpoints
    description: Custom integration-specific endpoints.
paths:
  /lms/courses/bulk:
    post:
      tags:
        - Unified LMS API
      summary: Upsert courses
      description: >-
        Create or update multiple courses in the LMS.


        <Accordion title="Supported integrations" icon="list-check">

        This feature is currently available for the following integrations:


        <ul>

        <li class="flex items-center"><img
          src="https://storage.googleapis.com/kombo-assets/integrations/successfactors/icon.svg"
          height="16px"
          width="16px"
          class="m-0 mr-2"
        /><a href="/lms/connectors/successfactors">SAP SuccessFactors</a></li>

        <li class="flex items-center"><img
          src="https://storage.googleapis.com/kombo-assets/integrations/cornerstoneondemand/icon.svg"
          height="16px"
          width="16px"
          class="m-0 mr-2"
        /><a href="/lms/connectors/cornerstoneondemand">Cornerstone
        OnDemand</a></li>

        <li class="flex items-center"><img
          src="https://storage.googleapis.com/kombo-assets/integrations/workday/icon.svg"
          height="16px"
          width="16px"
          class="m-0 mr-2"
        /><a href="/lms/connectors/workday">Workday</a></li>

        <li class="flex items-center"><img
          src="https://storage.googleapis.com/kombo-assets/integrations/sandbox/icon.svg"
          height="16px"
          width="16px"
          class="m-0 mr-2"
        /><a href="/lms/connectors/sandbox">Kombo Sandbox</a></li>

        <li class="flex items-center"><img
          src="https://storage.googleapis.com/kombo-assets/integrations/360learning/icon.svg"
          height="16px"
          width="16px"
          class="m-0 mr-2"
        /><a href="/lms/connectors/360learning">360Learning</a></li>

        <li class="flex items-center"><img
          src="https://storage.googleapis.com/kombo-assets/integrations/talentlms/icon.svg"
          height="16px"
          width="16px"
          class="m-0 mr-2"
        /><a href="/lms/connectors/talentlms">TalentLMS</a></li>

        <li class="flex items-center"><img
          src="https://storage.googleapis.com/kombo-assets/integrations/moodle/icon.svg"
          height="16px"
          width="16px"
          class="m-0 mr-2"
        /><a href="/lms/connectors/moodle">Moodle</a></li>

        </ul>


        You'd like to see this feature for another integration? Please reach
        out!

        We're always happy to discuss extending our coverage.

        </Accordion>



        <Info>
          **Note:** This endpoint is asynchronous – it returns a `task_id` immediately and processes the request in the background. Use the corresponding `GET` endpoint to poll for the task status until it reaches `COMPLETED` or `FAILED`. Learn more in our [async endpoints guide](/lms/guides/async-endpoints).
        </Info>


        <Note>
          This endpoint requires the permission **Upsert courses** to be enabled in [your scope config](/scopes).
        </Note>


        ### Example Request Body


        ```json

        {
          "items": [
            {
              "origin_id": "course-1",
              "course": {
                "type": "EXTERNAL",
                "title": "Building LMS integrations with Kombo",
                "description": "Learn how to build and integrate Learning Management System (LMS) integrations with Kombo. This course covers the unified LMS API, course management, user enrollment, progress tracking, and best practices for building robust LMS connectors.",
                "course_url": "https://docs.kombo.dev/lms/introduction",
                "thumbnail_url": "https://kombo.dev/images/courses/lms-integrations-thumbnail.png",
                "duration": 45,
                "languages": [
                  "en",
                  "de-CH"
                ]
              }
            },
            {
              "origin_id": "course-2",
              "course": {
                "type": "EXTERNAL",
                "title": "Introduction to TypeScript",
                "description": "Learn one of the most popular programming languages of the recent years quickly and efficiently. Results guaranteed!",
                "course_url": "https://example.com",
                "thumbnail_url": "https://example.com/images/thumbnail.jpg",
                "duration": 60,
                "languages": [
                  "en-US",
                  "pl-PL"
                ]
              }
            }
          ]
        }

        ```
      operationId: PostLmsCoursesBulk
      parameters:
        - in: header
          name: X-Integration-Id
          schema:
            type: string
          description: ID of the integration you want to interact with.
          example: bombohr:HWUTwvyx2wLoSUHphiWVrp28
          required: true
      requestBody:
        description: POST /lms/courses/bulk Request body
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PostLmsCoursesBulkRequestBody'
            examples:
              example1:
                value:
                  items:
                    - origin_id: course-1
                      course:
                        type: EXTERNAL
                        title: Building LMS integrations with Kombo
                        description: >-
                          Learn how to build and integrate Learning Management
                          System (LMS) integrations with Kombo. This course
                          covers the unified LMS API, course management, user
                          enrollment, progress tracking, and best practices for
                          building robust LMS connectors.
                        course_url: https://docs.kombo.dev/lms/introduction
                        thumbnail_url: >-
                          https://kombo.dev/images/courses/lms-integrations-thumbnail.png
                        duration: 45
                        languages:
                          - en
                          - de-CH
                    - origin_id: course-2
                      course:
                        type: EXTERNAL
                        title: Introduction to TypeScript
                        description: >-
                          Learn one of the most popular programming languages of
                          the recent years quickly and efficiently. Results
                          guaranteed!
                        course_url: https://example.com
                        thumbnail_url: https://example.com/images/thumbnail.jpg
                        duration: 60
                        languages:
                          - en-US
                          - pl-PL
      responses:
        '200':
          description: POST /lms/courses/bulk Positive response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PostLmsCoursesBulkPositiveResponse'
        default:
          $ref: '#/components/responses/ErrorResponseGeneral'
components:
  schemas:
    PostLmsCoursesBulkRequestBody:
      type: object
      properties:
        items:
          type: array
          items:
            type: object
            properties:
              origin_id:
                type: string
                description: >-
                  A unique identifier for this item in the batch, used to
                  correlate results and as a stable identifier for matching
                  existing courses.
              course:
                discriminator:
                  propertyName: type
                oneOf:
                  - type: object
                    properties:
                      type:
                        type: string
                        const: EXTERNAL
                        description: >-
                          `EXTERNAL` indicates that the content is not sent to
                          the LMS, but the `course_url` links to the content in
                          your system.
                      title:
                        type: string
                        description: The title of the course revision.
                      description:
                        type:
                          - string
                          - 'null'
                        description: A description of the course revision.
                      course_url:
                        type: string
                        description: >-
                          URL to the course page. For content providers, this
                          should be a deeplink into your product that allows
                          users to access the course directly.
                      thumbnail_url:
                        type:
                          - string
                          - 'null'
                        description: URL to the thumbnail image for the course.
                      duration:
                        type:
                          - integer
                          - 'null'
                        format: int64
                        exclusiveMinimum: 0
                        description: The duration of the course in minutes.
                      languages:
                        type:
                          - array
                          - 'null'
                        items:
                          type: string
                          pattern: ^[a-z]{2,3}(-[A-Z]{2})?$
                          description: >-
                            IETF language tag (BCP 47) in the format "ll-CC"
                            (e.g., "en-US", "de-DE") or "ll" (e.g., "en", "de").
                        description: >-
                          A array containing the supported languages for the
                          course content. If only one language is accepted by
                          remote tool we default to the first one. 
                    required:
                      - type
                      - title
                      - course_url
            required:
              - origin_id
              - course
          description: Array of courses to create or update.
      required:
        - items
    PostLmsCoursesBulkPositiveResponse:
      type: object
      properties:
        status:
          type: string
          const: success
        data:
          type: object
          properties:
            task_id:
              type: string
              description: >-
                The ID of the created task. Poll this to get the status and
                results.
          required:
            - task_id
        warnings:
          type: array
          items:
            type: object
            properties:
              message:
                type: string
            required:
              - message
          description: >-
            These are the interaction warnings that are shown in the dashboard.
            They are meant to provide debug information to you. We recommend
            logging them to the console.
      required:
        - status
        - data
        - warnings
  responses:
    ErrorResponseGeneral:
      description: The standard error response with just the platform error codes.
      content:
        application/json:
          schema:
            type: object
            properties:
              status:
                type: string
                enum:
                  - error
              error:
                type: object
                properties:
                  code:
                    type:
                      - string
                      - 'null'
                    enum:
                      - PLATFORM.RATE_LIMIT_EXCEEDED
                      - PLATFORM.CONCURRENCY_LIMIT_EXCEEDED
                      - PLATFORM.INTEGRATION_NOT_FOUND
                      - PLATFORM.INPUT_INVALID
                      - PLATFORM.UNKNOWN_ERROR
                      - PLATFORM.IP_NOT_WHITELISTED
                      - PLATFORM.AUTHENTICATION_INVALID
                      - PLATFORM.TASK_TIMED_OUT
                    example: PLATFORM.RATE_LIMIT_EXCEEDED
                    description: >-
                      Some errors include an error code that can be used to
                      identify their cause. See the [Error Handling
                      Docs](https://docs.kombo.dev/guides/errors) for more
                      information. For your error handling logic please use the
                      error `code` instead of other properties (e.g. message,
                      http status code, ...).
                  title:
                    type:
                      - string
                      - 'null'
                    description: A static, human-readable label.
                  message:
                    type: string
                    description: >-
                      A dynamic, detailed description of what went wrong in this
                      specific instance.
                  log_url:
                    type:
                      - string
                      - 'null'
                    format: uri
                    description: >-
                      The log page in the Kombo UI lists every interaction with
                      full details. If you need assistance, share that link with
                      our support team.
                required:
                  - code
                  - title
                  - message
                  - log_url
                description: Error details with structured code for programmatic handling.
            required:
              - status
              - error
          examples:
            Error Response:
              description: >-
                When building error handling logic, always use the `code` field
                to identify specific error types programmatically. See the
                complete list of error codes in the
                [docs](https://docs.kombo.dev/guides/errors).
              value:
                status: error
                error:
                  code: INTEGRATION.MODEL_NOT_AVAILABLE
                  title: >-
                    This data model isn't supported for the selected
                    integration.
                  message: >-
                    The "employees" model is not yet available for Greenhouse.
                    Please reach out to Kombo if you need this functionality.
                  log_url: https://app.kombo.dev/my-prod/logs?interactionId=123456
            Minimal Error Response:
              description: >-
                The "message" is always required while other fields can also be
                `null`. See the [docs](https://docs.kombo.dev/guides/errors) for
                more information.
              value:
                status: error
                error:
                  code: null
                  title: null
                  message: The message is always in the response.
                  log_url: null
  securitySchemes:
    ApiKey:
      type: http
      scheme: bearer
      description: >-
        Create an API key on the [Secrets](https://app.kombo.dev/secrets) page
        in the Kombo dashboard.

````