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

# Push a calendar event

> For partners that sync calendars themselves. Send each event as your calendar provider
returned it — a Google Calendar event, a Microsoft Graph event or a Nylas event — or in
the small shape, and get back the calendar event of that occurrence (`source: calendar_sync`),
with the `meeting_id` of its meeting.
We read the title, times, organizer, attendees with their response, and the meeting
link (from the conferencing fields, or found in the location or description).

- **Identity.** An event is its iCal UID plus, for an occurrence of a recurring event,
  its original start. Push the same event again to update it; push it for every member
  who has it and they share one meeting and one bot. Send a stable `iCalUID`.
- **Owner.** `member_email` creates the member the first time, as `POST /members` does;
  `member_id` names an existing one.
- **Recurring events.** Push each occurrence (Google instances, Graph occurrences, Nylas
  instances). A series master, with the repeat rule itself, is refused.
- **Cancelling.** Push the event as your provider reports it cancelled
  (`status: cancelled`, including Google's `{ id, status }` deletions, Graph's
  `isCancelled` or `@removed`, `cancelled: true` in the small shape). The meeting is
  cancelled once no member of the workspace still has the event; pushing it live again
  brings it back.
- **Past events** are kept, with their people, as past meetings. No bot is sent.
- **No link.** The meeting exists and `settings.sources["recording.enabled"].reason` is
  `no_meeting_url` until a push carries one. Only Google Meet, Zoom and Microsoft Teams
  links count; any other link (Webex, a dial-in page) reads as no link.

Whether a meeting is recorded follows the member's settings; change one meeting with a
`meeting:` [settings assignment](#operation/createSettings). A member who also connects the same calendar sees each
meeting twice: use one calendar source per workspace.




## OpenAPI

````yaml /openapi.yaml post /calendar_events
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:
  /calendar_events:
    post:
      tags:
        - Calendar events
      summary: Push a calendar event
      description: >
        For partners that sync calendars themselves. Send each event as your
        calendar provider

        returned it — a Google Calendar event, a Microsoft Graph event or a
        Nylas event — or in

        the small shape, and get back the calendar event of that occurrence
        (`source: calendar_sync`),

        with the `meeting_id` of its meeting.

        We read the title, times, organizer, attendees with their response, and
        the meeting

        link (from the conferencing fields, or found in the location or
        description).


        - **Identity.** An event is its iCal UID plus, for an occurrence of a
        recurring event,
          its original start. Push the same event again to update it; push it for every member
          who has it and they share one meeting and one bot. Send a stable `iCalUID`.
        - **Owner.** `member_email` creates the member the first time, as `POST
        /members` does;
          `member_id` names an existing one.
        - **Recurring events.** Push each occurrence (Google instances, Graph
        occurrences, Nylas
          instances). A series master, with the repeat rule itself, is refused.
        - **Cancelling.** Push the event as your provider reports it cancelled
          (`status: cancelled`, including Google's `{ id, status }` deletions, Graph's
          `isCancelled` or `@removed`, `cancelled: true` in the small shape). The meeting is
          cancelled once no member of the workspace still has the event; pushing it live again
          brings it back.
        - **Past events** are kept, with their people, as past meetings. No bot
        is sent.

        - **No link.** The meeting exists and
        `settings.sources["recording.enabled"].reason` is
          `no_meeting_url` until a push carries one. Only Google Meet, Zoom and Microsoft Teams
          links count; any other link (Webex, a dial-in page) reads as no link.

        Whether a meeting is recorded follows the member's settings; change one
        meeting with a

        `meeting:` [settings assignment](#operation/createSettings). A member
        who also connects the same calendar sees each

        meeting twice: use one calendar source per workspace.
      operationId: pushCalendarEvent
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CalendarEventPush'
            examples:
              google:
                summary: A Google Calendar event
                value:
                  workspace_id: wks_01k6a2r9s8x7c2dvq3m5n6p4ab
                  member_email: laia@gurusup.com
                  event:
                    kind: calendar#event
                    id: 7kq2abc_20260929T090000Z
                    iCalUID: 7kq2abc@google.com
                    recurringEventId: 7kq2abc
                    originalStartTime:
                      dateTime: '2026-09-29T09:00:00Z'
                    status: confirmed
                    summary: Weekly sync with Acme
                    start:
                      dateTime: '2026-09-29T11:00:00+02:00'
                      timeZone: Europe/Madrid
                    end:
                      dateTime: '2026-09-29T11:30:00+02:00'
                      timeZone: Europe/Madrid
                    hangoutLink: https://meet.google.com/abc-defg-hij
                    organizer:
                      email: marc@gurusup.com
                    attendees:
                      - email: laia@gurusup.com
                        responseStatus: accepted
                      - email: ana@acme.com
                        responseStatus: needsAction
              small:
                summary: The small shape
                value:
                  workspace_id: wks_01k6a2r9s8x7c2dvq3m5n6p4ab
                  member_id: mem_01k69x2m4q8r7t6v5w4x3y2z1a
                  event:
                    ical_uid: crm-meeting-42
                    title: Renewal call
                    starts_at: '2026-09-29T09:00:00Z'
                    ends_at: '2026-09-29T09:30:00Z'
                    meeting_url: https://zoom.us/j/81234567890
                    organizer:
                      email: marc@gurusup.com
                      name: Marc
                    participants:
                      - email: ana@acme.com
                        name: Ana Ruiz
                        status: accepted
      responses:
        '200':
          description: >
            The calendar event of the occurrence, the same object as the
            meeting's `calendar_event`.

            Versions before 2026-10-12 return the meeting instead.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CalendarEvent'
        '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 or `member_id` is not one the key can see, or a
            cancelled event that was never pushed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Errors'
        '409':
          description: >-
            Another push of the same event is still being processed (`busy`).
            Retry after `Retry-After` seconds.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Errors'
        '413':
          description: The request is over 64 KB.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Errors'
        '422':
          description: >
            An `event` no shape matches (`unrecognised_event`), a recurring
            series

            (`recurring_series_not_supported`), an event without an iCal UID or
            a start

            (`missing`), unreadable times (`invalid`), or not exactly one of
            `member_id` and

            `member_email`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Errors'
        '429':
          description: >-
            More than 1,000 pushes in a minute for the workspace. `Retry-After`
            says when to try again.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Errors'
components:
  schemas:
    CalendarEventPush:
      type: object
      required:
        - workspace_id
        - event
      description: Exactly one of `member_id` and `member_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
        member_id:
          type: string
          description: An existing member of the workspace.
        member_email:
          type: string
          format: email
          maxLength: 255
          description: >-
            The calendar owner; created as a member the first time.
            Disposable-mail and reserved test domains (such as `example.com`)
            are refused with `422` `invalid`.
        metadata:
          $ref: '#/components/schemas/Metadata'
          description: >
            Yours, on the calendar event of the occurrence, shared by every
            member who has it:

            merged on every push (`""` removes a key, `metadata: ""` removes
            them all). Never copied to

            the meeting.
        event:
          type: object
          description: >
            The event exactly as your provider returned it: a Google Calendar
            `events`

            resource, a Microsoft Graph `event` (request it with

            `Prefer: outlook.timezone="UTC"` or an IANA time zone), or a Nylas
            v3 event (bare, as

            `data`, or as a webhook's `data.object`). Keys keep your provider's
            casing. Without a

            provider payload, send the small shape (`CalendarEventSmall`).
          additionalProperties: true
    CalendarEvent:
      type: object
      description: >
        One calendar event per occurrence and workspace: every member's copy of
        it shares this

        object, as they share the meeting. Its times, link and title are the
        occurrence's; its people

        come from the organizer's copy.
      properties:
        id:
          type: string
          description: >-
            Beginning with `cev_`. One per meeting; stays the same through
            reschedules and every member's push.
        object:
          type: string
          description: Always `calendar_event`.
        meeting_id:
          type: string
          description: The meeting of this occurrence, beginning with `mtg_`.
        ical_uid:
          description: >
            The iCal UID shared by every attendee's copy of the event, or `null`
            when the calendar sent none.
          type:
            - string
            - 'null'
        recurring:
          type:
            - boolean
            - 'null'
          description: >-
            Whether the event is an occurrence of a recurring series. `null`
            only in a webhook event from before 2026-10-12, which did not record
            it.
        title:
          description: |
            The event title.
          type:
            - string
            - 'null'
        starts_at:
          description: |
            Scheduled start, in ISO 8601.
          type:
            - string
            - 'null'
          format: date-time
        ends_at:
          description: |
            Scheduled end, in ISO 8601.
          type:
            - string
            - 'null'
          format: date-time
        meeting_url:
          description: |
            The link to join the call, or `null` when the event has none.
          type:
            - string
            - 'null'
        organizer:
          description: |
            Who organizes the event, or `null` when unknown.
          oneOf:
            - $ref: '#/components/schemas/MeetingPerson'
            - type: 'null'
        attendees:
          type: array
          description: >-
            Everyone on the invite, the organizer included. Empty once no member
            has the event.
          items:
            type: object
            properties:
              name:
                type:
                  - string
                  - 'null'
                description: The attendee's name, when the calendar has one.
              email:
                type:
                  - string
                  - 'null'
                description: The attendee's email.
              member_id:
                type:
                  - string
                  - 'null'
                description: Set when the attendee is a member of the workspace.
              response:
                description: >
                  The attendee's answer to the invite, or `null` when the
                  calendar does not say.


                  - `accepted`: accepted.

                  - `declined`: declined.

                  - `tentative`: answered maybe.

                  - `needs_action`: has not answered.
                type:
                  - string
                  - 'null'
                enum:
                  - accepted
                  - declined
                  - tentative
                  - needs_action
                  - null
        source:
          description: |
            Where the event came from.

            - `calendar_connection`: a calendar the member connected.
            - `calendar_sync`: an event you pushed with `POST /calendar_events`.
          type: string
          enum:
            - calendar_connection
            - calendar_sync
        metadata:
          $ref: '#/components/schemas/Metadata'
          description: >-
            Yours; set it with `POST /calendar_events`. Never copied to the
            meeting.
        cancelled_at:
          description: >
            When the event was cancelled, once no member of the workspace still
            has it; otherwise `null`.
          type:
            - string
            - 'null'
          format: date-time
        created_at:
          description: |
            When the event first appeared, in ISO 8601.
          type: string
          format: date-time
        updated_at:
          description: |
            When the event or its meeting last changed, in ISO 8601.
          type: string
          format: date-time
      example:
        id: cev_01k6a2r9s8x7c2dvq3m5n6p4ab
        object: calendar_event
        meeting_id: mtg_01k6a2r9s8x7c2dvq3m5n6p4ab
        ical_uid: 7kq2abc@google.com
        recurring: true
        title: Weekly sync with Acme
        starts_at: '2026-09-29T09:00:00Z'
        ends_at: '2026-09-29T09:30:00Z'
        meeting_url: https://meet.google.com/abc-defg-hij
        organizer:
          name: Marc
          email: marc@gurusup.com
          member_id: mem_01k69x9s8x7c2dvq3m5n6p4ab
        attendees:
          - name: Marc
            email: marc@gurusup.com
            member_id: mem_01k69x9s8x7c2dvq3m5n6p4ab
            response: accepted
          - name: Laia Puig
            email: laia@gurusup.com
            member_id: mem_01k69x2m4q8r7t6v5w4x3y2z1a
            response: accepted
          - name: null
            email: ana@acme.com
            member_id: null
            response: needs_action
        source: calendar_sync
        metadata:
          gurusup_event_id: evt_311
        cancelled_at: null
        created_at: '2026-09-22T08:00:00Z'
        updated_at: '2026-09-28T17:12:03Z'
    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'
    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
    MeetingPerson:
      type: object
      properties:
        name:
          description: |
            The person's name, or `null` when unknown.
          type:
            - string
            - 'null'
        email:
          description: |
            The person's email, or `null` when unknown.
          type:
            - string
            - 'null'
        member_id:
          type:
            - string
            - 'null'
          description: Set when the person is a member of the meeting's workspace.
    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.
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: Authorization
      description: >-
        Your API key, sent bare. See
        [Authentication](/api-reference/authentication).

````