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

# Create a Lesson

> Creates a lesson in a section. New lessons are published by default and include one completion step.



## OpenAPI

````yaml post /lessons
openapi: 3.0.1
info:
  title: SchoolMaker API V1
  description: API for managing your SchoolMaker school
  license:
    name: MIT
  version: 1.0.0
servers:
  - url: https://schoolmaker.co/api/v1
    description: Production API
security:
  - bearerAuth: []
paths:
  /lessons:
    post:
      tags:
        - Lessons
      summary: Create a Lesson
      description: >-
        Creates a lesson in a section. New lessons are published by default and
        include one completion step.
      operationId: createLesson
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LessonCreateRequest'
            example:
              section_id: section_id
              name: Introduction
              lesson_type: text
              body: '# Welcome'
              content_format: markdown
              is_published: false
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                section_id:
                  type: string
                  minLength: 1
                  maxLength: 255
                  description: >-
                    Parent section ID. Required on creation. Changing it moves
                    the lesson and its content, steps and attachments. You need
                    edit access to both programs. A moved lesson goes to the end
                    unless position is provided. Null is not accepted.
                name:
                  type: string
                  maxLength: 255
                  minLength: 1
                  description: >-
                    Lesson title. Required on creation and cannot be blank or
                    null. Maximum 255 characters.
                description:
                  type: string
                  maxLength: 200000
                  description: >-
                    Lesson description, up to 200000 characters. Empty by
                    default. Send null to clear it. Use content_format to choose
                    HTML or Markdown.
                  nullable: true
                body:
                  type: string
                  maxLength: 200000
                  description: >-
                    Lesson content, up to 200000 characters. Empty by default.
                    Accepts HTML or Markdown and returns HTML. Send null to
                    clear it. Scripts, embedded content and signed attachment
                    markup are not accepted. For blockquotes, use HTML with
                    content_format=html.
                  nullable: true
                content_format:
                  type: string
                  maxLength: 200000
                  enum:
                    - html
                    - markdown
                    - null
                  description: >-
                    Format of the supplied body and description. Defaults to
                    html. Markdown is converted to HTML. Changing this field
                    alone does not change existing content.
                  nullable: true
                position:
                  type: integer
                  minimum: 0
                  description: >-
                    Position within the section, starting at 1. Defaults to the
                    end on creation or when moving sections. Moving a lesson
                    shifts the other lessons. Null is accepted only on creation.
                  nullable: true
                is_progression_locked:
                  type: boolean
                  description: >-
                    Lock the rest of the program until the member completes
                    every step in this lesson. When combined with a drip delay,
                    both conditions must be met. Defaults to false. Send false
                    or null to remove the lock.
                  nullable: true
                is_published:
                  type: boolean
                  description: >-
                    Whether the lesson is published. Defaults to true, including
                    in an unpublished program. Send false to create a draft.
                    Null is accepted only on creation.
                  nullable: true
                settings_embed_wistia:
                  type: string
                  maxLength: 200000
                  description: >-
                    Wistia video ID or supported video URL for a video lesson.
                    Send null or an empty string to clear it. A new value
                    replaces other video providers and settings_embed_code,
                    while preserving embed_code. Supply only one video source
                    per request.
                  nullable: true
                settings_embed_vimeo:
                  type: string
                  maxLength: 200000
                  description: >-
                    Vimeo video ID or supported video URL for a video lesson.
                    Send null or an empty string to clear it. A new value
                    replaces other video providers and settings_embed_code,
                    while preserving embed_code. Supply only one video source
                    per request.
                  nullable: true
                settings_embed_youtube:
                  type: string
                  maxLength: 200000
                  description: >-
                    YouTube video ID or supported video URL for a video lesson.
                    Send null or an empty string to clear it. A new value
                    replaces other video providers and settings_embed_code,
                    while preserving embed_code. Supply only one video source
                    per request.
                  nullable: true
                settings_embed_loom:
                  type: string
                  maxLength: 200000
                  description: >-
                    Loom video ID or supported video URL for a video lesson.
                    Send null or an empty string to clear it. A new value
                    replaces other video providers and settings_embed_code,
                    while preserving embed_code. Supply only one video source
                    per request.
                  nullable: true
                settings_embed_code:
                  type: string
                  maxLength: 200000
                  description: >-
                    Custom video embed HTML for a video lesson. Empty by
                    default. Send null or an empty string to clear it. A new
                    value replaces the video provider selection. Use only one
                    video source per request. For an embed lesson, use
                    embed_code instead.
                  nullable: true
                embed_code:
                  type: string
                  maxLength: 200000
                  description: >-
                    HTML displayed in an embed lesson. Empty by default. Send
                    null or an empty string to clear it. This field is
                    independent of settings_embed_code and video provider
                    settings.
                  nullable: true
                lesson_type:
                  type: string
                  maxLength: 200000
                  enum:
                    - video
                    - text
                    - pdf
                    - embed
                    - audio
                    - null
                  description: >-
                    Lesson type. Defaults to video. Changing the type preserves
                    existing steps and media. Null is accepted only on creation.
                  nullable: true
                drip_delay:
                  type: integer
                  minimum: 0
                  maximum: 32767
                  description: >-
                    Additional delay in days after the section unlocks, from 0
                    to 32767. Defaults to 0. With a program drip start,
                    availability uses that date plus both delays, without the
                    member drip boost. Progression locks also apply. Null is
                    accepted only on creation.
                  nullable: true
              required:
                - section_id
                - name
              additionalProperties: false
            example:
              section_id: section_id
              name: Introduction
              is_published: false
              drip_delay: 2
      responses:
        '200':
          description: Successful request.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LessonDetail'
              example:
                id: lesson_id
                section_id: section_id
                name: Introduction
                position: 1
                lesson_type: text
                drip_delay: 0
                is_published: false
                is_progression_locked: false
                description: ''
                body: <div class="lexxy-content"><h1>Welcome</h1></div>
                settings_embed_wistia: null
                settings_embed_vimeo: null
                settings_embed_youtube: null
                settings_embed_loom: null
                settings_embed_code: null
                embed_code: null
                transcripts: []
                media:
                  pdf_url: null
                  audio_url: null
                  video_poster_url: null
                  video_status: null
                  video_id: null
                  video_error: null
                  video_progress: null
        '401':
          description: Missing or invalid API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LessonError'
              example:
                error: Access denied
        '403':
          description: You do not have permission to perform this action.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LessonError'
              example:
                error: Access denied
        '404':
          description: Lesson not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LessonError'
              example:
                error: Record not found
        '422':
          description: Invalid request. No changes were saved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LessonError'
              example:
                error: 'Invalid arguments: /attributes/drip_delay integer'
components:
  schemas:
    LessonCreateRequest:
      anyOf:
        - type: object
          properties:
            section_id:
              type: string
              minLength: 1
              maxLength: 255
              description: ID of the section for this lesson. Required and cannot be null.
            name:
              type: string
              maxLength: 255
              minLength: 1
              description: >-
                Required lesson title, up to 255 characters. Cannot be blank or
                null.
            description:
              type: string
              maxLength: 200000
              description: >-
                Lesson description, up to 200000 characters. Defaults to an
                empty string when omitted or null. Use content_format=markdown
                to convert Markdown to HTML.
              nullable: true
            body:
              type: string
              maxLength: 200000
              description: >-
                Lesson content in HTML, or Markdown with
                content_format=markdown. Maximum 200000 characters. Omitted or
                null gives an empty body. Responses return HTML. Scripts,
                iframes, object and embed tags, and attachment markup are not
                accepted. Use the video or embed fields for embedded media. Use
                HTML blockquote tags for quotes because Markdown blockquotes
                display as ordinary text.
              nullable: true
            content_format:
              type: string
              maxLength: 200000
              enum:
                - html
                - markdown
                - null
              description: >-
                Format of the body and description sent in this request. Use
                html (default when omitted or null) or markdown. Responses
                return HTML. This does not change content omitted from the
                request.
              nullable: true
            position:
              type: integer
              minimum: 0
              description: >-
                Position in the section, starting at 1. Omitted, null or 0
                places the lesson last. Inserting at an occupied position moves
                later lessons down.
              nullable: true
            is_progression_locked:
              type: boolean
              description: >-
                Lock the rest of the program until members complete all steps in
                this lesson. If a drip delay also applies, both conditions must
                be met. Defaults to false when omitted or null.
              nullable: true
            is_published:
              type: boolean
              description: >-
                Publish this lesson. Defaults to true when omitted or null,
                including in unpublished programs. Send false to create a draft.
                Program publication and member access still apply.
              nullable: true
            settings_embed_wistia:
              type: string
              maxLength: 200000
              description: >-
                Wistia video ID or supported HTTP(S) share, watch or embed URL
                for lesson_type=video. URLs are saved as IDs. Omitted or null
                leaves it empty. A changed nonblank value clears the other video
                providers and settings_embed_code, while keeping embed_code.
                Supply one video source. For multiple changed sources, priority
                is Wistia, YouTube, Vimeo, Loom, then settings_embed_code.
              nullable: true
            settings_embed_vimeo:
              type: string
              maxLength: 200000
              description: >-
                Vimeo video ID or supported HTTP(S) share, watch or embed URL
                for lesson_type=video. URLs are saved as IDs. Omitted or null
                leaves it empty. A changed nonblank value clears the other video
                providers and settings_embed_code, while keeping embed_code.
                Supply one video source. For multiple changed sources, priority
                is Wistia, YouTube, Vimeo, Loom, then settings_embed_code.
              nullable: true
            settings_embed_youtube:
              type: string
              maxLength: 200000
              description: >-
                YouTube video ID or supported HTTP(S) share, watch or embed URL
                for lesson_type=video. URLs are saved as IDs. Omitted or null
                leaves it empty. A changed nonblank value clears the other video
                providers and settings_embed_code, while keeping embed_code.
                Supply one video source. For multiple changed sources, priority
                is Wistia, YouTube, Vimeo, Loom, then settings_embed_code.
              nullable: true
            settings_embed_loom:
              type: string
              maxLength: 200000
              description: >-
                Loom video ID or supported HTTP(S) share, watch or embed URL for
                lesson_type=video. URLs are saved as IDs. Omitted or null leaves
                it empty. A changed nonblank value clears the other video
                providers and settings_embed_code, while keeping embed_code.
                Supply one video source. For multiple changed sources, priority
                is Wistia, YouTube, Vimeo, Loom, then settings_embed_code.
              nullable: true
            settings_embed_code:
              type: string
              maxLength: 200000
              description: >-
                Custom video embed HTML for lesson_type=video. Defaults to empty
                when omitted or null. A nonblank value clears video provider
                fields unless a changed provider takes precedence. The separate
                embed_code field is kept. Supply one video source per request.
              nullable: true
            embed_code:
              type: string
              maxLength: 200000
              description: >-
                Custom HTML for lesson_type=embed. Defaults to empty when
                omitted or null. This is separate from settings_embed_code and
                keeps any video provider settings.
              nullable: true
            lesson_type:
              type: string
              maxLength: 200000
              enum:
                - video
                - text
                - pdf
                - embed
                - audio
                - null
              description: Lesson type. Defaults to video when omitted or null.
              nullable: true
            drip_delay:
              type: integer
              minimum: 0
              maximum: 32767
              description: >-
                Additional delay in days, from 0 to 32767. Defaults to 0 when
                omitted or null. Adds to the section unlock time, including the
                member drip boost. If program access has a drip start date, uses
                the earliest start date plus section and lesson delays, without
                the boost. Progression locks and access restrictions still
                apply.
              nullable: true
          required:
            - section_id
            - name
          additionalProperties: false
        - type: object
          properties:
            section_id:
              type: string
              minLength: 1
              maxLength: 255
              description: ID of the section for this lesson. Required and cannot be null.
            attributes:
              type: object
              properties:
                name:
                  type: string
                  maxLength: 255
                  minLength: 1
                  description: >-
                    Required lesson title, up to 255 characters. Cannot be blank
                    or null.
                description:
                  type: string
                  maxLength: 200000
                  description: >-
                    Lesson description, up to 200000 characters. Defaults to an
                    empty string when omitted or null. Use
                    content_format=markdown to convert Markdown to HTML.
                  nullable: true
                body:
                  type: string
                  maxLength: 200000
                  description: >-
                    Lesson content in HTML, or Markdown with
                    content_format=markdown. Maximum 200000 characters. Omitted
                    or null gives an empty body. Responses return HTML. Scripts,
                    iframes, object and embed tags, and attachment markup are
                    not accepted. Use the video or embed fields for embedded
                    media. Use HTML blockquote tags for quotes because Markdown
                    blockquotes display as ordinary text.
                  nullable: true
                content_format:
                  type: string
                  maxLength: 200000
                  enum:
                    - html
                    - markdown
                    - null
                  description: >-
                    Format of the body and description sent in this request. Use
                    html (default when omitted or null) or markdown. Responses
                    return HTML. This does not change content omitted from the
                    request.
                  nullable: true
                position:
                  type: integer
                  minimum: 0
                  description: >-
                    Position in the section, starting at 1. Omitted, null or 0
                    places the lesson last. Inserting at an occupied position
                    moves later lessons down.
                  nullable: true
                is_progression_locked:
                  type: boolean
                  description: >-
                    Lock the rest of the program until members complete all
                    steps in this lesson. If a drip delay also applies, both
                    conditions must be met. Defaults to false when omitted or
                    null.
                  nullable: true
                is_published:
                  type: boolean
                  description: >-
                    Publish this lesson. Defaults to true when omitted or null,
                    including in unpublished programs. Send false to create a
                    draft. Program publication and member access still apply.
                  nullable: true
                settings_embed_wistia:
                  type: string
                  maxLength: 200000
                  description: >-
                    Wistia video ID or supported HTTP(S) share, watch or embed
                    URL for lesson_type=video. URLs are saved as IDs. Omitted or
                    null leaves it empty. A changed nonblank value clears the
                    other video providers and settings_embed_code, while keeping
                    embed_code. Supply one video source. For multiple changed
                    sources, priority is Wistia, YouTube, Vimeo, Loom, then
                    settings_embed_code.
                  nullable: true
                settings_embed_vimeo:
                  type: string
                  maxLength: 200000
                  description: >-
                    Vimeo video ID or supported HTTP(S) share, watch or embed
                    URL for lesson_type=video. URLs are saved as IDs. Omitted or
                    null leaves it empty. A changed nonblank value clears the
                    other video providers and settings_embed_code, while keeping
                    embed_code. Supply one video source. For multiple changed
                    sources, priority is Wistia, YouTube, Vimeo, Loom, then
                    settings_embed_code.
                  nullable: true
                settings_embed_youtube:
                  type: string
                  maxLength: 200000
                  description: >-
                    YouTube video ID or supported HTTP(S) share, watch or embed
                    URL for lesson_type=video. URLs are saved as IDs. Omitted or
                    null leaves it empty. A changed nonblank value clears the
                    other video providers and settings_embed_code, while keeping
                    embed_code. Supply one video source. For multiple changed
                    sources, priority is Wistia, YouTube, Vimeo, Loom, then
                    settings_embed_code.
                  nullable: true
                settings_embed_loom:
                  type: string
                  maxLength: 200000
                  description: >-
                    Loom video ID or supported HTTP(S) share, watch or embed URL
                    for lesson_type=video. URLs are saved as IDs. Omitted or
                    null leaves it empty. A changed nonblank value clears the
                    other video providers and settings_embed_code, while keeping
                    embed_code. Supply one video source. For multiple changed
                    sources, priority is Wistia, YouTube, Vimeo, Loom, then
                    settings_embed_code.
                  nullable: true
                settings_embed_code:
                  type: string
                  maxLength: 200000
                  description: >-
                    Custom video embed HTML for lesson_type=video. Defaults to
                    empty when omitted or null. A nonblank value clears video
                    provider fields unless a changed provider takes precedence.
                    The separate embed_code field is kept. Supply one video
                    source per request.
                  nullable: true
                embed_code:
                  type: string
                  maxLength: 200000
                  description: >-
                    Custom HTML for lesson_type=embed. Defaults to empty when
                    omitted or null. This is separate from settings_embed_code
                    and keeps any video provider settings.
                  nullable: true
                lesson_type:
                  type: string
                  maxLength: 200000
                  enum:
                    - video
                    - text
                    - pdf
                    - embed
                    - audio
                    - null
                  description: Lesson type. Defaults to video when omitted or null.
                  nullable: true
                drip_delay:
                  type: integer
                  minimum: 0
                  maximum: 32767
                  description: >-
                    Additional delay in days, from 0 to 32767. Defaults to 0
                    when omitted or null. Adds to the section unlock time,
                    including the member drip boost. If program access has a
                    drip start date, uses the earliest start date plus section
                    and lesson delays, without the boost. Progression locks and
                    access restrictions still apply.
                  nullable: true
              additionalProperties: false
              description: Lesson content and settings.
              required:
                - name
          required:
            - section_id
            - attributes
          additionalProperties: false
      description: >-
        Send fields directly or inside attributes. JSON numbers and booleans
        must use their native types. Form requests accept number and boolean
        values, including nested fields such as attributes[is_published]. Use
        JSON for null values. Empty strings and the text null are not treated as
        null.
    LessonDetail:
      type: object
      required:
        - id
        - section_id
        - name
        - position
        - lesson_type
        - drip_delay
        - is_published
        - is_progression_locked
      properties:
        id:
          type: string
        section_id:
          type: string
        name:
          type: string
        position:
          type: integer
          nullable: true
        lesson_type:
          type: string
          enum:
            - video
            - text
            - pdf
            - embed
            - audio
        drip_delay:
          type: integer
        is_published:
          type: boolean
        is_progression_locked:
          type: boolean
          nullable: true
        settings_embed_wistia:
          type: string
          nullable: true
        settings_embed_vimeo:
          type: string
          nullable: true
        settings_embed_youtube:
          type: string
          nullable: true
        settings_embed_loom:
          type: string
          nullable: true
        settings_embed_code:
          type: string
          nullable: true
        embed_code:
          type: string
          nullable: true
        description:
          type: string
        body:
          type: string
          description: Rendered HTML.
        transcripts:
          type: array
          items:
            type: object
            properties:
              language:
                type: string
                nullable: true
              content:
                type: string
                nullable: true
        media:
          type: object
          properties:
            pdf_url:
              type: string
              nullable: true
            audio_url:
              type: string
              nullable: true
            video_poster_url:
              type: string
              nullable: true
            video_status:
              type: string
              nullable: true
            video_id:
              type: string
              nullable: true
            video_error:
              type: string
              nullable: true
            video_progress:
              type: integer
              nullable: true
    LessonError:
      type: object
      required:
        - error
      properties:
        error:
          oneOf:
            - type: string
            - type: array
              items:
                type: string
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer

````

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