SapanCalDeveloper Docs

Writing events

Create, update, move and delete events on a user's calendar under your own ids.

You write events to a user's calendar under your own event id, for example your booking id. There is one call to create or update an event and one to delete it. You never need to store Google or Microsoft event ids.

Create or update an event

PUT /users/{user_id}/events/{event_id} creates the event the first time and updates it after that:

Bash
curl -X PUT https://api.bentocal.com/au/v1/users/user_123/events/booking_8812 \
  -H "Authorization: Bearer $BENTOCAL_TEST_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "summary": "Intro call",
    "description": "Booked through Example App.",
    "start": "2026-10-20T23:00:00Z",
    "end": "2026-10-20T23:30:00Z",
    "time_zone": "Australia/Sydney",
    "location": "https://meet.example.com/abc"
  }'
JSON
{
  "event_id": "booking_8812",
  "connection_id": "conn_4kT9pQ2vXa7LmN3s",
  "calendar_id": "sam@example.com",
  "provider_event_id": "5q2hb7n1k8v3c0d9"
}

The response is 201 when the event was created and 200 when it was updated. Because the same id always means the same event, it's safe to retry a request that timed out: you won't get a duplicate.

Event ids are yours to choose (1 to 255 characters; URL-encode them in the path) and are scoped to the user, so you can use the same booking id for each person attending.

Fields

FieldRequiredNotes
summaryYesThe event title, up to 1024 characters.
start, endYesISO 8601 with an offset. end must be after start.
descriptionNoUp to 8192 characters.
locationNoUp to 1024 characters, for example a meeting link.
time_zoneNoIANA time zone, for example Australia/Sydney. Calendars show the event in this zone.
all_dayNotrue for an all-day event. See below.
transparencyNoopaque (default) blocks the time in free/busy; transparent doesn't.
connection_idNoWrite to this connection instead of the user's default connection.
calendar_idNoWrite to this calendar instead of the connection's primary calendar.

BentoCal writes the event to the user's own calendar only. It doesn't invite attendees: to put a meeting in several people's calendars, write it once for each user.

Which calendar it goes to

By default an event goes to the primary calendar of the user's default connection. The default is set when the user first connects a calendar, and you can change it with PATCH /users/{user_id}.

Pass connection_id and/or calendar_id to choose another calendar. Use GET /connections/{connection_id}/calendars to find calendar ids; only calendars with can_write: true accept events.

If a later write for the same event id targets a different calendar, BentoCal moves the event there. If the user deleted the event in their calendar app, the next write creates it again.

All-day events

With all_day: true, the event covers whole days in time_zone (UTC if you leave it out):

  • It starts on the date of start.
  • An end at exactly local midnight is exclusive: 2026-10-20T00:00 to 2026-10-21T00:00 is one day, the 20th.
  • An end at any other time includes that day.
  • An all-day event always covers at least one day.
JSON
{
  "summary": "Conference",
  "all_day": true,
  "start": "2026-10-20T00:00:00+11:00",
  "end": "2026-10-22T00:00:00+11:00",
  "time_zone": "Australia/Sydney"
}

This is a two-day event on 20 and 21 October.

Delete an event

DELETE /users/{user_id}/events/{event_id} removes the event from the calendar and returns 204.

Deleting is idempotent: an event id BentoCal doesn't know, or an event already deleted in the calendar, is also a success. If the connection needs relinking, the call fails with 409 relink_required and BentoCal keeps track of the event, so you can delete it once the user reconnects.

Errors

StatusCodeCause
404not_foundThe user, connection or calendar doesn't exist.
409relink_requiredThe connection needs relinking. details.connection_id says which. See Relink a connection.
409conflictThe user has no default connection, or the connection was revoked.
403forbiddenThe provider refused the write, for example a read-only calendar.
502provider_unavailableGoogle or Microsoft failed. Safe to retry after Retry-After seconds.

See Errors for the full list.