---
title: "Booking pages"
description: "`bookings.listPages`, `getPage`, `createPage`, `updatePage`, `deletePage` and `listTimes` for the pages, and `list`, `listAll`, `iterate`, `get`, `approve`, `decline`, `cancel` and `resendEmail` for the meetings guests book on them."
url: "https://openemail.uk/docs/sdk/bookings"
area: "TypeScript"
category: "Mailbox"
---

# Booking pages

`bookings.listPages`, `getPage`, `createPage`, `updatePage`, `deletePage` and `listTimes` for the pages, and `list`, `listAll`, `iterate`, `get`, `approve`, `decline`, `cancel` and `resendEmail` for the meetings guests book on them.

## Every method

**bookings.ts**

```
const page = await openemail.bookings.createPage({
  name: 'Intro call',
  timezone: 'Europe/Berlin',
  config: {
    description: 'A first chat about your project.',
    durations: [30, 60],
    location: { kind: 'video', value: 'https://meet.example.com/hana' },
    rules: { bufferAfterMinutes: 15, dailyLimit: 4 },
    approval: true,
  },
})

console.log(page.url, page.status, page.away)

const open = await openemail.bookings.listTimes(page.id, {
  from: new Date(),
  durationMinutes: 30,
})
console.log(open.timezone, open.times.slice(0, 5))

for await (const booking of openemail.bookings.iterate({ view: 'pending', pageId: page.id })) {
  console.log(booking.guest.name, booking.guest.email, booking.start)
  if (booking.guest.email.endsWith('@example.com')) await openemail.bookings.approve(booking.id)
  else await openemail.bookings.decline(booking.id, { reason: 'This page is for customers only.' })
}

const upcoming = await openemail.bookings.list({ view: 'upcoming', limit: 10 })
const [next] = upcoming.items
if (next?.guestMailFailed) await openemail.bookings.resendEmail(next.id)
if (next) await openemail.bookings.cancel(next.id, { reason: 'Something urgent came up.' })

await openemail.bookings.updatePage(page.id, {
  status: 'paused',
  config: { busy: { outOfOffice: false } },
})
await openemail.bookings.deletePage(page.id)
```

A booking page is a public link, `page.url`, where a guest picks a free time. Only `name` is needed to create one: it opens on weekdays from 09:00 to 17:00 with 30 minute meetings. `config` holds every setting, and `updatePage` merges what you send: inside `location`, `availability`, `rules`, `appearance`, `guestChanges`, `busy` and `seo` each field is set on its own, and a list such as `durations` or `availability.weekly` is replaced whole.

`listTimes` answers the start times a guest could book, with the calendar, other bookings and out of office already taken out. `page.away` lists the out of office periods of `config.fromEmail`, which close the page unless `config.busy.outOfOffice` is false. On a page with `approval` true every booking waits as `pending` until `approve` or `decline`, and `cancel` calls off a confirmed meeting. All three email the guest.

Reading needs `calendar:read`. Every change needs `calendar:write` and `emails:send`, except `deletePage`, which needs only `calendar:write`. A page belongs to one person: an API key reaches the pages of the workspace owner, and a key limited to particular addresses is refused with 422 `capability_unsupported`.
