---
title: "Create a calendar event"
method: POST
path: "/calendar/events"
tags: ["Calendar"]
---

# Create a calendar event

`POST /calendar/events`

## Request

- Base URL: `https://shipmail.to/api/v1`
- URL: `https://shipmail.to/api/v1/calendar/events`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://shipmail.to/api/auth/oauth2/authorize`, token URL `https://shipmail.to/api/auth/oauth2/token`)

## Headers

- `X-Shipmail-Organization` string

## Request body

- CreateCalendarEventRequest
  - `mailbox` string, email, required: The mailbox (calendar owner) address.
  - `calendar_id` string: Target calendar. Defaults to the mailbox's default calendar.
  - `title` string, required
  - `invitation_language` 'en' | 'fr' | 'es': Language used for invitation, update, cancellation, and RSVP interface copy.
  - `start` string, required: Local date-time (YYYY-MM-DDTHH:MM:SS). Its zone is given by timezone.
  - `description` string
  - `timezone` string: IANA time zone the start is defined in.
  - `duration` string: ISO 8601 duration, e.g. PT1H. Defaults to one hour.
  - `all_day` boolean
  - `location` string
  - `video_url` string, uri
  - `color` string
  - `status` 'confirmed' | 'tentative' | 'cancelled'
  - `free_busy_status` 'free' | 'busy'
  - `privacy` 'public' | 'private' | 'secret'
  - `recurrence` Recurrence
    - `frequency` 'yearly' | 'monthly' | 'weekly' | 'daily' | 'hourly' | 'minutely' | 'secondly', required
    - `interval` integer
    - `count` integer
    - `until` string: Local date-time, e.g. 2026-12-31T00:00:00.
    - `by_day` RecurrenceNDay[]
      - `day` 'mo' | 'tu' | 'we' | 'th' | 'fr' | 'sa' | 'su', required
      - `nth_of_period` integer
  - `reminders` Reminder[]
    - `minutes_before` integer, required: Minutes before the event start to fire an email reminder.
  - `attendees` CalendarAttendeeInput[]
    - `email` string, email, required
    - `name` string
  - `operation_key` string: Stable retry key for this exact create payload.
  - `send_invitations` boolean: Send invitations to attendees.

## Response `201`

Calendar event created.

- CalendarEventMutationResult
  - `object` 'calendar_event', required
  - `id` string, required
  - `revision` string, required: Content revision to pass as expected_revision on a later update.
  - `mailbox` string, email, required: The mailbox (calendar owner) address.
  - `calendar_id` string, nullable, required
  - `uid` string, nullable, required
  - `title` string, nullable, required
  - `invitation_language` 'en' | 'fr' | 'es', required: Language used for Shipmail invitation, update, cancellation, and RSVP interface copy.
  - `description` string, nullable, required
  - `location` string, nullable, required
  - `video_url` string, nullable, required: Video/conference join URL (JSCalendar virtualLocation).
  - `all_day` boolean, required
  - `start` string, required: Timed events: a UTC instant. All-day events: a YYYY-MM-DD date.
  - `end` string, required: Timed events: a UTC instant. All-day events: the exclusive end date.
  - `timezone` string, nullable, required: The event's own IANA time zone. Null for all-day or floating events.
  - `duration` string, nullable, required: ISO 8601 duration, e.g. PT1H.
  - `status` 'confirmed' | 'tentative' | 'cancelled', nullable, required
  - `free_busy_status` 'free' | 'busy', nullable, required
  - `privacy` 'public' | 'private' | 'secret', nullable, required
  - `color` string, nullable, required
  - `recurrence` Recurrence, required
    - `frequency` 'yearly' | 'monthly' | 'weekly' | 'daily' | 'hourly' | 'minutely' | 'secondly', required
    - `interval` integer
    - `count` integer
    - `until` string: Local date-time, e.g. 2026-12-31T00:00:00.
    - `by_day` RecurrenceNDay[]
      - `day` 'mo' | 'tu' | 'we' | 'th' | 'fr' | 'sa' | 'su', required
      - `nth_of_period` integer
  - `recurrence_id` string, nullable, required: Set on an expanded recurrence instance.
  - `reminders` Reminder[], required
    - `minutes_before` integer, required: Minutes before the event start to fire an email reminder.
  - `organizer` CalendarPerson, required
    - `email` string, email, required
    - `name` string, nullable, required
  - `attendees` CalendarAttendee[], required
    - `email` string, email, required
    - `name` string, nullable, required
    - `status` 'needs-action' | 'accepted' | 'declined' | 'tentative', required
  - `created_at` string, date-time, nullable, required
  - `updated_at` string, date-time, nullable, required
  - `invitation_outcomes` CalendarInvitationOutcome[], required: Per-recipient delivery outcome for this mutation.
    - `recipient` string, email, required
    - `status` 'sent' | 'failed' | 'unknown', required
  - `invitation_failures` string[], required: Compatibility list of failed and unknown recipients.

## Other responses

- `404`: Resource not found.
- `422`: Validation failed.
- `429`: Rate limit exceeded.

---

[API](https://skmtc.dev/shipmail/apis/shipmail-api.md) · [All operations](https://skmtc.dev/shipmail/apis/shipmail-api/llms.txt) · [OpenAPI document](https://skmtc.dev/shipmail/apis/shipmail-api/revisions/2c23e59d7e30?raw)
