Webhooks
Webhooks are only available for enterprise accounts.
Webhooks are a technique of programming that allows a web application to receive real-time notifications of events from another application. In other words, webhooks allow two applications to communicate with each other.
Webhooks configuration
The webhooks are available only for organizations, so the events will be triggered when something happens in a resource owned by that organization.
The webhook configuration has 2 important fields:
url: The URL that will be used to send a webhook.password(optional): This will allow webhook receivers to verify that the webhook is coming from TimeTime and not from a bad actor that discovered the webhook receiver URL. The password will be securely stored in TimeTime, and then appended as a header in each webhook delivery, the header name isX-TT-Webhook-Password.
Webhooks delivery order
TimeTime will send webhooks to your org one by one, reducing the chances of race conditions on your side. No webhooks will be sent if there is one webhook delivery in process.
Webhooks retries
TimeTime will perform 10 attempts to deliver a webhook. To allow your server recover from a temporary issue, TimeTime will apply an exponential backoff between retries. The initial delay will be 200ms, and it'll be doubling that till reaching the 10 attempts (with a maximum delay of 10 seconds).
After exhausting all the attempts, TimeTime won't try again to send this webhook, and it'll move on to the next one. Here we're making a decision in favor the "availability" over "consistency", we prefer to move one instead of "stopping the world" so your system keep receiving webhooks, at the chance of losing some of them.
TimeTime will securely store the webhook payloads, so if you missed some webhooks and really need them, contact us so we can consider retrying those ones.
Available webhooks
TimeTime offers webhooks for some events happening in the system, full list with OpenApi docs can be found here.
CalendarEventChanged: Triggered when a calendar event is created or updated.BookingChanged: Triggered when a booking is created or updated in any way, such as an status change (confirmed, canceled, etc).UpcomingBooking: Sent if "webhook" reminders are enabled in your tenant (enterprise customers only), then the webhook will be sent respecting the time configured in the event type settings.
Event type location in booking webhooks
BookingChanged and UpcomingBooking include the event type's configured location in eventType.location:
BookingChanged:new.eventType.locationand, whenoldis present,old.eventType.location.UpcomingBooking:booking.eventType.location.
The field uses the same location format as the event type API. It is null when no location is configured.
Older stored webhook payloads and booking snapshots may omit the field or contain null; receivers should accept both.
type | Additional fields | Meaning |
|---|---|---|
FixedLocation | freeText | A configured address, room, meeting URL, or other location text. |
GoogleMeetLocation | None | The event type uses Google Meet. |
MicrosoftOutlookLocation | None | The event type uses Microsoft Teams. |
BookerPhoneLocation | questionId | Identifies the question that collects the booker's phone number. |
BookerSelectionLocation | questionId | Identifies the question that collects the booker's location choice. |
This field describes the event type configuration. For a generated online meeting URL, use the booking's
conferenceLink (which can be null until the conference is created). For a phone number or location supplied
by the booker, find the entry in answeredQuestions whose id matches questionId.
Location changes after booking
eventType.location reflects the event type configuration when the booking is read. It is not a snapshot
of the location at booking creation, and editing the event type can change the location returned for existing bookings.
- In
BookingChanged,old.eventType.locationretains the configuration read immediately before the booking change.new.eventType.locationis refreshed when the webhook is processed. If the booking can no longer be loaded,newfalls back to the stored payload. - In
UpcomingBooking,booking.eventType.locationis read when the reminder is processed.
For example, if a booking is created with Room A, the event type is changed to Room B, and the booking
is then cancelled, both old and new contain Room B. If the event type changes again to Room C before
that cancellation webhook is processed, old contains Room B and new contains Room C.
These fields do not provide a history of event type location changes. Store the original location separately
if your integration needs to preserve where the appointment was booked. The booking's answeredQuestions
and conferenceLink remain booking-specific; changing a location's questionId can mean it no longer matches
an answer collected for an earlier booking.
Location examples
Each example below is a booking fragment, showing only the fields needed to find the location.
In BookingChanged, these fields are inside new and, when present, old.
In UpcomingBooking, they are inside booking. See the webhook payload examples
for the surrounding structure.
Fixed address or room
Read the address from eventType.location.freeText.
{
"eventType": {
"location": {
"type": "FixedLocation",
"freeText": "Sala 4, Calle Mayor 123, Madrid"
}
},
"conferenceLink": null,
"answeredQuestions": []
}
Fixed meeting URL
A manually configured meeting URL is also a FixedLocation. Read it from freeText;
conferenceLink can be null because no conference needs to be generated.
{
"eventType": {
"location": {
"type": "FixedLocation",
"freeText": "https://video.example.com/consultation"
}
},
"conferenceLink": null,
"answeredQuestions": []
}
Google Meet
The location type identifies the provider. Read the generated join URL from conferenceLink.
{
"eventType": {
"location": {
"type": "GoogleMeetLocation"
}
},
"conferenceLink": "https://meet.google.com/abc-defg-hij",
"answeredQuestions": []
}
Microsoft Teams
MicrosoftOutlookLocation identifies a Microsoft Teams meeting. The join URL is in conferenceLink.
{
"eventType": {
"location": {
"type": "MicrosoftOutlookLocation"
}
},
"conferenceLink": "https://teams.microsoft.com/l/meetup-join/example",
"answeredQuestions": []
}
The URLs in these examples are illustrative.
Conference link not available yet
A booking webhook may arrive before the meeting URL has been generated. The location still identifies
the provider, while conferenceLink is null. This also applies to Microsoft Teams and online meetings
selected by the booker.
{
"eventType": {
"location": {
"type": "GoogleMeetLocation"
}
},
"conferenceLink": null,
"answeredQuestions": []
}
Phone call
Match eventType.location.questionId to an answeredQuestions[].id, then read that entry's answer
for the phone number. Question IDs can be customized; use the ID from the payload.
{
"eventType": {
"location": {
"type": "BookerPhoneLocation",
"questionId": "phone"
}
},
"conferenceLink": null,
"answeredQuestions": [
{
"id": "phone",
"label": "Phone number",
"answer": "+34910000000"
}
]
}
Booker chooses the location
BookerSelectionLocation identifies the question used to choose a location. Match its questionId
to an answeredQuestions[].id. The webhook serializes the selected answer as human-readable text.
For an online choice, read the join URL from conferenceLink.
The following fragments show each supported choice.
In person
{
"eventType": {
"location": {
"type": "BookerSelectionLocation",
"questionId": "meeting-location"
}
},
"conferenceLink": null,
"answeredQuestions": [
{
"id": "meeting-location",
"label": "Where would you like to meet?",
"answer": "Sala 4, Calle Mayor 123, Madrid"
}
]
}
Google Meet
{
"eventType": {
"location": {
"type": "BookerSelectionLocation",
"questionId": "meeting-location"
}
},
"conferenceLink": "https://meet.google.com/abc-defg-hij",
"answeredQuestions": [
{
"id": "meeting-location",
"label": "Where would you like to meet?",
"answer": "Google Meet"
}
]
}
Microsoft Teams
{
"eventType": {
"location": {
"type": "BookerSelectionLocation",
"questionId": "meeting-location"
}
},
"conferenceLink": "https://teams.microsoft.com/l/meetup-join/example",
"answeredQuestions": [
{
"id": "meeting-location",
"label": "Where would you like to meet?",
"answer": "Teams meeting"
}
]
}
Phone call
{
"eventType": {
"location": {
"type": "BookerSelectionLocation",
"questionId": "meeting-location"
}
},
"conferenceLink": null,
"answeredQuestions": [
{
"id": "meeting-location",
"label": "Where would you like to meet?",
"answer": "Booker phone"
},
{
"id": "phone",
"label": "Phone number",
"answer": "+34910000000"
}
]
}
For the phone choice, "Booker phone" is the selected option. The number is collected through a separate
phone question (phone in this example); use the phone question ID configured for your event type.
If a fixed-location choice has no address, its answer is "Fixed location". An unanswered question can have
"answer": null.
No configured location
When the event type has no configured location, eventType.location is explicitly null.
{
"eventType": {
"location": null
},
"conferenceLink": null,
"answeredQuestions": []
}
Older payload without the field
Previously stored payloads may omit location entirely. Treat a missing field as an unknown location;
it does not prove that the event type has no location configured.
{
"eventType": {
"id": "ed19c788-e869-4de4-81ec-ec0d2ba748cf",
"name": "Consultation"
},
"conferenceLink": null,
"answeredQuestions": []
}
Webhook payload examples
BookingChanged
When a booking is created, old is null. On subsequent changes, old contains the previous booking
state, including the event type configuration read before that change when available. Read the configuration
at webhook processing time from new.eventType.location; neither field preserves the location at booking creation.
See location changes after booking.
{
"type": "BookingChanged",
"new": {
"id": "90b33f62-0347-4ad8-b63a-88eab21df3ee",
"eventType": {
"id": "ed19c788-e869-4de4-81ec-ec0d2ba748cf",
"name": "Reunión con Odín del Río Piñeiro",
"owner": {
"type": "BookedEventTypeOwnerUser",
"id": "54330e53-e9b9-430c-a417-7efaa87f39f7",
"email": "odin@timetime.in",
"externalId": null
},
"tags": {},
"location": {
"type": "FixedLocation",
"freeText": "Sala 4, Calle Mayor 123, Madrid"
}
},
"interval": {
"start": "2025-01-19T11:45:00Z",
"end": "2025-01-19T11:55:00Z"
},
"booker": {
"email": "odin+booker@timetime.in"
},
"answeredQuestions": [
{
"id": "tt_booker_email",
"label": "Correo electrónico",
"answer": "odin+booker@timetime.in"
},
{
"id": "8f3e67b3-c381-4fb0-8197-dc53f73aa633",
"label": "Nombre",
"answer": "odinnn test"
}
],
"notes": "",
"units": 1,
"cancellation": null,
"bookedResources": [],
"conferenceLink": null,
"privateNotes": [],
"status": "CONFIRMED",
"price": null,
"confirmedAt": "2025-01-19T11:42:32.234713Z",
"heldUntil": null
},
"old": null
}
UpcomingBooking
Read the location from booking.eventType.location. This webhook has no new or old fields.
{
"type": "UpcomingBooking",
"booking": {
"id": "90b33f62-0347-4ad8-b63a-88eab21df3ee",
"eventType": {
"id": "ed19c788-e869-4de4-81ec-ec0d2ba748cf",
"name": "Reunión con Odín del Río Piñeiro",
"owner": {
"type": "BookedEventTypeOwnerUser",
"id": "54330e53-e9b9-430c-a417-7efaa87f39f7",
"email": "odin@timetime.in",
"externalId": null
},
"tags": {},
"location": {
"type": "FixedLocation",
"freeText": "Sala 4, Calle Mayor 123, Madrid"
}
},
"interval": {
"start": "2025-01-19T11:45:00Z",
"end": "2025-01-19T11:55:00Z"
},
"booker": {
"email": "odin+booker@timetime.in"
},
"answeredQuestions": [
{
"id": "tt_booker_email",
"label": "Correo electrónico",
"answer": "odin+booker@timetime.in"
},
{
"id": "8f3e67b3-c381-4fb0-8197-dc53f73aa633",
"label": "Nombre",
"answer": "odinnn test"
}
],
"notes": "",
"units": 1,
"cancellation": null,
"bookedResources": [],
"conferenceLink": null,
"privateNotes": [],
"status": "CONFIRMED",
"price": null,
"confirmedAt": "2025-01-19T11:42:32.234713Z",
"heldUntil": null
}
}
CalendarEventChanged
Calendar events expose their own new.locations array. They do not contain an eventType.location field.
{
"type": "CalendarEventChanged",
"new": {
"id": "5934c6a5-6f01-4223-8b4d-308af18be8dc",
"calendarId": "ae0e1585-a169-4e0a-bc8a-5a7a4ce7e62b",
"interval": {
"inclusiveStart": {
"dateTime": "2024-03-20T15:00:00+01:00",
"timeZone": "Europe/Madrid"
},
"exclusiveEnd": {
"dateTime": "2024-03-20T16:00:00+01:00",
"timeZone": "Europe/Madrid"
}
},
"status": "CONFIRMED",
"summary": "Some event",
"description": "Some event description",
"attachments": [],
"locations": [],
"attendees": [
{
"id": "460b4f91-87f8-4c03-8724-80a651e56976",
"invitation": {
"id": "27de4f27-46fb-4899-8ad4-bce8f3349afe",
"displayTimeMode": "EXACT",
"summary": "You have been invited to an event",
"subtitle": "Please accept or decline the invitation.",
"description": "Some invitation description"
},
"status": "ACCEPTED",
"organizer": false,
"email": "someone@example.com",
"displayName": null,
"comment": null,
"managementUrl": "https://app.timetime.in/i/27de4f27-46fb-4899-8ad4-bce8f3349afc"
}
],
"comments": [
"comment 1",
"comment 2 🤣"
],
"tags": {
"tag 1": "grande"
}
},
"semanticDiff": []
}