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

# Create a member

> Creates a partner end user inside a workspace. Idempotent on `workspace_id` and
`email`: a second call returns the existing member with `200`, unchanged (its `name`
and `metadata` stay as they are; change them with `PATCH /members/{id}`). Nothing is emailed,
and the person never hears from MeetingKit: no confirmation, no onboarding, no
summary emails. An email that already belongs to a MeetingKit user is added to
the workspace as it is; such a member's `name` is theirs and reads as `null`.




## OpenAPI

````yaml /openapi.yaml post /members
openapi: 3.1.0
info:
  title: MeetingKit API
  description: >
    The MeetingKit API lets you build a meetings feature into your product:
    users connect

    a calendar, a notetaker joins their calls, and you get the transcript,
    speakers and

    summary of each meeting.
  version: '2026-10-12'
  contact:
    name: MeetingKit Developer Support
    email: dev@happyscribe.co
servers:
  - url: https://api.meetingkit.com/api/v1
security:
  - apiKeyAuth: []
tags:
  - name: Agent sessions
    description: Exchange the code a user hands their AI agent for API credentials.
  - name: Uploads
    description: Get signed URLs to upload media files directly to MeetingKit storage.
  - name: Transcribe
    description: Create transcription orders from media URLs.
  - name: Subtitle
    description: Create subtitling orders from media URLs.
  - name: Translate
    description: Create translation orders from existing conversations.
  - name: Orders
    description: Retrieve and confirm the orders created by the service endpoints.
  - name: Conversations
    description: List, retrieve, update, and delete conversations.
  - name: Exports
    description: Export conversations to text, subtitle, video-editing, and data formats.
  - name: Bots
    description: Send a notetaker bot to Zoom, Google Meet, or Microsoft Teams calls.
  - name: Glossaries
    description: List glossaries to apply custom terminology to orders.
  - name: Style guides
    description: List style guides to apply formatting preferences to orders.
  - name: Workspaces
    description: List the workspaces the authenticated user belongs to.
  - name: Organization memberships
    description: Manage which users belong to a workspace.
  - name: Members
    description: A partner's end users inside a workspace (MeetingKit).
  - name: Meetings
    description: >-
      Every meeting of a workspace, from calendars and bots, with its results
      (MeetingKit).
  - name: Calendar connections
    description: >-
      Members' Google and Microsoft calendars, connected through a hosted
      consent link and synced by MeetingKit.
  - name: Calendar events
    description: Calendar events a partner pushes from its own calendar sync (MeetingKit).
  - name: Settings
    description: >-
      What gets recorded and how, as values you assign to a workspace, a member,
      a meeting category or one meeting (MeetingKit).
  - name: Settings assignments
    description: Where settings apply (MeetingKit).
  - name: Files
    description: Images uploaded to a workspace, to use in a brand kit (MeetingKit).
  - name: Webhook endpoints
    description: Register the receivers of a workspace's webhooks, and test them.
  - name: Webhook events
    description: >-
      The webhooks sent to a workspace's endpoints, how each delivery went, and
      redelivery.
  - name: People
    description: >-
      Language Services. People found in your transcripts (Memory API, private
      beta).
  - name: Companies
    description: >-
      Language Services. Companies found in your transcripts (Memory API,
      private beta).
paths:
  /members:
    post:
      tags:
        - Members
      summary: Create a member
      description: >
        Creates a partner end user inside a workspace. Idempotent on
        `workspace_id` and

        `email`: a second call returns the existing member with `200`, unchanged
        (its `name`

        and `metadata` stay as they are; change them with `PATCH
        /members/{id}`). Nothing is emailed,

        and the person never hears from MeetingKit: no confirmation, no
        onboarding, no

        summary emails. An email that already belongs to a MeetingKit user is
        added to

        the workspace as it is; such a member's `name` is theirs and reads as
        `null`.
      operationId: createMember
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MemberCreate'
      responses:
        '200':
          description: The member already existed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Member'
        '201':
          description: Member created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Member'
        '401':
          description: >-
            Missing or invalid API key, or the key is not an owner or admin of
            the workspace.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Errors'
        '404':
          description: The workspace is not one the key belongs to.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Errors'
        '422':
          description: >
            Invalid `email` or `name`, including an email on a disposable-mail
            or reserved test

            domain (`invalid`); an email that cannot be added to a workspace
            (`unavailable`);

            a workspace on a legacy plan that bills every member as a seat
            (`seat_billed_plan`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Errors'
        '429':
          description: >-
            More than 100 members created in the workspace in the last hour.
            `Retry-After` says when to try again.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Errors'
components:
  schemas:
    MemberCreate:
      type: object
      required:
        - workspace_id
        - email
      properties:
        workspace_id:
          type: string
          description: >-
            Workspace ID, beginning with `wks_`. Treat it as an opaque string.
            Integer workspace ids are still accepted.
          example: wks_01k6a2r9s8x7c2dvq3m5n6p4ab
        email:
          description: >
            The end user's email. Creating a member again with it returns the
            existing one.

            Addresses on disposable-mail domains (such as `mailinator.com`) and
            reserved test

            domains (such as `example.com`) are refused with `422` `invalid`.
          type: string
          format: email
          maxLength: 255
        name:
          description: |
            The end user's name.
          type: string
          maxLength: 100
        client_reference_id:
          description: >
            Your own id for this person. Stored and returned, never interpreted.
            Set when the

            member is created; a second call for the same email keeps the stored
            one.
          type: string
          maxLength: 255
        metadata:
          $ref: '#/components/schemas/MetadataUpdate'
    Member:
      type: object
      properties:
        id:
          type: string
          description: >-
            Stable typed member ID beginning with `mem_`. Treat it as an opaque
            string.
        object:
          type: string
          description: Always `member`.
        workspace_id:
          type: string
          description: Workspace ID, beginning with `wks_`. Treat it as an opaque string.
          example: wks_01k6a2r9s8x7c2dvq3m5n6p4ab
        email:
          description: |
            The member's email, unique within the workspace.
          type: string
          format: email
        name:
          type: string
          nullable: true
          description: >-
            `null` for a person who also has workspaces of their own: their name
            is theirs.
        client_reference_id:
          type: string
          nullable: true
          maxLength: 255
          description: >-
            Your own id for this person. Stored and returned, never interpreted.
            `null` until you set it.
        metadata:
          $ref: '#/components/schemas/Metadata'
        created_at:
          description: |
            When the member was created, in ISO 8601.
          type: string
          format: date-time
        settings:
          $ref: '#/components/schemas/SettingsBlock'
          description: >
            What applies to the member's meetings that no category or meeting
            decides, and every assignment that reaches

            them. On [List members](#operation/listMembers), only with
            `include=settings`.
    Errors:
      type: object
      required:
        - errors
      description: >
        Every error the API returns, `401` and `429` included. See
        [Errors](/api-reference/errors).
      properties:
        errors:
          type: array
          items:
            $ref: '#/components/schemas/Error'
        retry_in_seconds:
          type: integer
          description: >-
            On `429`, how long to wait before retrying. Also sent as
            `Retry-After`.
      example:
        errors:
          - code: invalid
            field: recording.methods.bot.mode
            message: 'must be one of: audio_and_video, audio_only, inherit'
    MetadataUpdate:
      description: >
        Merged into the object's metadata: the keys you send are added or
        overwritten and the

        others kept. `""` as a value removes that key; `metadata: ""` removes
        every key. Numbers and

        booleans are stored as their text; objects, arrays and `null` are
        refused.
      oneOf:
        - type: object
          maxProperties: 50
          propertyNames:
            minLength: 1
            maxLength: 40
            pattern: ^[^\[\]]+$
          additionalProperties:
            type:
              - string
              - number
              - boolean
            maxLength: 500
        - type: string
          enum:
            - ''
      example:
        gurusup_user_id: usr_8812
        old_key: ''
    Metadata:
      type: object
      description: >
        Your own key-value pairs, for your ids and context. MeetingKit stores
        them, returns them on

        the object and in every webhook that carries it, and never acts on them.
        Up to 50 keys of up

        to 40 characters (no square brackets), values up to 500 characters. See

        [metadata](/meetingkit/setup#a-workspace-per-customer).
      maxProperties: 50
      propertyNames:
        minLength: 1
        maxLength: 40
        pattern: ^[^\[\]]+$
      additionalProperties:
        type: string
        maxLength: 500
      example:
        gurusup_user_id: usr_8812
    SettingsBlock:
      type: object
      description: >
        What applies to this object, which assignment supplied each value, and
        every assignment that reaches it.

        A meeting is resolved exactly; a member as for a meeting in no category;
        a workspace as for a member with nothing

        of their own. See [Settings](/meetingkit/settings).
      properties:
        recording:
          description: |
            Whether the meeting is recorded, and how. Always a value.
          type: object
          properties:
            enabled:
              type: boolean
              description: Whether it is recorded.
            methods:
              description: |
                How it is recorded.
              type: object
              properties:
                bot:
                  description: |
                    The notetaker bot that joins the call.
                  type: object
                  properties:
                    start:
                      type: string
                      enum:
                        - on_join
                        - on_command
                      description: >
                        - `on_join`: records as soon as it joins.

                        - `on_command`: joins paused, until someone types
                        `!resume`.
                    mode:
                      type: string
                      enum:
                        - audio_and_video
                        - audio_only
                      description: |
                        - `audio_and_video`: audio and video.
                        - `audio_only`: audio only.
                    silence_detection:
                      description: |
                        What the bot does when nobody speaks for a while.
                      type: object
                      properties:
                        alert:
                          type: boolean
                          description: >-
                            Whether the bot posts a chat message after a long
                            silence.
        transcription:
          description: |
            How the recording is transcribed.
          type: object
          properties:
            language:
              type: string
              description: A language tag, `auto` or `multi`.
        summary:
          description: |
            How the summary is written.
          type: object
          properties:
            template:
              type: string
              description: The template's slug or `tpl_` id.
            language:
              type: string
              description: A language tag, or `same_as_transcript`.
        branding:
          description: |
            How the notetaker is branded.
          type: object
          properties:
            brand_kit_id:
              type: string
              description: >-
                The brand kit the bot is sent with, or `none` (also when the
                plan does not include notetaker customization).
        sources:
          type: object
          description: >
            For every field, by its dotted path (`recording.enabled`,
            `transcription.language`…), where the value came from.
          additionalProperties:
            $ref: '#/components/schemas/SettingsSource'
        assignments:
          type: array
          description: Every assignment that reaches the object, most specific first.
          items:
            type: object
            properties:
              id:
                type: string
                description: Beginning with `asg_`.
              settings_id:
                type: string
                description: The settings it applies, beginning with `set_`.
              scope:
                type: array
                description: Its conditions.
                items:
                  $ref: '#/components/schemas/SettingsCondition'
              own:
                type: boolean
                description: >-
                  Whether the assignment names this object itself, rather than
                  reaching it from above.
      example:
        recording:
          enabled: true
          methods:
            bot:
              start: on_join
              mode: audio_only
              silence_detection:
                alert: true
        transcription:
          language: ca
        summary:
          template: discovery_call
          language: same_as_transcript
        branding:
          brand_kit_id: brk_01k6acme00000000000000000
        sources:
          recording.enabled:
            assignment_id: asg_01k6a3ext00000000000000000
          recording.methods.bot.start:
            assignment_id: asg_01k6a1ana00000000000000000
          recording.methods.bot.mode:
            assignment_id: asg_01k6a1ana00000000000000000
          recording.methods.bot.silence_detection.alert:
            assignment_id: asg_01k6a1ana00000000000000000
          transcription.language:
            assignment_id: asg_01k6a1ana00000000000000000
          summary.template:
            assignment_id: asg_01k6a1ana00000000000000000
          summary.language:
            assignment_id: asg_01k6a1ana00000000000000000
          branding.brand_kit_id:
            assignment_id: asg_01k6a0wks00000000000000000
        assignments:
          - id: asg_01k6a3ext00000000000000000
            settings_id: set_01k6rec00000000000000000000
            scope:
              - member:mem_01k69x9s8x7c2dvq3m5n6p4ab
              - meetings:external
            own: false
          - id: asg_01k6a1ana00000000000000000
            settings_id: set_01k6sa1es0000000000000000a
            scope:
              - member:mem_01k69x9s8x7c2dvq3m5n6p4ab
            own: false
          - id: asg_01k6a0wks00000000000000000
            settings_id: set_01k6wks00000000000000000000
            scope:
              - workspace:wks_01k6a2r9s8x7c2dvq3m5n6p4ab
            own: false
    Error:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: string
          description: >-
            A stable snake_case word, safe to branch on. See
            [Errors](/api-reference/errors) for the list.
        message:
          type: string
          description: A sentence for humans. It may change; do not parse it.
        field:
          type: string
          description: >-
            The dotted path to the request field at fault, such as
            `recording.methods.bot.mode`. Present only when one field is.
    SettingsSource:
      type: object
      properties:
        assignment_id:
          type:
            - string
            - 'null'
          description: >-
            The assignment whose settings supplied the value; `null` when none
            did, and `reason` says why.
        reason:
          type: string
          enum:
            - happyscribe_default
            - no_meeting_url
            - unsupported_platform
            - member_paused
            - bot_cancelled
          description: >
            Present when no assignment supplied the value.


            - `happyscribe_default`: nothing sets it; MeetingKit's default
            applies.

            - `no_meeting_url`: the meeting has no link to join, so nothing
            records it.

            - `unsupported_platform`: the link is not Zoom, Google Meet or
            Microsoft Teams.

            - `member_paused`: the member paused their notetaker.

            - `bot_cancelled`: the bot sent to this meeting was cancelled before
            it joined.
    SettingsCondition:
      type: string
      description: >
        One condition of an assignment's `scope`, written `<kind>:<name>`. Every
        condition of a scope must hold.


        - `workspace:wks_…`: the workspace's members and meetings. A scope names
        exactly one `workspace:` or `member:`.

        - `member:mem_…`: one member's meetings.

        - `meeting:mtg_…`: one meeting, this occurrence only. It implies its
        workspace; a scope with it names no member.

        - `meetings:organized`: meetings the member organizes.

        - `meetings:internal`: meetings where every participant is a workspace
        member.

        - `meetings:domain`: meetings where every participant is on the member's
        email domain.

        - `meetings:external`: meetings with at least one participant outside
        the workspace.


        One category per scope for now; to record external *or* organized
        meetings, make two assignments of the same settings.
      example: meetings:external
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: Authorization
      description: >-
        Your API key, sent bare. See
        [Authentication](/api-reference/authentication).

````