Bookings inside your product.
coss.com Scheduling is a booking API for platforms. Providers set hours and connect calendars, customers book in your app, and overlaps are refused.
How it works
For marketplaces and other platforms whose providers get booked: add them as hosts, and their customers book them in your app.
// On your server: a provider, their hours and what can be booked.
await ...({
: "tutor_482",
: "Ana Reyes",
: "ana@example.com",
: "America/New_York",
});
await ...("tutor_482", {
: [{ : [1, 2, 3, 4, 5], : "09:00", : "17:00" }],
});
const { : } = await ...({
: "Trial lesson",
: 30,
: 10,
: [{ : "tutor_482" }],
});
// When a signed-in customer wants to book: a session for their browser.
const { : } = await ...({
: !.,
: { : "customer_77", : "Sam Lee", : "sam@example.com", : "UTC" },
});
// Hand session.url to the browser.// In the browser: the booker in an iframe on your own page.
({
: ,
,
: () => {
if (. === "booked") .("Booked", .);
},
});Hosts get the same treatment: coss.scheduling.sessions.createForHost and mountHostPortal put their hours, calendars and bookings on a page in your app. To book from your own UI, list times with coss.scheduling.slots.list and book with coss.scheduling.bookings.create. See the Scheduling guide and the API reference.
A slot can't be taken twice
Double-booking is refused by the database, so it holds under races, retries and second tabs.
Every booking takes a claim on its host's time, with its buffers. A Postgres exclusion constraint, scheduling_claim_no_overlap, refuses any two claims of one host that overlap. It's the only enforcement: slot lists and re-checks just avoid asking a question it would refuse, so there's no gap between checking and writing for a booking to slip through.
When two people go for one time, one gets the booking and the other gets slot_unavailable, and you show them the times again. The same claim backs holds, pending approvals, series and group sessions. Every attempt the SDK retries carries the same Idempotency-Key, so a lost response can't book twice.
Events made outside coss.com are a different case. Something added to a host's calendar can still land on a booked time. The booking stands, coss.com never cancels on its own, and you get scheduling.booking.external_conflict.
From the team behind Cal.com
Scheduling is a hard problem we've spent years on.
coss.com Scheduling is built by the team behind Cal.com, on the same scheduling technology that has processed tens of millions of bookings there. Time zones, availability and calendar connections have already met the real world, and you get them through one API key alongside the rest of coss.com.
Everything a booking needs
Availability, calendars, the booking itself and telling people about it, on the key you already use for the rest of coss.com.
Calendars
Hosts connect Google, Microsoft or CalDAV calendars. Their busy times block slots, and bookings go on the calendar they choose. Changes arrive by push from Google and Microsoft, CalDAV is read every five minutes, and a calendar that can't be read never counts as free. See calendars.
An embeddable booker and host portal
mountBooker and mountHostPortal open coss.com's pages in an iframe in your app, under your brand name. Your API key stays on your server: a session is short-lived and reaches one thing, and only your allowed origins can embed it or call the client API. See embedding.
Your own UI, if you prefer
Every step is an API call, and a session's token also works from a browser against the client API. coss.com's own pages are built on that API, so nothing they do is out of your reach.
Holds and approvals
Hold a slot while you take payment with your own provider, then confirm it. Or set requires_approval: the time stays blocked until the host approves or declines, and a booking nobody answers is declined at its deadline. See bookings.
Pools and collective bookings
A pool books any available host, sharing bookings by weight, narrowed by attributes such as language. collective needs every required host free at once. availability.search answers who's free across up to 500 hosts, for a marketplace's search page. See pools and groups.
Group sessions
With kind: "group" and a capacity, each attendee books a seat in the same session, with a booking and manage link of their own. The host's time is taken by the first seat and given back with the last, and a full session answers slot_unavailable.
Recurring series
Book up to 52 weekly or monthly occurrences at the attendee's local time, so 10:00 stays 10:00 across a clock change. Preview first, then skip or refuse occurrences that are taken. Each is an ordinary booking that can move on its own.
Hours that hold up
Weekly hours in the host's time zone, date overrides, buffers, minimum notice, booking windows, and limits per host per day or week. Listing slots and booking both use one definition of what can be booked, so they can't disagree. See hosts and availability.
Who gets told
Attendees and hosts get emails with calendar invitations, from your own domain or from coss.com on your behalf. Attendees get a reminder a day before, by SMS too from your own number if you turn it on, and you can turn off any of them. Google Meet and Microsoft Teams links come with the calendar event. Bookings and calendars send webhooks and log lines. See notifications.
Built to hold little about people
Calendars, attendees and the events on your webhooks each carry as little as the job needs.
From calendars, coss.com stores when they're busy and nothing else: no titles, descriptions or attendees of other events. A booking goes on a host's calendar as a private event titled "Appointment", with no attendees, so their colleagues learn nothing from it.
Attendee contact details and answers are encrypted, and a booking only needs a time_zone, so you can use your own ids rather than names. Answers come back only when you retrieve one booking, never in lists, webhooks, logs, emails or calendars, and webhooks carry ids, times and statuses. coss.scheduling.attendees.erase removes someone's contact details and answers from their bookings right away.
Our Terms don't allow special categories of personal data or protected health information without a written agreement. See privacy for what's stored and for how long.
Specifications
The limits of a booking. The API reference lists each one with its field.
- Calendars
- Google, Microsoft, CalDAV
- Event type kinds
- one-on-one, pool, collective, group
- Duration
- 5 minutes to 24 hours
- Buffers
- up to 8 hours before and after
- Holds
- 10 minutes by default, 1 minute to 24 hours
- Approval deadline
- 1 day by default, up to 30 days
- Series
- up to 52 occurrences, weekly or monthly
- Group session
- 2 to 10,000 seats
- Slots per request
- up to 62 days
- Availability search
- up to 500 hosts
- Calendars read ahead
- 400 days
- Questions per event type
- 25
- Host session
- 1 hour by default, at most 24 hours
- Booker session
- 30 minutes by default, at most 24 hours
- Embedding origins
- up to 10, https
- Attendee details kept
- 90 days after the booking ends
- Bookings kept
- 395 days after the booking ends
Pricing
You pay per confirmed booking. Holds and pending approvals cost nothing until they're confirmed.
The Free plan includes 100 scheduling bookings a month. A group session is one booking however many attend, and each occurrence of a series is one. Rescheduling is free, and a cancelled booking stays charged. Booking emails sent from your own domain are billed like any email, and SMS reminders like any text message. See pricing for the plans.
Test it in a sandbox
Sandbox environments run the same code, including the double-booking guarantee and the hosted pages, and bill nothing.
With a sandbox (coss_test_…) key, emails go to the fake provider, so nobody's mailed, and the dashboard shows them with their links. Connect a simulated calendar and set its busy times with coss.scheduling.calendars.setSimulatedBusy, and test your handlers with coss trigger scheduling.booking.confirmed. See testing.
Questions
- How do I add scheduling to my app?
- Add each person who can be booked as a host with coss.scheduling.hosts.create(), give them a schedule, and create an event type. Your customers then book through the API, or in a booker you embed with mountBooker from coss/scheduling. Hosts set their hours and connect their calendars through your own UI or the host portal you embed with mountHostPortal.
- How does coss.com prevent double-booking?
- Every booking takes a claim on its host's time, buffers included, and a Postgres exclusion constraint refuses two claims of one host that overlap. That constraint is the enforcement, so two people clicking at once, a second tab or a retry can't both win. The one who loses gets slot_unavailable.
- Which calendars can hosts connect?
- Google and Microsoft through their consent screens, and CalDAV servers such as Apple's with an app-specific password. coss.com stores when each calendar is busy and adds bookings to the calendar the host chooses, as private events titled "Appointment" with no attendees. It stores no titles, descriptions or attendees of other events.
- What happens if a calendar can't be read?
- It never counts as free. By default, if access is lost the host stops being offered at once, you get a scheduling.calendar.needs_reauth webhook and the host gets an email with a link to reconnect. If a provider is having trouble, what's known keeps being used for up to seven hours, or twenty minutes for calendars without push notifications, then the host stops being offered until a read works.
- How do I take payment before a booking is confirmed?
- Hold the slot with coss.scheduling.holds.create(), charge the customer with your own payment provider, then confirm with coss.scheduling.holds.confirm(). A hold keeps the time for ten minutes by default, so nobody else can take it, and it tells nobody and isn't charged.
- Do I need to build a booking page?
- No. Your server creates a session for one event type, host or booking, and the page opens from its link or in an iframe in your app. If you'd rather build your own UI, the API and the browser client API do everything those pages do.
- What counts as a billable booking?
- One per confirmed booking, per occurrence of a series and per group session, however many people attend. Holds and pending approvals aren't charged, rescheduling is free and a cancelled booking stays charged. Sandbox environments are free, and the Free plan includes bookings every month. The pricing page has the rate.
Works with
- Emailcoss.com Email is a transactional email API. Send single, batch and scheduled email from your domains, with templates, tracking and per-recipient webhooks.
- SMScoss.com SMS is an API that sends and receives text messages from your own phone numbers, with US 10DLC and toll-free registration done for you.
- Formscoss.com Forms is a form backend. Point any HTML form at an endpoint, and every submission is screened for spam and sent to webhooks, email and contacts.
- PlatformThe coss.com platform is what every product shares. Environments and scoped keys, signed webhooks, searchable logs, dated API versions and one bill.
Start with Scheduling today.
Development keys record every request and event and deliver nothing, so you can build and test before you verify a domain. Hand your coding agent this prompt:
Add coss.com to this project: read https://coss.com/llms.txt, get a development key with `npx coss-cli init --agents`, and build and test with it.