Event-based webhook flow
Introduction
The webhook event-based flow for restaurant reservations and customer management allows integration between TheFork system and your CRM system. This integration enables real-time communication of events such as customer creation, customer update, reservation creation, and reservation update. This comprehensive documentation outlines the steps required to activate and utilize these features effectively.
Activation process
To activate the webhook feature, follow these steps:
- Provide Endpoint: create a RESTful POST endpoint on your CRM system with a custom URL and a token.
Example:https://data.myrestaurant.com/api/thefork?token=NN8ul7c3wRE0hYP2XPOhyYDRQnyHFMJq - Token Generation: generate a token of your choice to include in the endpoint URL.
- Inform TheFork: provide the generated endpoint URL with the token to TheFork system for configuration.
Webhook payload
Upon activation, TheFork system will send payload data to your provided endpoint.
Common fields
All webhook payloads include the following fields:
entityType: identifies the type of entity that was created or updated (customer,reservation, orreview).uuid: unique identifier (UUID) of the entity, necessary for retrieving the latest data from TheFork API.eventType: indicates the specific action performed (see details below for each entity type).
Based on the entity type, the payload can include additional fields.
Customer
Fields
entityType: Alwayscustomeruuid: Unique identifier of the customereventType:customerCreatedorcustomerUpdatedgroupUuid: Unique identifier of the associated restaurant group
Example
{
"entityType": "customer",
"eventType": "customerCreated",
"uuid": "d7b2f4a1-3c8e-4f5d-9a2b-1e6c8f3d5a7b",
"groupUuid": "c1fa3225-690d-4b86-b255-042b3c218b68"
}
Reservation
Fields
entityType: Alwaysreservationuuid: Unique identifier of the reservationeventType:reservationCreatedorreservationUpdatedgroupUuid: Unique identifier of the associated restaurant grouprestaurantUuid: Unique identifier of the associated restaurant
Example
{
"entityType": "reservation",
"eventType": "reservationCreated",
"uuid": "a288660b-94e9-4702-936f-9c7caec0cdd4",
"groupUuid": "c1fa3225-690d-4b86-b255-042b3c218b68",
"restaurantUuid": "565426e9-a7d9-4123-8d9b-94275483fcf9"
}
Review
Fields
entityType: Alwaysreviewuuid: Unique identifier of the revieweventType: One of the following:reviewRatingCreated: Sent when a new rating is submitted (with or without a pending comment).reviewCommentPublished: Sent when a guest's comment is officially published.reviewCommentUnpublished: Sent when a comment has been published and pending moderation or has been unpublished.reviewValidityChanged: Sent rarely, typically when a user requests data deletion (GDPR compliance).
groupUuid: Unique identifier of the associated restaurant grouprestaurantUuid: Unique identifier of the associated restaurantreservationUuid: Unique identifier of the associated reservation
Example
{
"entityType": "review",
"eventType": "reviewRatingCreated",
"uuid": "69724c5f-6316-4e7d-b178-dac6c6249bd1",
"groupUuid": "c1fa3225-690d-4b86-b255-042b3c218b68",
"restaurantUuid": "565426e9-a7d9-4123-8d9b-94275483fcf9",
"reservationUuid": "1b3df5cc-56f9-4aca-a905-d858c41992fe"
}
Event flow
The following diagram illustrates how review events flow through the system:
Handling Webhook Events
Upon receiving a webhook event, your CRM system should perform the following actions:
- Acknowledge Request Immediately: respond to the webhook event with a 200 HTTP status code and an empty JSON response to acknowledge successful reception. This must be done as quickly as possible (within a few seconds) to prevent timeouts and automatic retries from TheFork system.
{
"data": {}
}
-
Process Event Asynchronously: after acknowledging the request, parse the received payload to extract relevant information such as entity type, UUID, and event type. This processing should happen asynchronously (e.g., via a background job or message queue) to avoid blocking the webhook response.
-
Filter Known Events (Forward Compatibility):
- Your integration should check the
entityTypeandeventTypebefore processing. - If your system receives an
entityTypeoreventTypeit does not recognize (e.g., a new feature added by TheFork), simply ignore the event and skip further processing. - This ensures your integration remains compatible as TheFork adds new event types in the future.
- Your integration should check the
-
Retrieve Latest Data: utilize the UUID provided in the payload to call TheFork API (
GET /reservations/{id},GET /customers/{id}, orGET /reviews/{id}) and fetch the latest data for the corresponding entity.
Always acknowledge the webhook request immediately upon receipt, before performing any additional processing like API calls or database operations. This ensures TheFork receives confirmation that your endpoint is reachable and functioning, preventing unnecessary retries.
Once you respond with a 200 OK, TheFork considers the webhook successfully delivered and will not retry. If your system encounters an error during asynchronous processing (e.g., database failure, API call error), you are responsible for handling it. We recommend:
- Implementing your own retry mechanism or message queue with dead-letter handling
- Logging failed events for manual review or reprocessing
- Using the TheFork API to fetch the latest data if an event was missed
Error Handling
In case of errors encountered during webhook event processing, your CRM system should handle them appropriately. TheFork system manages the following error scenarios:
- Restaurant Group Configuration Error (
RESTAURANT_GROUP_NOT_READY):
- Status code: 400
- Error Identifier:
RESTAURANT_GROUP_NOT_READY - Message: "The restaurant group needs to accept TheFork ERB in the tool"
- Response Format:
{
"error": "RESTAURANT_GROUP_NOT_READY",
"message": "The restaurant group needs to accept TheFork ERB in the tool",
"data": {}
}
- Rate Limit Exceeded (
RATE_LIMIT):
- Status code: 429
- Error Identifier:
RATE_LIMIT - Message: "You have reached the maximum number of requests per minute"
- Response Format:
{
"error": "RATE_LIMIT",
"message": "You have reached the maximum number of requests per minute",
"data": {}
}