# Create calendar event

Create a Brigg-owned calendar event and optionally send email invitations. This does not create an event inside a person’s connected Google or Microsoft calendar.

POST https://api.brigg.app/v1/operations/meetings.CreateCalendarEvent

## Access & visibility

Allow `meetings.CreateCalendarEvent` on your API key. Resource write permissions: `core:CalendarEvent`.

**Workspace access by default.** Private member data requires [approved member delegation](https://developer.brigg.app/authentication#member-delegation) through `Brigg-Act-As`; the key supplies permissions while private ownership and project boundaries remain enforced.

[Set up authentication](https://developer.brigg.app/authentication) · [Choose permissions](https://developer.brigg.app/permissions)

## Request fields

Send a JSON object with the following fields. Required fields must be included; omit optional fields you do not need.
| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `title` | string | Yes | Display title. At least 1 character. |
| `start` | string | Yes | Start timestamp with an explicit time zone, for example 2026-11-10T10:00:00+01:00. Brigg normalizes it to UTC. Do not send a date without a time zone. |
| `end` | string | Yes | End timestamp with an explicit time zone, strictly later than start. Returned calendar times use UTC. |
| `location` | string | No | Physical address or meeting location supplied to invitees. |
| `description` | string | No | Descriptive text. |
| `agenda` | string | No | Discussion topics planned for the meeting. |
| `notes` | string | No | Notes supplied for the calendar event. |
| `attendees` | array of string | No | Workspace member account IDs from [List colleagues](https://developer.brigg.app/reference/workspace/ListColleagues), not Person record IDs or email addresses. Members without an email address are returned in send.skipped. |
| `visibility` | array of string | No | Reserved compatibility field; it currently has no effect. Omit it. It cannot make the calendar event private or grant access to attendees. At least 1 item. |
| `send_invite` | boolean | No | Send email invitations after saving the event. Defaults to false. Requires at least one attendee with an email address. |
| `message` | string | No | The cover note of the mail, instead of the default. |

## Choose the calendar you mean

This creates a Brigg-owned calendar record. Use [Create connected calendar event](https://developer.brigg.app/reference/meetings/CreateConnectedCalendarEvent) to write to Google or Microsoft instead. Use [Create meeting](https://developer.brigg.app/reference/meetings/CreateMeeting) for a meeting record with notes and summaries. These are different resources.

Omit `send_invite` or set it to false to save without email. To send invitations, find member account IDs with [List colleagues](https://developer.brigg.app/reference/workspace/ListColleagues) and set `send_invite: true`. Email addresses and customer Person IDs are not accepted as attendee identities by this operation.

## Handle invitation delivery separately

The calendar event is saved before invitations are attempted. `send.message_ids` lists submitted emails, not proof of delivery. `send.skipped` contains member IDs without usable email addresses. If `send.rate_limited` is true, the event exists but invitations were not sent. Do not create the event again.

After resolving delivery or quota issues, use [Update calendar event](https://developer.brigg.app/reference/meetings/UpdateCalendarEvent) with the returned `id`, `send_update: true` and a new idempotency key. Retrying the original create with its original key returns that create's recorded outcome; it does not constitute a new send attempt.

## Response

Returns **200 OK** with a JSON body.
| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | Yes | Brigg calendar record ID. Use it with [Get calendar event](https://developer.brigg.app/reference/meetings/GetCalendarEvent) or [Update calendar event](https://developer.brigg.app/reference/meetings/UpdateCalendarEvent). |
| `uid` | string | Yes | Calendar invitation UID, distinct from the Brigg record ID. |
| `sequence` | number | Yes | Calendar invitation revision number. |
| `send` | [object](#response-send) | No | Invitation attempt result. Absent when no invitation attempt was made; the saved event exists independently of this result. |

### response.send

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `message_ids` | map of string | Yes | Recipient email address to delivery message ID. |
| `skipped` | array of string | Yes | Attendee account ids with no email address. |
| `rate_limited` | boolean | No | The org's invite quota was hit — the event write landed, no mail went out. |

## Errors & retries

Set `BRIGG_REQUEST_ID` once for each logical action. The samples send it as `Idempotency-Key`. Reuse the same value and body on retries, including after a timeout; a missing response does not prove the action failed.

For rate limits, follow the server’s retry guidance and back off. See [HTTP errors](https://developer.brigg.app/http#errors) and [safe retries and limits](https://developer.brigg.app/reliability).

| HTTP status | Code | What to do |
| --- | --- | --- |
| 400 | `invalid_json` | Send a JSON object with Content-Type: application/json. |
| 400 | `invalid_input` | Check the request fields and types. Supply a stable Idempotency-Key containing 1–200 characters. |
| 401 | `invalid_key` | The workspace API key is missing, invalid or revoked. |
| 403 | `forbidden` | Check the key’s operation and resource grants. If Brigg-Act-As is supplied, the key must be authorized to delegate to that member. |
| 404 | `not_found` | The requested operation or resource is not available to this credential. |
| 429 | `rate_limited` | Wait for Retry-After before retrying. Reuse the original Idempotency-Key. |

## Next steps

- [Get calendar event](https://developer.brigg.app/reference/meetings/GetCalendarEvent)
- [Update calendar event](https://developer.brigg.app/reference/meetings/UpdateCalendarEvent)
- [Create connected calendar event](https://developer.brigg.app/reference/meetings/CreateConnectedCalendarEvent)
- [List colleagues](https://developer.brigg.app/reference/workspace/ListColleagues)

[Download OpenAPI](https://developer.brigg.app/openapi.json) · [Versioning & retirement](https://developer.brigg.app/versioning)

## Examples

### Save without sending

Times are UTC. No invitations are sent when send_invite is omitted.
#### cURL


```sh
curl 'https://api.brigg.app/v1/operations/meetings.CreateCalendarEvent' \
  -H "Authorization: Bearer $BRIGG_API_KEY" \
  -H 'Content-Type: application/json' \
  -H "Idempotency-Key: $BRIGG_REQUEST_ID" \
  --data-raw '{
  "title": "Northstar project kickoff",
  "start": "2026-11-10T09:00:00.000Z",
  "end": "2026-11-10T09:45:00.000Z"
}'
```

#### TypeScript


```typescript
const requestId = process.env.BRIGG_REQUEST_ID;
if (!requestId) throw new Error("Set BRIGG_REQUEST_ID once per action and reuse it on retries.");

const response = await fetch("https://api.brigg.app/v1/operations/meetings.CreateCalendarEvent", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.BRIGG_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": requestId, // Create once per action; reuse on retries.
  },
  body: JSON.stringify({
    "title": "Northstar project kickoff",
    "start": "2026-11-10T09:00:00.000Z",
    "end": "2026-11-10T09:45:00.000Z"
  }),
});
const result = await response.json();
if (!response.ok) throw new Error(`${response.status}: ${result.error} — ${result.message}`);
console.log(result);
```

#### Python


```python
import json
import os
from urllib.request import Request, urlopen
from urllib.error import HTTPError

request_id = os.environ["BRIGG_REQUEST_ID"]  # Reuse for retries of this action.
payload = {
  "title": "Northstar project kickoff",
  "start": "2026-11-10T09:00:00.000Z",
  "end": "2026-11-10T09:45:00.000Z"
}
request = Request(
    "https://api.brigg.app/v1/operations/meetings.CreateCalendarEvent",
    data=json.dumps(payload).encode("utf-8"),
    headers={
        "Authorization": f"Bearer {os.environ['BRIGG_API_KEY']}",
        "Content-Type": "application/json",
        "Idempotency-Key": request_id,  # Create once per action; reuse on retries.
    },
    method="POST",
)
try:
    with urlopen(request) as response:
        print(json.load(response))
except HTTPError as error:
    print(error.code, json.load(error))
    raise
```

#### Response example


```json
{
  "id": "e_calendar_kickoff",
  "uid": "kickoff@example.com",
  "sequence": 0
}
```

### Invite workspace members

Use real account IDs from List colleagues. The response maps submitted emails to message IDs.
#### cURL


```sh
curl 'https://api.brigg.app/v1/operations/meetings.CreateCalendarEvent' \
  -H "Authorization: Bearer $BRIGG_API_KEY" \
  -H 'Content-Type: application/json' \
  -H "Idempotency-Key: $BRIGG_REQUEST_ID" \
  --data-raw '{
  "title": "Northstar project kickoff",
  "start": "2026-11-10T09:00:00.000Z",
  "end": "2026-11-10T09:45:00.000Z",
  "attendees": [
    "a_jamie"
  ],
  "send_invite": true,
  "message": "Please join the project kickoff."
}'
```

#### TypeScript


```typescript
const requestId = process.env.BRIGG_REQUEST_ID;
if (!requestId) throw new Error("Set BRIGG_REQUEST_ID once per action and reuse it on retries.");

const response = await fetch("https://api.brigg.app/v1/operations/meetings.CreateCalendarEvent", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.BRIGG_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": requestId, // Create once per action; reuse on retries.
  },
  body: JSON.stringify({
    "title": "Northstar project kickoff",
    "start": "2026-11-10T09:00:00.000Z",
    "end": "2026-11-10T09:45:00.000Z",
    "attendees": [
      "a_jamie"
    ],
    "send_invite": true,
    "message": "Please join the project kickoff."
  }),
});
const result = await response.json();
if (!response.ok) throw new Error(`${response.status}: ${result.error} — ${result.message}`);
console.log(result);
```

#### Python


```python
import json
import os
from urllib.request import Request, urlopen
from urllib.error import HTTPError

request_id = os.environ["BRIGG_REQUEST_ID"]  # Reuse for retries of this action.
payload = {
  "title": "Northstar project kickoff",
  "start": "2026-11-10T09:00:00.000Z",
  "end": "2026-11-10T09:45:00.000Z",
  "attendees": [
    "a_jamie"
  ],
  "send_invite": True,
  "message": "Please join the project kickoff."
}
request = Request(
    "https://api.brigg.app/v1/operations/meetings.CreateCalendarEvent",
    data=json.dumps(payload).encode("utf-8"),
    headers={
        "Authorization": f"Bearer {os.environ['BRIGG_API_KEY']}",
        "Content-Type": "application/json",
        "Idempotency-Key": request_id,  # Create once per action; reuse on retries.
    },
    method="POST",
)
try:
    with urlopen(request) as response:
        print(json.load(response))
except HTTPError as error:
    print(error.code, json.load(error))
    raise
```

#### Response example


```json
{
  "id": "e_calendar_kickoff",
  "uid": "kickoff@example.com",
  "sequence": 0,
  "send": {
    "message_ids": {
      "jamie@example.com": "msg_kickoff"
    },
    "skipped": [],
    "rate_limited": false
  }
}
```

### Event saved, invitations held

Handle this successful HTTP response as partial completion. Keep the event ID and retry delivery separately.
#### cURL


```sh
curl 'https://api.brigg.app/v1/operations/meetings.CreateCalendarEvent' \
  -H "Authorization: Bearer $BRIGG_API_KEY" \
  -H 'Content-Type: application/json' \
  -H "Idempotency-Key: $BRIGG_REQUEST_ID" \
  --data-raw '{
  "title": "Northstar project kickoff",
  "start": "2026-11-10T09:00:00.000Z",
  "end": "2026-11-10T09:45:00.000Z",
  "attendees": [
    "a_jamie"
  ],
  "send_invite": true
}'
```

#### TypeScript


```typescript
const requestId = process.env.BRIGG_REQUEST_ID;
if (!requestId) throw new Error("Set BRIGG_REQUEST_ID once per action and reuse it on retries.");

const response = await fetch("https://api.brigg.app/v1/operations/meetings.CreateCalendarEvent", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.BRIGG_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": requestId, // Create once per action; reuse on retries.
  },
  body: JSON.stringify({
    "title": "Northstar project kickoff",
    "start": "2026-11-10T09:00:00.000Z",
    "end": "2026-11-10T09:45:00.000Z",
    "attendees": [
      "a_jamie"
    ],
    "send_invite": true
  }),
});
const result = await response.json();
if (!response.ok) throw new Error(`${response.status}: ${result.error} — ${result.message}`);
console.log(result);
```

#### Python


```python
import json
import os
from urllib.request import Request, urlopen
from urllib.error import HTTPError

request_id = os.environ["BRIGG_REQUEST_ID"]  # Reuse for retries of this action.
payload = {
  "title": "Northstar project kickoff",
  "start": "2026-11-10T09:00:00.000Z",
  "end": "2026-11-10T09:45:00.000Z",
  "attendees": [
    "a_jamie"
  ],
  "send_invite": True
}
request = Request(
    "https://api.brigg.app/v1/operations/meetings.CreateCalendarEvent",
    data=json.dumps(payload).encode("utf-8"),
    headers={
        "Authorization": f"Bearer {os.environ['BRIGG_API_KEY']}",
        "Content-Type": "application/json",
        "Idempotency-Key": request_id,  # Create once per action; reuse on retries.
    },
    method="POST",
)
try:
    with urlopen(request) as response:
        print(json.load(response))
except HTTPError as error:
    print(error.code, json.load(error))
    raise
```

#### Response example


```json
{
  "id": "e_calendar_kickoff",
  "uid": "kickoff@example.com",
  "sequence": 0,
  "send": {
    "message_ids": {},
    "skipped": [],
    "rate_limited": true
  }
}
```

## JSON schemas


```json-schema-request
{
  "type": "object",
  "properties": {
    "title": {
      "type": "string",
      "minLength": 1,
      "description": "Display title."
    },
    "start": {
      "type": "string",
      "description": "Start timestamp with an explicit time zone, for example 2026-11-10T10:00:00+01:00. Brigg normalizes it to UTC. Do not send a date without a time zone."
    },
    "end": {
      "type": "string",
      "description": "End timestamp with an explicit time zone, strictly later than start. Returned calendar times use UTC."
    },
    "location": {
      "type": "string",
      "description": "Physical address or meeting location supplied to invitees."
    },
    "description": {
      "type": "string",
      "description": "Descriptive text."
    },
    "agenda": {
      "type": "string",
      "description": "Discussion topics planned for the meeting."
    },
    "notes": {
      "type": "string",
      "description": "Notes supplied for the calendar event."
    },
    "attendees": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Workspace member account IDs from [List colleagues](https://developer.brigg.app/reference/workspace/ListColleagues), not Person record IDs or email addresses. Members without an email address are returned in send.skipped."
    },
    "visibility": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "minItems": 1,
      "description": "Reserved compatibility field; it currently has no effect. Omit it. It cannot make the calendar event private or grant access to attendees."
    },
    "send_invite": {
      "type": "boolean",
      "description": "Send email invitations after saving the event. Defaults to false. Requires at least one attendee with an email address."
    },
    "message": {
      "type": "string",
      "description": "The cover note of the mail, instead of the default."
    }
  },
  "required": [
    "title",
    "start",
    "end"
  ],
  "additionalProperties": false,
  "examples": [
    {
      "title": "Northstar project kickoff",
      "start": "2026-11-10T09:00:00.000Z",
      "end": "2026-11-10T09:45:00.000Z"
    }
  ]
}
```


```json-schema-response
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "Brigg calendar record ID. Use it with [Get calendar event](https://developer.brigg.app/reference/meetings/GetCalendarEvent) or [Update calendar event](https://developer.brigg.app/reference/meetings/UpdateCalendarEvent)."
    },
    "uid": {
      "type": "string",
      "description": "Calendar invitation UID, distinct from the Brigg record ID."
    },
    "sequence": {
      "type": "number",
      "description": "Calendar invitation revision number."
    },
    "send": {
      "type": "object",
      "description": "Invitation attempt result. Absent when no invitation attempt was made; the saved event exists independently of this result.",
      "properties": {
        "message_ids": {
          "description": "Recipient email address to delivery message ID.",
          "type": "object",
          "additionalProperties": {
            "type": "string"
          }
        },
        "skipped": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Attendee account ids with no email address."
        },
        "rate_limited": {
          "type": "boolean",
          "description": "The org's invite quota was hit — the event write landed, no mail went out."
        }
      },
      "required": [
        "message_ids",
        "skipped"
      ],
      "additionalProperties": false
    }
  },
  "required": [
    "id",
    "uid",
    "sequence"
  ],
  "additionalProperties": false,
  "examples": [
    {
      "id": "e_calendar_kickoff",
      "uid": "kickoff@example.com",
      "sequence": 0
    }
  ]
}
```

