---
title: "Create Event"
method: POST
path: "/v0/inboxes/{inbox_id}/calendar/events"
tags: ["inboxes > calendar"]
---

# Create Event

`POST /v0/inboxes/{inbox_id}/calendar/events`

## Request

- Base URL: `https://api.agentmail.to`
- URL: `https://api.agentmail.to/v0/inboxes/{inbox_id}/calendar/events`
- Auth: HTTP bearer

Creates a one-off or recurring event on the inbox's calendar. Times are wall-clock values in
`timezone` (the calendar's default time zone if omitted); the response also gives each
boundary as a UTC instant in `start_at` and `end_at`.

`calendar.event.created` is sent once the event is stored, then `calendar.event.starting`
and `calendar.event.ending` as each date begins and ends. With `send_invites: true` the
inbox also emails an invitation to every attendee.

Pass `client_id` to make retries safe: repeating the request with the same `client_id` and
body returns the original event with status `200` instead of `201`, for as long as the event
exists.

With `send_invites: true`, each attendee counts as one send against the organization, pod
and inbox send limits, charged before the event is stored. An over-limit request returns
`429` `rate_limit_exceeded` and creates nothing. A replay of an earlier create is not
charged again.

The event's `etag` is the value to send in `If-Match` to make a later update or delete
conditional. Requires the `calendar_event_create` permission.

Calendar is available in US production (`api.agentmail.to`) but not yet in EU production
(`api.agentmail.eu`), which returns `403`.

## Path parameters

- `inbox_id` string, required: The ID of the inbox.

## Request body

- CalendarCreateCalendarEventRequest
  - `client_id` string: Your idempotency key for this create. Retrying with the same `client_id` and the same body returns the original event with `200` instead of creating a second one, for as long as the event exists (`404` once it has been deleted). Reusing it with a different body is a `409` `idempotency_conflict`.
  - `title` string, required: Title of the event. 1 to 1,000 characters.
  - `description` string: Description of the event. At most 65,536 bytes.
  - `location` string: Location of the event. At most 1,024 characters.
  - `metadata` unknown
  - `status` 'confirmed' | 'tentative' | 'cancelled': Status of the event. A `cancelled` event or date stays readable but sends no `calendar.event.starting` or `calendar.event.ending` webhooks (cancelling a date that is already running still sends its `calendar.event.ending`). A date cancelled by deleting its dated ID is removed from the series instead, so reading it can return `404` or `410`.
  - `all_day` boolean: Set to `true` for an all-day event. Defaults to `false`.
  - `start` string, required: A local wall-clock time without an offset, interpreted in the event's `timezone`. Timed events use `YYYY-MM-DDTHH:mm:ss` (for example `2026-10-15T09:00:00`). All-day events use `YYYY-MM-DD`. Years must be between 1900 and 9999.
  - `end` string, required: A local wall-clock time without an offset, interpreted in the event's `timezone`. Timed events use `YYYY-MM-DDTHH:mm:ss` (for example `2026-10-15T09:00:00`). All-day events use `YYYY-MM-DD`. Years must be between 1900 and 9999.
  - `timezone` string: IANA time zone name, for example `America/New_York`, `Europe/London` or `UTC`. Requests accept any capitalization and IANA aliases such as `US/Eastern`. The calendar stores and returns the canonical name, which for some zones is an older spelling: `Asia/Kolkata` is returned as `Asia/Calcutta`. Abbreviations such as `PST` and Windows names such as `Pacific Standard Time` are rejected.
  - `duration_mode` 'nominal' | 'exact': How the event's length is kept when a date crosses a daylight-saving change. - `exact`: the event lasts the same elapsed time. Default for one-off timed events. - `nominal`: the event keeps its wall-clock end time (a 09:00 to 10:00 meeting stays 09:00 to 10:00 local time). Default for recurring timed events. All-day events are always `nominal`.
  - `recurrence` CalendarRecurrenceInput: Repeats the event. `rule` is an RFC 5545 RRULE, evaluated in the event's `timezone` from the event's `start`. Each date keeps its wall-clock time across daylight-saving changes.
    - `rule` string, required: RFC 5545 RRULE body, with or without the `RRULE:` prefix, for example `FREQ=WEEKLY;BYDAY=MO,WE,FR` or `FREQ=MONTHLY;BYDAY=-1FR;COUNT=12`. Supported parts: `FREQ`, `INTERVAL` (1 to 366), `COUNT` (1 to 10,000), `UNTIL` (`YYYYMMDD` for all-day events, `YYYYMMDDTHHMMSSZ` for timed events), `WKST`, `BYMONTH`, `BYWEEKNO`, `BYYEARDAY`, `BYMONTHDAY`, `BYDAY`, `BYHOUR`, `BYMINUTE`, `BYSECOND` and `BYSETPOS`. `COUNT` and `UNTIL` are mutually exclusive. The rule is stored in a normalized form, so a response can differ textually from what you sent. At most 512 characters after normalization.
    - `exdates` CalendarWallTime[]: Dates to skip, matching the original start of a date: `YYYY-MM-DDTHH:mm:ss` for timed events, `YYYY-MM-DD` for all-day events. At most 366.
    - `rdates` CalendarRecurrenceDate[]: Extra dates to add. Timed events take date-times or periods; all-day events take dates. At most 100.
      - union: A wall-clock date or date-time, or (timed events only) a period.
        - string: A local wall-clock time without an offset, interpreted in the event's `timezone`. Timed events use `YYYY-MM-DDTHH:mm:ss` (for example `2026-10-15T09:00:00`). All-day events use `YYYY-MM-DD`. Years must be between 1900 and 9999.
        - CalendarRecurrencePeriod: An extra date (RDATE) given as a period. Specify exactly one of `end` or `duration`.
          - `start` string, required: A local wall-clock time without an offset, interpreted in the event's `timezone`. Timed events use `YYYY-MM-DDTHH:mm:ss` (for example `2026-10-15T09:00:00`). All-day events use `YYYY-MM-DD`. Years must be between 1900 and 9999.
          - `end` string: A local wall-clock time without an offset, interpreted in the event's `timezone`. Timed events use `YYYY-MM-DDTHH:mm:ss` (for example `2026-10-15T09:00:00`). All-day events use `YYYY-MM-DD`. Years must be between 1900 and 9999.
          - `duration` string: ISO 8601 duration, for example `PT30M`.
  - `attendees` CalendarAttendee[]: Attendees of the event. At most 100.
    - `email` string, required: Email address of the attendee. Stored in lowercase. Must be unique within the event.
    - `name` string: Display name of the attendee. At most 256 characters.
    - `status` 'needs_action' | 'accepted' | 'declined' | 'tentative': The attendee's response to the invitation.
    - `role` 'required' | 'optional': Whether the attendee's presence is required.
    - `comment` string: Comment the attendee sent with their response. At most 4,096 UTF-8 bytes; on create or update, a longer comment is dropped rather than rejected.
    - `responded_at` string, date-time: Time at which the attendee last responded.
  - `send_invites` boolean: When `true`, the inbox emails an invitation (iCalendar `REQUEST`) to every attendee. Defaults to `false`.

## Response `201`

Response with status 201

- CalendarCalendarEventMutationResponse
  - `event` CalendarCalendarEvent, required: A calendar event. The same shape is used by every response, list item and webhook. `kind` says whether it is a one-off event, the definition of a recurring series, or one date of a series.
    - `event_id` string, required: ID of a calendar event. A one-off or recurring event is addressed by its UUID. One date of a recurring event is addressed by a dated ID, `<uuid>_<slot>`: `<uuid>_t20261015T090000` for a timed date (the original wall-clock start in the event's time zone) or `<uuid>_d20261015` for an all-day date. Dated IDs are stable: moving a date keeps its original ID.
    - `kind` 'single' | 'series' | 'instance', required: What the event object represents. - `single`: a one-off event, addressed by its UUID. - `series`: the definition of a recurring event, addressed by its UUID. It carries `recurrence`; `start` and `end` describe its first date. - `instance`: one date of a recurring event, addressed by its dated ID. It carries `series_id`, `original_start` and `is_exception`.
    - `series_id` string: For `instance` events, the UUID of the series this date belongs to.
    - `original_start` string: A local wall-clock time without an offset, interpreted in the event's `timezone`. Timed events use `YYYY-MM-DDTHH:mm:ss` (for example `2026-10-15T09:00:00`). All-day events use `YYYY-MM-DD`. Years must be between 1900 and 9999.
    - `original_start_at` string, date-time: For `instance` events, `original_start` as a UTC instant.
    - `is_exception` boolean: For `instance` events, `true` when this date was edited or moved, individually or by a `mode=future` change.
    - `title` string, required: Title of the event.
    - `description` string: Description of the event. Omitted from agenda and instance list items.
    - `location` string: Location of the event.
    - `metadata` unknown
    - `status` 'confirmed' | 'tentative' | 'cancelled', required: Status of the event. A `cancelled` event or date stays readable but sends no `calendar.event.starting` or `calendar.event.ending` webhooks (cancelling a date that is already running still sends its `calendar.event.ending`). A date cancelled by deleting its dated ID is removed from the series instead, so reading it can return `404` or `410`.
    - `all_day` boolean, required: Whether this is an all-day event.
    - `start` string, required: A local wall-clock time without an offset, interpreted in the event's `timezone`. Timed events use `YYYY-MM-DDTHH:mm:ss` (for example `2026-10-15T09:00:00`). All-day events use `YYYY-MM-DD`. Years must be between 1900 and 9999.
    - `end` string, required: A local wall-clock time without an offset, interpreted in the event's `timezone`. Timed events use `YYYY-MM-DDTHH:mm:ss` (for example `2026-10-15T09:00:00`). All-day events use `YYYY-MM-DD`. Years must be between 1900 and 9999.
    - `timezone` string, required: IANA time zone name, for example `America/New_York`, `Europe/London` or `UTC`. Requests accept any capitalization and IANA aliases such as `US/Eastern`. The calendar stores and returns the canonical name, which for some zones is an older spelling: `Asia/Kolkata` is returned as `Asia/Calcutta`. Abbreviations such as `PST` and Windows names such as `Pacific Standard Time` are rejected.
    - `duration_mode` 'nominal' | 'exact', required: How the event's length is kept when a date crosses a daylight-saving change. - `exact`: the event lasts the same elapsed time. Default for one-off timed events. - `nominal`: the event keeps its wall-clock end time (a 09:00 to 10:00 meeting stays 09:00 to 10:00 local time). Default for recurring timed events. All-day events are always `nominal`.
    - `duration_value` integer, required: Length of the event, in milliseconds for timed events and in days for all-day events.
    - `start_at` string, date-time, required: Start as a UTC instant. This is when `calendar.event.starting` is due.
    - `end_at` string, date-time, required: End as a UTC instant. This is when `calendar.event.ending` is due.
    - `recurrence` CalendarRecurrence: The recurrence of a series, as stored.
      - `rule` string, required: Normalized RRULE body, without the `RRULE:` prefix.
      - `exdates` CalendarWallTime[]
      - `rdates` CalendarRecurrenceDate[]
        - union: A wall-clock date or date-time, or (timed events only) a period.
          - string: A local wall-clock time without an offset, interpreted in the event's `timezone`. Timed events use `YYYY-MM-DDTHH:mm:ss` (for example `2026-10-15T09:00:00`). All-day events use `YYYY-MM-DD`. Years must be between 1900 and 9999.
          - CalendarRecurrencePeriod: An extra date (RDATE) given as a period. Specify exactly one of `end` or `duration`.
            - `start` string, required: A local wall-clock time without an offset, interpreted in the event's `timezone`. Timed events use `YYYY-MM-DDTHH:mm:ss` (for example `2026-10-15T09:00:00`). All-day events use `YYYY-MM-DD`. Years must be between 1900 and 9999.
            - `end` string: A local wall-clock time without an offset, interpreted in the event's `timezone`. Timed events use `YYYY-MM-DDTHH:mm:ss` (for example `2026-10-15T09:00:00`). All-day events use `YYYY-MM-DD`. Years must be between 1900 and 9999.
            - `duration` string: ISO 8601 duration, for example `PT30M`.
      - `truncate_before` string: A local wall-clock time without an offset, interpreted in the event's `timezone`. Timed events use `YYYY-MM-DDTHH:mm:ss` (for example `2026-10-15T09:00:00`). All-day events use `YYYY-MM-DD`. Years must be between 1900 and 9999.
    - `attendees` CalendarAttendee[]: Attendees of the event. Omitted from agenda and instance list items; `attendee_count` is always present.
      - `email` string, required: Email address of the attendee. Stored in lowercase. Must be unique within the event.
      - `name` string: Display name of the attendee. At most 256 characters.
      - `status` 'needs_action' | 'accepted' | 'declined' | 'tentative': The attendee's response to the invitation.
      - `role` 'required' | 'optional': Whether the attendee's presence is required.
      - `comment` string: Comment the attendee sent with their response. At most 4,096 UTF-8 bytes; on create or update, a longer comment is dropped rather than rejected.
      - `responded_at` string, date-time: Time at which the attendee last responded.
    - `attendee_count` integer, required: Number of attendees.
    - `response_status` 'needs_action' | 'accepted' | 'declined' | 'tentative': The attendee's response to the invitation.
    - `uid` string, required: iCalendar UID of the event. Invitations about this event carry the same UID.
    - `sequence` integer, required: iCalendar SEQUENCE number. It increases when a change to a one-off or series event affects what attendees see (time, status, title, description, location, recurrence or attendees). A change to a dated event increases it only when the change is sent with `send_invites`.
    - `source` 'api' | 'email', required: Where the event came from. `api` events were created through this API and the inbox is their organizer. `email` events were created from a calendar invitation (iMIP) received by the inbox; their organizer is the sender of the invitation.
    - `organizer_email` string: Email address of the organizer. For `api` events, the inbox.
    - `origin_message_id` string: For `email` events, the ID of the message whose invitation last created or updated the event.
    - `resource_revision` integer: Revision of the resource. It increases on every change. The resource's `etag` is `"rv-<resource_revision>"`.
    - `created_at` string, date-time, required: Time at which the event (or, for a date, the definition governing it) was created.
    - `updated_at` string, date-time, required: Time at which the event (or, for a date, the definition governing it) was last updated.
    - `etag` string: The event's or date's current version, also sent as the `ETag` response header. Send it in `If-Match` to make an update, delete or response conditional. Present on Get, Create, Update, Delete and Respond responses; list items and webhooks omit it. Treat it as opaque: a dated event's `etag` (`"occ-..."`) is not derived from `resource_revision`.
  - `operation_id` string, required: ID of the change this request made. The `calendar.event.created`, `calendar.event.updated`, `calendar.event.deleted` or `calendar.event.responded` webhook for the change carries the same value as its `event_id`, so you can match webhooks to your own requests.

## Other responses

- `400`: Error response with status 400
- `403`: Calendar isn't available in this region (EU production), or the API key lacks the required calendar permission.
- `404`: Error response with status 404
- `409`: Error response with status 409
- `413`: The request body is too large (8 KB for calendar settings, 128 KB for events).
- `429`: Too many requests, or the invitation emails this request would send exceed an organization, pod or inbox send limit. Nothing was changed. Honor the `Retry-After` header when present.

## Changes

- **2026-10-16** `3f5c7830c952`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/agentmail-to/apis/api/changes/v0/inboxes/:inbox_id/calendar/events/post.md)

---

[API](https://skmtc.dev/agentmail-to/apis/api.md) - [All operations](https://skmtc.dev/agentmail-to/apis/api/llms.txt) - [OpenAPI document](https://skmtc.dev/agentmail-to/apis/api/revisions/a9792efe7bdf?raw)
