openapi: 3.0.0
info:
  title: Skribby REST API
  description: >
    API-first platform for capturing, transcribing, and processing online
    meetings. 

    Deploy meeting bots into Zoom, Microsoft Teams, and Google Meet to receive
    real-time 

    or post-call transcription, audio, and structured data.


    ## Quick Start


    1. **[Sign up](https://platform.skribby.io)** for a free account

    2. **[Generate API key](https://platform.skribby.io/?to=api-keys)** from
    your dashboard

    3. **Create your first bot:**


    ```bash

    curl -X POST 'https://platform.skribby.io/api/v1/bot' \
      -H 'Authorization: Bearer YOUR_API_KEY' \
      -H 'Content-Type: application/json' \
      -d '{
        "transcription_model": "whisper",
        "meeting_url": "https://meet.google.com/abc-def-ghi",
        "service": "gmeet",
        "bot_name": "My First Bot"
      }'
    ```
  version: v1
  contact:
    name: Skribby Support
    email: support@skribby.io
    url: https://skribby.io
servers:
  - url: https://platform.skribby.io/api/v1
    description: Production server
security:
  - bearerAuth: []
paths:
  /bot:
    post:
      summary: Create Bot
      description: Create a new meeting bot to join and record a meeting.
      operationId: createBot
      tags:
        - Bot Operations
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - transcription_model
                - service
                - meeting_url
                - bot_name
              properties:
                transcription_model:
                  type: string
                  enum:
                    - none
                    - whisper
                    - assembly-ai-realtime
                    - deepgram
                    - assembly-ai
                    - speechmatics
                    - rev-ai
                    - elevenlabs
                    - deepgram-realtime
                    - speechmatics-realtime
                    - gladia
                    - gladia-realtime
                  description: >
                    The transcription model to use for transcribing the audio.

                    Refer to [your billing
                    page](https://platform.skribby.io?to=billing) for cost and
                    availability per model.
                service:
                  type: string
                  enum:
                    - gmeet
                    - teams
                    - zoom
                  description: |
                    The service the bot needs to join:
                    - `gmeet` - Google Meet
                    - `teams` - Microsoft Teams
                    - `zoom` - Zoom
                meeting_url:
                  type: string
                  format: uri
                  description: The URL to the meeting itself which the bot will use to join
                  example: https://meet.google.com/osk-sbwe-nff
                bot_name:
                  type: string
                  description: The name of the bot that'll join the meeting
                  example: My Meeting Bot
                bot_avatar_file:
                  type: string
                  format: binary
                  description: |
                    Binary image file for bot avatar. 
                    Ideally should be in 16:9 aspect ratio.
                bot_avatar_url:
                  type: string
                  format: uri
                  description: |
                    URL to an image that will be used as the bot's avatar.
                    This will be ignored if bot_avatar_file is provided.
                lang:
                  type: string
                  description: >
                    Language of the meeting. Optional but can improve
                    transcription accuracy.

                    When using deepgram-realtime, this parameter is highly
                    recommended.


                    Refer to the [Bot Language](/concepts/bot-language) page for
                    more information.
                  example: en
                video:
                  type: boolean
                  default: false
                  description: >
                    Whether video should also be recorded during the meeting.  

                    Refer to [your billing
                    page](https://platform.skribby.io?to=billing) for cost
                    implications and availability.
                webhook_url:
                  type: string
                  format: uri
                  description: >-
                    URL to receive live updates on bot status changes,
                    participant changes, etc.
                store_recording_for_1_year:
                  type: boolean
                  default: false
                  description: >
                    Audio recordings are stored for 1 week by default. This
                    addon extends storage to 1 year.  

                    Refer to [your billing
                    page](https://platform.skribby.io?to=billing) for cost
                    implications and availability.
                time_limit:
                  type: integer
                  minimum: 5
                  maximum: 240
                  default: 240
                  deprecated: true
                  description: |
                    Use time_limit on `stop_options`.
                scheduled_start_time:
                  type: integer
                  description: >
                    Unix timestamp for when the bot should join the meeting. If
                    not provided,

                    the bot will attempt to join immediately.
                profanity_filter:
                  type: boolean
                  default: false
                  description: >
                    Whether the transcription should censor profanity.

                    Only available on select models. Refer to [your billing
                    page](https://platform.skribby.io?to=billing) for
                    availability per model.
                initial_chat_message:
                  type: string
                  description: >
                    Whenever the bot joins the meeting, it'll send this message
                    to the chat.
                stop_options:
                  type: object
                  description: >
                    Define if and when the bot should stop on certain
                    conditions.
                  properties:
                    time_limit:
                      type: integer
                      minimum: 5
                      maximum: 240
                      default: 240
                      description: >-
                        Maximum time in minutes that the bot may be active. Hard
                        limit is 4 hours (240 minutes).
                    last_person_detection:
                      type: integer
                      minimum: 0
                      maximum: 60
                      default: 2
                      description: >-
                        Minimum time in minutes the bot will spent alone in the
                        meeting (once everyone left) before the bot will stop.
                        Setting this to `0` disables this functionality.
                    silence_detection:
                      type: integer
                      minimum: 0
                      maximum: 60
                      default: 15
                      description: >-
                        Minimum time in minutes the bot will wait for any sounds
                        before the bot will stop. This is useful for when there
                        are other bots in the call and therefor the
                        `last_person_detection` fails. Setting this to `0`
                        disables this functionality.
                authentication:
                  type: object
                  description: >
                    Authentication credentials for joining private meetings.  

                    Refer to the [Bot
                    Authentication](/concepts/bot-authentication) page for more
                    information.
                  properties:
                    account_id:
                      type: string
                      description: >
                        ID of the authenticated account created [via the
                        dashboard](https://platform.skribby.io?to=authenticated-accounts).

                        Used for Google Meet and Microsoft Teams authentication.
                    zoom_zak_token:
                      type: string
                      description: ZAK Token for Zoom authentication.
                    always_authenticate:
                      type: boolean
                      default: false
                      description: >
                        By default, bots try to join as guests first. Set to
                        true to force authentication.
            examples:
              basic_bot:
                summary: Basic Bot
                value:
                  transcription_model: whisper
                  meeting_url: https://meet.google.com/osk-sbwe-nff
                  service: gmeet
                  bot_name: My Meeting Bot
              realtime_bot:
                summary: Real-time Transcription
                value:
                  transcription_model: deepgram-realtime
                  meeting_url: https://teams.microsoft.com/l/meetup-join/...
                  service: teams
                  bot_name: Live Bot
                  lang: en
                  webhook_url: https://your-server.com/webhook
              scheduled_bot:
                summary: Scheduled Bot
                value:
                  transcription_model: deepgram
                  meeting_url: https://zoom.us/j/123456789
                  service: zoom
                  bot_name: Scheduled Bot
                  scheduled_start_time: 1640995200
      responses:
        '200':
          description: Bot created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Bot'
        '400':
          description: Bad request - Invalid parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized - Invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Unauthenticated'
  /bot/{id}:
    get:
      summary: Get Bot
      description: |
        Retrieve information about a specific bot, including its current status,
        transcript (if available), participants, and lifecycle events.
      operationId: getBot
      tags:
        - Bot Operations
      parameters:
        - name: id
          in: path
          required: true
          description: Bot ID
          schema:
            type: string
            format: uuid
          example: 3c09b2aa-6708-42c1-8145-aa55ee223613
        - name: with-speaker-events
          in: query
          required: false
          description: Include speaker events in participant data
          schema:
            type: boolean
            default: false
      responses:
        '200':
          description: Bot information retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Bot'
        '401':
          description: Unauthorized - Invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Unauthenticated'
        '404':
          description: Bot not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotFound'
    delete:
      summary: Delete Bot Data
      description: >
        Delete all data related to the bot, including transcription and
        recording.  

        Bots can only be deleted if they are scheduled or not in an active state
        (`booting`, `joining`, `recording`, `processing` or `transcribing`).  

        Be aware, this action is not reversible!
      operationId: deleteBot
      tags:
        - Bot Operations
      parameters:
        - name: id
          in: path
          required: true
          description: Bot ID
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Bot deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Meeting bot deleted successfully.
        '401':
          description: Unauthorized - Invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Unauthenticated'
        '403':
          description: Bot cannot be deleted
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: Error message
                    example: Meeting bot is still active.
        '404':
          description: Bot not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotFound'
  /bot/{id}/chat-message:
    post:
      summary: Send Chat Message
      description: Send a chat message as the meeting bot
      operationId: sendChatMessage
      tags:
        - Bot Operations
      parameters:
        - name: id
          in: path
          required: true
          description: Bot ID
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - message
              properties:
                message:
                  type: string
                  description: The URL to the meeting itself which the bot will use to join
                  example: Welcome to the meeting!
            examples:
              chat_message:
                summary: Chat Message
                value:
                  message: Welcome to the meeting!
      responses:
        '200':
          description: Message sent to the meeting bot
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Message sent to the meeting bot.
        '400':
          description: Bad request - Invalid parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized - Invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Unauthenticated'
  /bot/{id}/stop:
    post:
      summary: Stop Bot
      description: |
        Stop a running meeting bot. This will cause the bot to leave the meeting
        and begin processing the recording.
      operationId: stopBot
      tags:
        - Bot Operations
      parameters:
        - name: id
          in: path
          required: true
          description: Bot ID
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Bot stopped successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Meeting bot is shutting down.
        '401':
          description: Unauthorized - Invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Unauthenticated'
        '403':
          description: Bot cannot be deleted
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: Error message
                    example: Meeting bot is not joining or recording state.
        '404':
          description: Bot not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotFound'
  /bot/scheduled:
    get:
      summary: Get Scheduled Bots
      description: |
        Retrieve all scheduled bots that haven't started yet. Returns an array 
        of bot objects with status "scheduled".
      operationId: getScheduledBots
      tags:
        - Bot Operations
      responses:
        '200':
          description: Scheduled bots retrieved successfully
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Bot'
        '401':
          description: Unauthorized - Invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Unauthenticated'
  /recording:
    post:
      summary: Create Recording
      description: >
        Upload and transcribe a recording file. You can either upload a file
        directly

        or provide a URL to a publicly accessible file.


        **Note**: Either `recording_file` or `recording_url` is required, but
        not both.
      operationId: createRecording
      tags:
        - Recording Operations
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/CreateRecordingFormRequest'
          application/json:
            schema:
              $ref: '#/components/schemas/CreateRecordingUrlRequest'
            examples:
              url_upload:
                summary: Upload via URL
                value:
                  transcription_model: whisper
                  recording_url: https://example.com/recording.mp3
                  lang: en
              file_upload:
                summary: Direct File Upload
                value:
                  transcription_model: deepgram
                  lang: en
                  webhook_url: https://your-server.com/webhook
      responses:
        '200':
          description: Recording created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Recording'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized - Invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Unauthenticated'
  /recording/{id}:
    get:
      summary: Get Recording
      description: >
        Retrieve information about a specific recording, including its
        transcription

        status and transcript (if available).
      operationId: getRecording
      tags:
        - Recording Operations
      parameters:
        - name: id
          in: path
          required: true
          description: Recording ID
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Recording information retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Recording'
        '401':
          description: Unauthorized - Invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Unauthenticated'
        '404':
          description: Recording not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotFound'
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >
        API key authentication. Get your API key from the [Skribby
        dashboard](https://platform.skribby.io?to=api-keys).

        Include it in the Authorization header: `Authorization: Bearer
        YOUR_API_KEY`
  schemas:
    CreateRecordingFormRequest:
      type: object
      required:
        - transcription_model
        - recording_file
      properties:
        transcription_model:
          type: string
          enum:
            - whisper
            - deepgram
            - assembly-ai
            - speechmatics
            - rev-ai
            - elevenlabs
            - gladia
          description: >-
            The transcription model to use (realtime models not supported for
            uploads)
        recording_file:
          type: string
          format: binary
          description: |
            Audio or video file to be transcribed. Supported formats:
            MP3, WAV, MP4, WEBM, M4A, FLAC. Maximum file size: 1GB.
        lang:
          type: string
          description: >
            Language of the recording content, which will be provided to the
            transcription model.  

            Refer to the [Bot Language](/concepts/bot-language) page for more
            information.
          example: en
        webhook_url:
          type: string
          format: uri
          description: URL to receive status updates during transcription
        store_recording_for_1_year:
          type: boolean
          default: false
          description: >
            Recordings are stored for 1 day by default. This extends storage to
            1 year.  

            Refer to [your billing page](https://platform.skribby.io?to=billing)
            for cost implications and availability.
        profanity_filter:
          type: boolean
          default: false
          description: Whether to censor profanity in transcription.
    CreateRecordingUrlRequest:
      type: object
      required:
        - transcription_model
      properties:
        transcription_model:
          type: string
          enum:
            - whisper
            - deepgram
            - assembly-ai
            - speechmatics
            - rev-ai
            - elevenlabs
            - gladia
          description: The transcription model to use
        recording_url:
          type: string
          format: uri
          description: |
            URL of the file to be transcribed. File must be publicly accessible.
            Supported formats: MP3, WAV, MP4, WEBM, M4A, FLAC.
        lang:
          type: string
          description: Language of the recording content
          example: en
        webhook_url:
          type: string
          format: uri
          description: URL to receive status updates
        store_recording_for_1_year:
          type: boolean
          default: false
          description: Extend storage from 1 day to 1 year
        profanity_filter:
          type: boolean
          default: false
          description: Whether to censor profanity in transcription
    Bot:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Unique bot identifier
          example: 3c09b2aa-6708-42c1-8145-aa55ee223613
        status:
          type: string
          enum:
            - scheduled
            - booting
            - joining
            - recording
            - processing
            - transcribing
            - leaving
            - finished
            - not_admitted
            - auth_required
            - invalid_credentials
            - failed
          description: Current status of the bot
        service:
          type: string
          enum:
            - gmeet
            - teams
            - zoom
          description: Service the bot joined
        scheduled_for:
          type: string
          format: date-time
          nullable: true
          description: When the bot is scheduled to join (for scheduled bots)
        time_limit:
          type: integer
          nullable: true
          description: Use `time_limit` property in `stop_options`.
          deprecated: true
        stop_options:
          type: object
          description: Defined options when the bot should stop on certain conditions.
          properties:
            time_limit:
              type: integer
              minimum: 5
              maximum: 240
              default: 240
              description: >-
                Maximum time in minutes that the bot may be active. Hard limit
                is 4 hours (240 minutes).
            last_person_detection:
              type: integer
              minimum: 0
              maximum: 60
              default: 2
              description: >-
                Minimum time in minutes the bot will spent alone in the meeting
                (once everyone left) before the bot will stop. `0` disables this
                functionality.
            silence_detection:
              type: integer
              minimum: 0
              maximum: 60
              default: 15
              description: >-
                Minimum time in minutes the bot will wait for any sounds before
                the bot will stop. This is useful for when there are other bots
                in the call and therefor the `last_person_detection` fails. `0`
                disables this functionality.
        bot_name:
          type: string
          description: Name of the bot in the meeting
        bot_avatar:
          type: string
          format: uri
          nullable: true
          description: URL to bot avatar image
        meeting_url:
          type: string
          format: uri
          description: URL of the meeting
        webhook_url:
          type: string
          format: uri
          nullable: true
          description: Webhook URL for receiving updates
        recording_url:
          type: string
          format: uri
          nullable: true
          description: URL to download the recording
        recording_available_until:
          type: string
          format: date-time
          nullable: true
          description: When the recording will be automatically deleted
        websocket_url:
          type: string
          format: uri
          nullable: true
          description: WebSocket URL for real-time transcription (realtime models only)
        websocket_read_only_url:
          type: string
          format: uri
          nullable: true
          description: >
            WebSocket URL for real-time transcription (realtime models only) -
            Only provides access to events, no actions.  

            Useful if you want to use the websocket directly in your front-end
            without providing access to the user.
        video:
          type: boolean
          description: Whether video is recorded for this meeting
        lang:
          type: string
          nullable: true
          description: Language specified when creating the bot
        detected_lang:
          type: string
          nullable: true
          description: Language detected from the conversation (if supported by the model)
        transcript:
          type: array
          items:
            $ref: '#/components/schemas/TranscriptSegment'
          description: Array of transcript segments
        transcription_model:
          type: string
          description: Model used for transcription
        participants:
          type: array
          items:
            $ref: '#/components/schemas/Participant'
          description: List of meeting participants
        events:
          type: array
          items:
            $ref: '#/components/schemas/Event'
          description: List of bot lifecycle events
        profanity_filter:
          type: boolean
          description: Whether profanity filter was enabled
        created_at:
          type: string
          format: date-time
          description: When the bot was created
        finished_at:
          type: string
          format: date-time
          nullable: true
          description: When the bot finished
    Recording:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Unique recording identifier
        status:
          type: string
          enum:
            - transcribing
            - finished
            - failed
          description: Current status of the recording
        webhook_url:
          type: string
          format: uri
          nullable: true
          description: Webhook URL for receiving status updates
        recording_url:
          type: string
          format: uri
          nullable: true
          description: URL to the original recording file
        recording_available_until:
          type: string
          format: date-time
          nullable: true
          description: When the recording will be deleted
        lang:
          type: string
          nullable: true
          description: Language specified when creating the recording
        detected_lang:
          type: string
          nullable: true
          description: Language detected from the audio
        transcript:
          type: array
          items:
            $ref: '#/components/schemas/TranscriptSegment'
          description: Transcript segments
        transcription_model:
          type: string
          description: Model used for transcription
        events:
          type: array
          items:
            $ref: '#/components/schemas/Event'
          description: List of processing events
        profanity_filter:
          type: boolean
          description: Whether profanity filter was enabled
        created_at:
          type: string
          format: date-time
          description: When the recording was uploaded
    TranscriptSegment:
      type: object
      properties:
        start:
          type: number
          description: Start time in seconds
          example: 4
        end:
          type: number
          description: End time in seconds
          example: 5.62
        speaker:
          type: integer
          description: Speaker ID
          example: 0
        speaker_name:
          type: string
          nullable: true
          description: Name of the speaker
          example: John Doe
        confidence:
          type: number
          minimum: 0
          maximum: 1
          description: Confidence score for transcript accuracy
          example: 0.9980372
        transcript:
          type: string
          description: The transcribed text
          example: This is a quick test.
        utterances:
          type: array
          items:
            type: object
          description: Detailed utterance information (model-specific)
    Participant:
      type: object
      properties:
        name:
          type: string
          description: Participant's display name
          example: John Doe
        avatar:
          type: string
          format: uri
          nullable: true
          description: URL to participant's avatar
          example: https://picsum.photos/50
        first_seen_at:
          type: string
          format: date-time
          description: When participant was first detected
          example: '2025-06-25T03:03:15.913000Z'
        events:
          type: array
          items:
            $ref: '#/components/schemas/SpeakerEvent'
          description: Speaker events (if `with-speaker-events=true`)
    SpeakerEvent:
      type: object
      properties:
        type:
          type: string
          enum:
            - started-speaking
            - stopped-speaking
          description: Type of speaker event
        timestamp:
          type: integer
          description: Unix timestamp in milliseconds
          example: 1750820602963
    Event:
      type: object
      properties:
        event:
          type: string
          description: Type of event
          example: status_update
        data:
          type: object
          description: Event data
          properties:
            old_status:
              type: string
              example: joining
            new_status:
              type: string
              example: recording
        created_at:
          type: string
          format: date-time
          description: When the event occurred
    Error:
      type: object
      properties:
        message:
          type: string
          description: Error message
          example: The selected transcription model is invalid.
        errors:
          type: object
          description: Error code
          properties:
            transcription_model:
              type: array
              description: List of errors per parameter
              items:
                type: string
                example: The selected transcription model is invalid.
    NotFound:
      type: object
      properties:
        message:
          type: string
          description: Error message
          example: No results found.
    Unauthenticated:
      type: object
      properties:
        message:
          type: string
          description: Error message
          example: Unauthenticated.
tags:
  - name: Bot Operations
    description: Create and manage meeting bots
  - name: Recording Operations
    description: Upload and transcribe recordings
