Sync bookings
Copy Bridge bookings into your CRM, database or spreadsheet, and keep them up to date as people book, reschedule and cancel.
This guide shows how to keep a copy of your workspace's bookings in another system. You load every booking once, then check for changes every few minutes.
You need an API key with Read access. See Authentication.
How it works
Every booking has an updated_at time. It changes when the booking is created, rescheduled, cancelled or given a different host. To find what changed since your last sync, ask for bookings updated after that time:
curl -G https://api.meetonbridge.com/v1/bookings \
-H "Authorization: Bearer $BRIDGE_API_KEY" \
--data-urlencode "after_updated_at=2026-10-28T09:00:00Z" \
-d sort_by=updated_at \
-d order=asc \
-d take=100
Cancelled bookings are included, so you see cancellations as well as new bookings.
Set up the sync
Load every booking once
Request GET /bookings with sort_by=updated_at, order=asc and take=100, with no after_updated_at. Increase skip by 100 until pagination.has_more is false. See Pagination.
Save each booking by its id
Use the booking id as the key in your system. If a booking with that id exists, replace it. If not, add it. Getting the same booking twice is then harmless.
Save a checkpoint
Before each run starts, note the current time. When the run finishes, save that time minus 5 minutes as your checkpoint. The 5 minutes covers bookings that change while the run is in progress, and small clock differences.
Check for changes on a schedule
Every few minutes, run the same request with after_updated_at set to your checkpoint. Save each booking by id, then save the new checkpoint.
Here is a complete sync in JavaScript. Run it on a schedule, such as every 5 minutes:
const API = "https://api.meetonbridge.com/v1";
const headers = { Authorization: `Bearer ${process.env.BRIDGE_API_KEY}` };
async function syncBookings(checkpoint) {
const runStartedAt = new Date();
let skip = 0;
let hasMore = true;
while (hasMore) {
const params = new URLSearchParams({ sort_by: "updated_at", order: "asc", take: "100", skip: String(skip) });
if (checkpoint) params.set("after_updated_at", checkpoint);
const response = await fetch(`${API}/bookings?${params}`, { headers });
if (response.status === 429) {
const wait = Number(response.headers.get("RateLimit-Reset") ?? 60);
await new Promise((resolve) => setTimeout(resolve, wait * 1000));
continue;
}
const body = await response.json();
if (body.status !== "success") throw new Error(body.error.message);
for (const booking of body.data) {
await saveBooking(booking);
}
hasMore = body.pagination.has_more;
skip += 100;
}
return new Date(runStartedAt.getTime() - 5 * 60 * 1000).toISOString();
}
saveBooking is your own function that adds or replaces the booking in your system. Store the value syncBookings returns and pass it in on the next run. Pass nothing on the first run.
What changes look like
| Change | What you see |
|---|---|
| New booking | A booking you haven't seen before, with status set to confirmed. |
| Rescheduled | The same id with a new start and end. rescheduled_at shows when it moved. |
| Cancelled | The same id with status set to cancelled. cancellation shows when, who cancelled (invitee, host or calendar) and the reason. |
| New host | The same id with a different hosts list. |
Fields worth syncing
| Field | What it holds |
|---|---|
attendee | The person who booked: name, first_name, last_name, email, timezone and phone. |
guests | Email addresses of anyone else the attendee invited. |
responses | Answers to the booking page's questions. Each item has the question as it was worded when the person booked, its type and the answer. |
sms_consent | Whether the attendee agreed to text messages, and when. null when no phone number was given. |
location | type (bridge, in_person or none), the address and maps_url for in-person meetings, and the meeting_url for Bridge meetings. |
utm | UTM tags from the booking link, such as utm_source and utm_campaign. |
booking_page | The id and name of the page the booking came from. |
Questions keep the wording they had when the person booked. If you later rename a question on the booking page, older bookings still show the old wording.
Tips
- To sync one booking page only, add
booking_page_idto the request. - To skip cancelled bookings during the first load, add
status=confirmed. Keep cancelled bookings in the scheduled check so you see cancellations. - Checking every 5 minutes uses a few requests. Each key can make 120 requests per minute. See Rate limits.