Skip to content

Book an event on the caller's own calendar (user)

Always writes to the caller's own mailbox; there is no way to name a subject on this endpoint. Attendees are invited by email address only, never by a colleague's internal user id, which would let this endpoint be used to probe one.

attendees is capped at 50: a draft with attendees sets sendUpdates=all on the provider, so an unbounded list would turn this endpoint into a bulk-invite sender from the caller's own, real, DKIM/SPF-passing domain.

Rate limited to 15 requests/minute (throttle:calendar-write).

HTTP: bearerAuth

User bearer token. Default authentication for customer-facing endpoints. Obtain a token by calling POST /login with your credentials, then send it on every subsequent request as Authorization: Bearer <token>. The token inherits the permissions and PBX scope of the authenticated user.

HTTP Authorization Scheme
bearer
Bearer format
Bearer <token>
accept header · string
example: application/json

Request body · required · application/json

Request schema
subject*string
length: 0–255
start*string · date-time
end*string · date-time
Must be after `start`.
timezonestring | null
An IANA timezone name.
bodystring | null
length: 0–20000
locationstring | null
length: 0–255
online_meetingboolean | null
Whether to create a provider-native online meeting for this event.
attendeesarray<object>
items: 0–50
email*string · email
namestring | null
length: 0–255
typestring | null
enum: required optional

Responses

Created. `data` is omitted on the rare case the provider returns no event back.
Response schema
dataobject
A single calendar event, normalised away from whichever provider (Microsoft or Google) produced it. This is the shape returned by `GET /me/calendar/events/{event}`, `POST /me/calendar/events`, `PATCH /me/calendar/events/{event}`, `GET /me/calendar/next` and `GET /users/{user}/calendar/next`. **Not the shape of `GET /me/calendar/agenda` or `GET /users/{user}/calendar/agenda`.** Those two endpoints currently serialise the underlying event data directly (camelCase field names, e.g. `seriesMasterId` instead of `series_master_id`), while every other endpoint on this page goes through this snake_case model. This is a known, tracked inconsistency in the API today, not a documentation error; see the `agenda` operations for the exact camelCase shape they return.
id*string
Provider-native event id. Opaque; do not parse it.
example: AAMkAGI1AAAtOTU1AAA=
deleted*boolean
True when the provider is reporting this event as removed. A deleted event carries no other field but `id` (and `calendar_id`, if known) - every other field is absent rather than stale.
example:
series_master_idstring | null
Id of the recurring series this event belongs to, or null for a non-recurring event.
subjectstring | null
Event title. Null when the provider did not say.
example: Weekly Sync
startstring | null · date-time
Start time, always UTC regardless of the mailbox's own timezone.
example: 2026-09-08T09:00:00Z
endstring | null · date-time
End time, always UTC regardless of the mailbox's own timezone.
example: 2026-09-08T09:30:00Z
is_all_day*boolean
example:
is_cancelled*boolean
True when the organizer cancelled the event (distinct from `deleted`, a tombstone).
example:
show_asstring | null
How the event presents the owner's availability. Null when the provider did not say.
enum: free tentative busy oof workingElsewhere null
example: busy
sensitivitystring | null
How private the owner marked the event. Null when the provider did not say.
enum: normal personal private confidential null
example: normal
responsestring | null
The mailbox owner's own answer to the invitation.
enum: none organizer tentativelyAccepted accepted declined notResponded null
example: accepted
calendar_idstring | null
Which calendar the event came from. Null means the mailbox's primary calendar.
attendeesarray<object>
Invitees. Null when the provider did not say (never an empty array standing in for "no attendees", which is itself a distinct fact).
emailstring · email
example: jane.smith@example.com
namestring | null
example: Jane Smith
typestring
enum: required optional
example: required
responsestring | null
enum: none organizer tentativelyAccepted accepted declined notResponded null
example: accepted
organizer_emailstring | null · email
example: jane.smith@example.com
locationstring | null
example: Conference Room 2
online_meetingstring | null
Provider-native online-meeting join URL. Null when the event has none.
example: https://meet.example.com/abc-defg-hij
Unauthenticated. The `Authorization: Bearer <token>` header was missing, malformed, or names a token that has been revoked or deleted.
Response schema
messagestring
The calendar assistant is not enabled for this account. Returned when there is no `user_provider_mappings` row for the caller carrying the assistant capability, or the capability is present but switched off. There is deliberately no fallback to "assume Microsoft" here, unlike other capabilities on the same table.
Response schema
messagestring
Standard field validation (e.g. missing `subject`, `end` not after `start`, more than 50 attendees).
Response schema
messagestring
errorsobject
Free-form object
Too Many Requests. The rate limit for this action has been exceeded. Retry after the window indicated by the Retry-After header.
Response schema
messagestring
post https://cockpit.voxbi.com/api/v1/me/calendar/events
Base URL
Request sample
curl -X POST 'https://cockpit.voxbi.com/api/v1/me/calendar/events' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  --data '{"subject":"Weekly Sync","start":"2026-09-08T09:00:00Z","end":"2026-09-08T09:30:00Z","timezone":"Europe/Luxembourg","location":"Conference Room 2","online_meeting":true,"attendees":[{"email":"jane.smith@example.com","name":"Jane Smith","type":"required"}]}'
const response = await fetch('https://cockpit.voxbi.com/api/v1/me/calendar/events', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${YOUR_TOKEN}`,
  },
  body: JSON.stringify({
    "subject": "Weekly Sync",
    "start": "2026-09-08T09:00:00Z",
    "end": "2026-09-08T09:30:00Z",
    "timezone": "Europe/Luxembourg",
    "location": "Conference Room 2",
    "online_meeting": true,
    "attendees": [
        {
            "email": "jane.smith@example.com",
            "name": "Jane Smith",
            "type": "required"
        }
    ]
}),
});

const data = await response.json();
console.log(data);
import requests

response = requests.post('https://cockpit.voxbi.com/api/v1/me/calendar/events',
    headers={'Authorization': f'Bearer {YOUR_TOKEN}'},
    json={
    "subject": "Weekly Sync",
    "start": "2026-09-08T09:00:00Z",
    "end": "2026-09-08T09:30:00Z",
    "timezone": "Europe/Luxembourg",
    "location": "Conference Room 2",
    "online_meeting": true,
    "attendees": [
        {
            "email": "jane.smith@example.com",
            "name": "Jane Smith",
            "type": "required"
        }
    ]
}
)
response.raise_for_status()
data = response.json()
print(data)
<?php
$context = stream_context_create([
    'http' => [
        'method'  => 'POST',
        'header'  => "Content-Type: application/json\r\nAuthorization: Bearer YOUR_TOKEN",
        'content' => '{
    \"subject\": \"Weekly Sync\",
    \"start\": \"2026-09-08T09:00:00Z\",
    \"end\": \"2026-09-08T09:30:00Z\",
    \"timezone\": \"Europe/Luxembourg\",
    \"location\": \"Conference Room 2\",
    \"online_meeting\": true,
    \"attendees\": [
        {
            \"email\": \"jane.smith@example.com\",
            \"name\": \"Jane Smith\",
            \"type\": \"required\"
        }
    ]
}',
    ],
]);

$response = file_get_contents('https://cockpit.voxbi.com/api/v1/me/calendar/events', false, $context);
$data = json_decode($response, true);
print_r($data);
Sample request
{ … }
"subject": "Weekly Sync",
"start": "2026-09-08T09:00:00Z",
"end": "2026-09-08T09:30:00Z",
"timezone": "Europe/Luxembourg",
"location": "Conference Room 2",
"online_meeting": true,
"attendees": [ … ]
{ … }
"email": "jane.smith@example.com",
"name": "Jane Smith",
"type": "required"
}
]
}
No example for this status.
{ … }
"message": "Unauthenticated."
}
Content-Type string
example: application/json
{ … }
"message": "The calendar assistant is not enabled for this account."
}
{ … }
"message": "The given data was invalid.",
"errors": { … }
"subject": [ … ]
"The subject field is required."
]
}
}
{ … }
"message": "Too Many Attempts."
}
Retry-After integer
Seconds to wait before retrying.
example: 60
Content-Type string
example: application/json