Calendar

Calendars and events (with recurrence, attendees and replies), sharing, free/busy for people and rooms, categories, preferences, import and export, and private .ics links.

MethodPathSummary
GET/api/cal/bootstrapEverything the calendar page needs to start
PATCH/api/cal/prefsSave calendar preferences
POST/api/cal/calendarsCreate a calendar
PATCH/api/cal/calendars/:idUpdate a calendar
DELETE/api/cal/calendars/:idDelete a calendar
POST/api/cal/calendars/:id/subscriptionMake a private .ics link
DELETE/api/cal/calendars/:id/subscriptionStop a calendar's .ics link
GET/api/cal/calendars/:id/sharesWho a calendar is shared with
POST/api/cal/calendars/:id/sharesShare a calendar
DELETE/api/cal/calendars/:id/shares/:shareStop sharing a calendar with someone
GET/api/cal/peoplePeople (and groups) in your organisation, plus your own contacts
GET/api/cal/roomsList meeting rooms
POST/api/cal/freebusyBusy times for people in your organisation and rooms
POST/api/cal/calendars/:id/importImport an .ics file into a calendar (each event becomes its own entry)
GET/api/cal/calendars/:id/export.icsExport a calendar as .ics
GET/api/cal/eventsEvents in a time range
POST/api/cal/calendars/:id/eventsCreate an event
PATCH/api/cal/calendars/:id/events/:uriChange an event
DELETE/api/cal/calendars/:id/events/:uriDelete an event
GET/api/cal/categoriesList categories
POST/api/cal/categoriesCreate a category
PATCH/api/cal/categories/:idUpdate a category
DELETE/api/cal/categories/:idDelete a category

#Everything the calendar page needs to start

GET/api/cal/bootstrap

Everything the page needs to start.

Address
https://<your-org>.brambleit.cloud/mail/api/cal/bootstrap
Requires
Signed-in browser session (the sso_session / session_id cookies from Bramble sign-in).
Licence: Mail.

Response 200

FieldTypeDescription
meobject
me.namestring
me.emailstring
me.addressesarray of any
calendarsarray of any
sharedarray of any
roomsarray of any
categoriesarray of any
prefsarray of any
timezoneany
feedsarray of object
feeds[].idinteger
feeds[].oninteger
feeds[].colorinteger
davobject
dav.urlstring
dav.usernamestring
Example response
JSON
{
  "me": {
    "name": "Example name",
    "email": "alex@example.com",
    "addresses": []
  },
  "calendars": [],
  "shared": [],
  "rooms": [],
  "categories": [],
  "prefs": [],
  "timezone": null,
  "feeds": [
    {
      "id": 42,
      "…f": "…",
      "on": 1,
      "color": 1
    }
  ],
  "dav": {
    "url": "https://example.com/…",
    "username": "Example username"
  }
}

Example request

JavaScript
// From a page served by Bramble (uses the signed-in session)
const res = await fetch('/mail/api/cal/bootstrap', {
  method: 'GET',
  credentials: 'include',
});
const data = await res.json();

#Save calendar preferences

PATCH/api/cal/prefs
Address
https://<your-org>.brambleit.cloud/mail/api/cal/prefs
Requires
Signed-in browser session (the sso_session / session_id cookies from Bramble sign-in).
Licence: Mail.

Request body JSON

NameTypeDescription
viewstring: "day" | "week" | "month" | "agenda"
weekStartnumber
dayStartnumber
timezoneany
feedsobject
feedColorsobject
hiddenarray of any
roomsarray of any

Response 200

Example request

JavaScript
// From a page served by Bramble (uses the signed-in session)
const res = await fetch('/mail/api/cal/prefs', {
  method: 'PATCH',
  credentials: 'include',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({"view":"day","weekStart":12.5,"dayStart":12.5,"timezone":"…","feeds":{},"feedColors":{},"hidden":[],"rooms":[]}),
});
const data = await res.json();

#Create a calendar

POST/api/cal/calendars
Address
https://<your-org>.brambleit.cloud/mail/api/cal/calendars
Requires
Signed-in browser session (the sso_session / session_id cookies from Bramble sign-in).
Licence: Mail.

Request body JSON

NameTypeDescription
namestring
colorany
uriany

Response 200

Example request

JavaScript
// From a page served by Bramble (uses the signed-in session)
const res = await fetch('/mail/api/cal/calendars', {
  method: 'POST',
  credentials: 'include',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({"name":"Example name","color":"…","uri":"…"}),
});
const data = await res.json();

#Update a calendar

PATCH/api/cal/calendars/:id
Address
https://<your-org>.brambleit.cloud/mail/api/cal/calendars/:id
Requires
Signed-in browser session (the sso_session / session_id cookies from Bramble sign-in).
Licence: Mail.

Path parameters

NameTypeDescription
idrequiredinteger

Request body JSON

NameTypeDescription
namestring
colorany
sortany

Response 200

Example request

JavaScript
// From a page served by Bramble (uses the signed-in session)
const res = await fetch('/mail/api/cal/calendars/42', {
  method: 'PATCH',
  credentials: 'include',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({"name":"Example name","color":"…","sort":"…"}),
});
const data = await res.json();

#Delete a calendar

DELETE/api/cal/calendars/:id
Address
https://<your-org>.brambleit.cloud/mail/api/cal/calendars/:id
Requires
Signed-in browser session (the sso_session / session_id cookies from Bramble sign-in).
Licence: Mail.

Path parameters

NameTypeDescription
idrequiredinteger

Response 200

FieldTypeDescription
okboolean
Example response
JSON
{
  "ok": true
}

Example request

JavaScript
// From a page served by Bramble (uses the signed-in session)
const res = await fetch('/mail/api/cal/calendars/42', {
  method: 'DELETE',
  credentials: 'include',
});
const data = await res.json();

#Make a private .ics link

POST/api/cal/calendars/:id/subscription

The link is in the response once. Making a new one stops the old one working.

Address
https://<your-org>.brambleit.cloud/mail/api/cal/calendars/:id/subscription
Requires
Signed-in browser session (the sso_session / session_id cookies from Bramble sign-in).
Licence: Mail.

Path parameters

NameTypeDescription
idrequiredinteger

Response 200

FieldTypeDescription
urlstring
Example response
JSON
{
  "url": "https://example.com/…"
}

Example request

JavaScript
// From a page served by Bramble (uses the signed-in session)
const res = await fetch('/mail/api/cal/calendars/42/subscription', {
  method: 'POST',
  credentials: 'include',
});
const data = await res.json();

#Stop a calendar's .ics link

DELETE/api/cal/calendars/:id/subscription
Address
https://<your-org>.brambleit.cloud/mail/api/cal/calendars/:id/subscription
Requires
Signed-in browser session (the sso_session / session_id cookies from Bramble sign-in).
Licence: Mail.

Path parameters

NameTypeDescription
idrequiredinteger

Response 200

FieldTypeDescription
okboolean
Example response
JSON
{
  "ok": true
}

Example request

JavaScript
// From a page served by Bramble (uses the signed-in session)
const res = await fetch('/mail/api/cal/calendars/42/subscription', {
  method: 'DELETE',
  credentials: 'include',
});
const data = await res.json();

#Who a calendar is shared with

GET/api/cal/calendars/:id/shares
Address
https://<your-org>.brambleit.cloud/mail/api/cal/calendars/:id/shares
Requires
Signed-in browser session (the sso_session / session_id cookies from Bramble sign-in).
Licence: Mail.

Path parameters

NameTypeDescription
idrequiredinteger

Response 200

Example request

JavaScript
// From a page served by Bramble (uses the signed-in session)
const res = await fetch('/mail/api/cal/calendars/42/shares', {
  method: 'GET',
  credentials: 'include',
});
const data = await res.json();

#Share a calendar

POST/api/cal/calendars/:id/shares
Address
https://<your-org>.brambleit.cloud/mail/api/cal/calendars/:id/shares
Requires
Signed-in browser session (the sso_session / session_id cookies from Bramble sign-in).
Licence: Mail.

Path parameters

NameTypeDescription
idrequiredinteger

Request body JSON

NameTypeDescription
typestringuser or group.
idintegerThe person's or group's id.
levelanyfreebusy, read or write.

Response 200

Example request

JavaScript
// From a page served by Bramble (uses the signed-in session)
const res = await fetch('/mail/api/cal/calendars/42/shares', {
  method: 'POST',
  credentials: 'include',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({"type":"string","id":42,"level":"…"}),
});
const data = await res.json();

#Stop sharing a calendar with someone

DELETE/api/cal/calendars/:id/shares/:share
Address
https://<your-org>.brambleit.cloud/mail/api/cal/calendars/:id/shares/:share
Requires
Signed-in browser session (the sso_session / session_id cookies from Bramble sign-in).
Licence: Mail.

Path parameters

NameTypeDescription
idrequiredinteger
sharerequirednumber

Response 200

Example request

JavaScript
// From a page served by Bramble (uses the signed-in session)
const res = await fetch('/mail/api/cal/calendars/42/shares/12.5', {
  method: 'DELETE',
  credentials: 'include',
});
const data = await res.json();

#People (and groups) in your organisation, plus your own contacts

GET/api/cal/people

People (and groups) in your organisation, plus your own contacts. ?q=&groups=1&contacts=1

Address
https://<your-org>.brambleit.cloud/mail/api/cal/people
Requires
Signed-in browser session (the sso_session / session_id cookies from Bramble sign-in).
Licence: Mail.

Query parameters

NameTypeDescription
qany
groupsstring
contactsstring
roomsstring

Response 200

Example request

JavaScript
// From a page served by Bramble (uses the signed-in session)
const res = await fetch('/mail/api/cal/people', {
  method: 'GET',
  credentials: 'include',
});
const data = await res.json();

#List meeting rooms

GET/api/cal/rooms
Address
https://<your-org>.brambleit.cloud/mail/api/cal/rooms
Requires
Signed-in browser session (the sso_session / session_id cookies from Bramble sign-in).
Licence: Mail.

Response 200

Example request

JavaScript
// From a page served by Bramble (uses the signed-in session)
const res = await fetch('/mail/api/cal/rooms', {
  method: 'GET',
  credentials: 'include',
});
const data = await res.json();

#Busy times for people in your organisation and rooms

POST/api/cal/freebusy

Busy times for people in your organisation and rooms. body: { addresses: [], from: ISO, to: ISO }

Address
https://<your-org>.brambleit.cloud/mail/api/cal/freebusy
Requires
Signed-in browser session (the sso_session / session_id cookies from Bramble sign-in).
Licence: Mail.

Request body JSON

NameTypeDescription
fromany
toany
addressesarray of any

Response 200

Example request

JavaScript
// From a page served by Bramble (uses the signed-in session)
const res = await fetch('/mail/api/cal/freebusy', {
  method: 'POST',
  credentials: 'include',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({"from":"…","to":"…","addresses":[]}),
});
const data = await res.json();

#Import an .ics file into a calendar (each event becomes its own entry)

POST/api/cal/calendars/:id/import
Address
https://<your-org>.brambleit.cloud/mail/api/cal/calendars/:id/import
Requires
Signed-in browser session (the sso_session / session_id cookies from Bramble sign-in).
Licence: Mail.

Path parameters

NameTypeDescription
idrequiredinteger

Response 200

FieldTypeDescription
addedany
updatedany
failedany
Example response
JSON
{
  "added": null,
  "updated": null,
  "failed": null
}

Example request

JavaScript
// From a page served by Bramble (uses the signed-in session)
const res = await fetch('/mail/api/cal/calendars/42/import', {
  method: 'POST',
  credentials: 'include',
});
const data = await res.json();

#Export a calendar as .ics

GET/api/cal/calendars/:id/export.ics
Address
https://<your-org>.brambleit.cloud/mail/api/cal/calendars/:id/export.ics
Requires
Signed-in browser session (the sso_session / session_id cookies from Bramble sign-in).
Licence: Mail.

Path parameters

NameTypeDescription
idrequiredinteger

Response

A body.

Example request

JavaScript
// From a page served by Bramble (uses the signed-in session)
const res = await fetch('/mail/api/cal/calendars/42/export.ics', {
  method: 'GET',
  credentials: 'include',
});
const data = await res.json();

#Events in a time range

GET/api/cal/events

?from=ISO&to=ISO

Address
https://<your-org>.brambleit.cloud/mail/api/cal/events
Requires
Signed-in browser session (the sso_session / session_id cookies from Bramble sign-in).
Licence: Mail.

Query parameters

NameTypeDescription
fromrequiredanyStart (ISO date-time).
torequiredanyEnd (ISO date-time).

Response 200

FieldTypeDescription
eventsarray of any
feedsarray of any
Example response
JSON
{
  "events": [],
  "feeds": []
}

Example request

JavaScript
// From a page served by Bramble (uses the signed-in session)
const res = await fetch('/mail/api/cal/events?from=%E2%80%A6&to=%E2%80%A6', {
  method: 'GET',
  credentials: 'include',
});
const data = await res.json();

#Create an event

POST/api/cal/calendars/:id/events

With attendees, it's a meeting: colleagues get it on their calendar and an email, outside guests get an invitation email, and replies update the event.

Address
https://<your-org>.brambleit.cloud/mail/api/cal/calendars/:id/events
Requires
Signed-in browser session (the sso_session / session_id cookies from Bramble sign-in).
Licence: Mail.

Path parameters

NameTypeDescription
idrequiredinteger

Request body JSON

NameTypeDescription
attendeesarray of any
tzany

Response 200

FieldTypeDescription
uriany
etagany
Example response
JSON
{
  "uri": null,
  "etag": null,
  "…report(sched)": "…"
}

Example request

JavaScript
// From a page served by Bramble (uses the signed-in session)
const res = await fetch('/mail/api/cal/calendars/42/events', {
  method: 'POST',
  credentials: 'include',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({"attendees":[],"tz":"…"}),
});
const data = await res.json();

#Change an event

PATCH/api/cal/calendars/:id/events/:uri

Body: { ...fields, scope: 'all'|'this', recurrenceId, etag, moveTo, rsvp }

Address
https://<your-org>.brambleit.cloud/mail/api/cal/calendars/:id/events/:uri
Requires
Signed-in browser session (the sso_session / session_id cookies from Bramble sign-in).
Licence: Mail.

Path parameters

NameTypeDescription
idrequiredinteger
urirequiredstring

Request body JSON

NameTypeDescription
etaganyThe version you started from (refused if it changed).
attendeesarray of any
rsvpanyYour answer, when you're an attendee.
scopestringFor a repeating event: all or this (one occurrence, with recurrenceId).
recurrenceIdany
tzany
moveTonumberMove it to another calendar.

Response 200

FieldTypeDescription
calendarinteger
uriany
etagany
Example response
JSON
{
  "calendar": 1,
  "uri": null,
  "etag": null
}

Example request

JavaScript
// From a page served by Bramble (uses the signed-in session)
const res = await fetch('/mail/api/cal/calendars/42/events/string', {
  method: 'PATCH',
  credentials: 'include',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({"etag":"…","attendees":[],"rsvp":"…","scope":"string","recurrenceId":"…","tz":"…","moveTo":12.5}),
});
const data = await res.json();

#Delete an event

DELETE/api/cal/calendars/:id/events/:uri

?scope=this&recurrenceId=ms deletes one occurrence.

Address
https://<your-org>.brambleit.cloud/mail/api/cal/calendars/:id/events/:uri
Requires
Signed-in browser session (the sso_session / session_id cookies from Bramble sign-in).
Licence: Mail.

Path parameters

NameTypeDescription
idrequiredinteger
urirequiredstring

Query parameters

NameTypeDescription
scopestringthis with recurrenceId deletes one occurrence.
recurrenceIdany

Response 200

FieldTypeDescription
okboolean
Example response
JSON
{
  "ok": true,
  "…report(sched)": "…"
}

Example request

JavaScript
// From a page served by Bramble (uses the signed-in session)
const res = await fetch('/mail/api/cal/calendars/42/events/string', {
  method: 'DELETE',
  credentials: 'include',
});
const data = await res.json();

#List categories

GET/api/cal/categories
Address
https://<your-org>.brambleit.cloud/mail/api/cal/categories
Requires
Signed-in browser session (the sso_session / session_id cookies from Bramble sign-in).
Licence: Mail.

Response 200

Example request

JavaScript
// From a page served by Bramble (uses the signed-in session)
const res = await fetch('/mail/api/cal/categories', {
  method: 'GET',
  credentials: 'include',
});
const data = await res.json();

#Create a category

POST/api/cal/categories
Address
https://<your-org>.brambleit.cloud/mail/api/cal/categories
Requires
Signed-in browser session (the sso_session / session_id cookies from Bramble sign-in).
Licence: Mail.

Request body JSON

NameTypeDescription
idinteger
namestring
colorany

Response 200

Example request

JavaScript
// From a page served by Bramble (uses the signed-in session)
const res = await fetch('/mail/api/cal/categories', {
  method: 'POST',
  credentials: 'include',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({"id":42,"name":"Example name","color":"…"}),
});
const data = await res.json();

#Update a category

PATCH/api/cal/categories/:id
Address
https://<your-org>.brambleit.cloud/mail/api/cal/categories/:id
Requires
Signed-in browser session (the sso_session / session_id cookies from Bramble sign-in).
Licence: Mail.

Path parameters

NameTypeDescription
idrequirednumber

Response 200

Example request

JavaScript
// From a page served by Bramble (uses the signed-in session)
const res = await fetch('/mail/api/cal/categories/12.5', {
  method: 'PATCH',
  credentials: 'include',
});
const data = await res.json();

#Delete a category

DELETE/api/cal/categories/:id
Address
https://<your-org>.brambleit.cloud/mail/api/cal/categories/:id
Requires
Signed-in browser session (the sso_session / session_id cookies from Bramble sign-in).
Licence: Mail.

Path parameters

NameTypeDescription
idrequirednumber

Response 200

FieldTypeDescription
okboolean
Example response
JSON
{
  "ok": true
}

Example request

JavaScript
// From a page served by Bramble (uses the signed-in session)
const res = await fetch('/mail/api/cal/categories/12.5', {
  method: 'DELETE',
  credentials: 'include',
});
const data = await res.json();