OwnerRez has an API, which is available to any user or third party who needs to communicate with our software programmatically. Learn more how to authenticate with our API or how to build an OAuth based "app" that others can connect to for your brand.
Webhooks are only available for OAuth-authenticated apps.
Once you create an app, you'll need to use "webhooks" to receive updates from OwnerRez automatically when certain entities change.
- What is a webhook?
- Consuming a webhook
- The webhook data format
- What do I do with this data?
- Securing your webhook
- Debugging your webhook
- Keeping track of block/bookings over time
- Important gotchas
- Failure Policy
What is a webhook?
A webhook (also called a web callback or HTTP push API) is a way for an app to provide other applications with real-time information. A webhook delivers data to other applications as it happens, meaning you get data immediately. Unlike typical APIs where you would need to poll for data very frequently in order to get it close to real-time. This makes webhooks much more efficient for both provider and consumer.
Webhooks are sometimes referred to as "Reverse APIs," as they give you what amounts to an API spec, and you must design an API for the webhook to use. The OwnerRez webhook will make an HTTP request to your app (as a POST), and you will then be charged with interpreting it.
Consuming a webhook
The first step in consuming the OwnerRez webhook is to give us the URL where you want requests delivered to. This is done by setting the "URL" field under the Webhooks section of your OAuth app inside the Developer/API settings page in your OwnerRez account.
This means that you also need to set up a URL in your app that’s accessible from the public web so that OwnerRez can reach out, across the internet, and make requests to the URL.
You can also subscribe per connection with POST /v2/webhooksubscriptions (see OAuth Apps). Both are delivered. If your app's settings and a subscription cover the same event for the same account, you receive it twice, once at each URL. Use one or the other.
Along with the URL itself, you'll need to also set a User and Password value that we'll use to securely make the request so other anonymous requests don't get through. This will make sure only OwnerRez is able to make requests to your URL and no one else.
Your application should respond to webhooks from OwnerRez with a http code in the 2xx range if there are no problems consuming the webhook.
The webhook data format
Webhooks are sent as POST requests over HTTP with the payload formatted as JSON in the request body.
{
"id": "3f6e2a8c-1b7d-4c55-9e0a-6d2f8b1c4a70",
"user_id": 56789,
"action": "entity_update",
"entity_type": "property",
"entity_id": 12345,
"categories": ["descriptions"],
"entity": {
"property": "value"
}
}
The payload is made up of 7 fields, though others may be added at a later date. Your code should be designed to ignore fields you have not implemented so that updates to this format do not cause your application to fail.
Fields
| Name | Value Type | Description |
|---|---|---|
| id | GUID | A unique identifier for this delivery. A retry of the same delivery carries the same id, so use it to drop duplicates. It is not the record's id; that's entity_id. |
| user_id | Integer | The unique identifier of the user on which the event or action occurred. |
| action | String | The event or action that occurred, limited to the list below. |
| entity_type | String | The type of record that was modified, limited to the list below. For "entity_..." actions only. |
| entity_id | Integer | The unique identifier of the record that was modified. For "entity_..." actions only. |
| categories | Array | Strings representing the parts of the record that were changed. Only included if entity_type is present. |
| entity | Object |
An object representing the record, the same object you would receive from the API for |
The application_authorization_revoked webhook carries only id, user_id and action. user_id is the same value returned in the token response when the host authorized your app.
Actions
The following actions are supported:
entity_createentity_updateentity_deleteapplication_authorization_revokedwebhook_test
Entity Types
There are many different entity types that may appear. Currently, the following entity types are supported:
api_applicationbookingguestinquirypropertyquotethread_messagesurcharge
Surcharge and discount webhooks both use entity_type surcharge; a discount is a surcharge with a negative amount. Turn them on separately in your app's webhook settings.
Over time, this list will grow as new entity types are supported. All types other than api_application may be enabled or disabled in your application configuration within OwnerRez.
Webhook Categories
To limit how often you need to get updates, some entities also include a category depending on the type of entity that the webhook is for. This is so that you know what part of the entity changed, not just that the entity changed overall. For instance, bookings, as well as financial transactions and other information, can change over time. Or properties are quite large and include listing content (amenities, photos, descriptions) as well as rules and other information. It's helpful to know that amenities changed but not photos.
Non-Category Entities
The following entity types don't provide categories with webhooks:
api_applicationinquiryquotethread_message
Booking Categories
Currently, the following categories are supported for booking webhooks:
agreementavailabilitycanceledchargedatesdoorcodefinancialnotespaymentpropertytimetransaction
Guest Categories
Currently, the following categories are supported for guest webhooks:
info
Property Categories
Currently, the following categories are supported for property webhooks:
ratessurchargestaxesrulesavailabilitydescriptionslocationroomsphotos
What do I do with this data?
The payload described above contains all the information about a record, the same as if you were to query the API for that record. Our webhook client will wait up to 4 seconds for confirmation (HTTP status code 200-299) from your server before considering the webhook failed.
Failed webhooks are retried up to 10 times, with growing gaps, over about 4 hours. A retry sends the same payload as the first attempt, so a retried webhook can describe the record as it was hours ago. If a newer webhook for the same record already arrived, keep the newer one (compare updated_utc), or fetch the record when the order matters to you.
We recommend storing the webhook payloads you are interested in somewhere in your application and using a separate process to parse and handle them. This way, processing errors or timeouts do not cause a backlog of webhooks to your application.
Securing your webhook
Because our webhooks deliver data to publicly available URLs in your application, there’s the chance that someone else could find that URL and then provide you with false data. To prevent this from happening, you should employ a couple of techniques. First, force TLS connections (https). Second, implement basic authentication and provide a unique username and password to OwnerRez on your OAuth app configuration page.
Debugging your webhook
The simplest way to test your webhook is to use the "Send a Test Webhook" button within OwnerRez. This will send your application a webhook that looks like this:
{
"id": "3f6e2a8c-1b7d-4c55-9e0a-6d2f8b1c4a70",
"user_id": 56789,
"action": "webhook_test",
"entity_type": "api_application",
"entity_id": 12345
}
(The user_id and entity_id values will be your user identifier and the identifier of your OAuth application.)
If there are any problems with authentication, or if your application responds with a non-2xx HTTP code for any reason, the webhook will fail. This will be shown in OwnerRez on the webhooks list. You can find more information about the failure by clicking on the "Data" column.
Keeping track of blocks/bookings over time
If your app tracks bookings, load them once and then apply webhooks. Keeping Availability in Sync covers this end to end: which webhooks to subscribe to, what each booking type and status means, which entries to wait on, and how to catch up after a gap. The short version:
- Load once. On connection, pull bookings with
GET /v2/bookings. - Handle all three actions.
entity_createfor new entries,entity_updatefor changes and cancellations,entity_deletefor deletions. - Use
type, notis_block.typeisbooking,owner,block,quote_holdorlinked_availability.is_blockis deprecated. - A block can become a booking. Channel holds and quote holds turn into the booking with the same id, as an
entity_update. A booking never turns back into a block. - Watch
status.pendingmeans the dates are held but the stay isn't confirmed. Wait foractivebefore scheduling cleanings or messaging guests. A canceled entry can be reactivated, which arrives as anotherentity_update. - Deletes happen. Hosts can delete blocks, and OwnerRez deletes temporary blocks, such as the ones it adds while an Airbnb date change or a linked property's booking is processed, when they're no longer needed. Deleting a quote deletes its quote hold. A channel hold normally isn't deleted: it becomes the booking. A deleted record never comes back.
Important gotchas
- Retries end. After 10 retries over about 4 hours, a webhook is dropped. If your endpoint was down longer, catch up with
GET /v2/bookings?since_utc=…(see Catching up after a gap). - Duplicates. A retry after your app processed the payload but returned an error is a duplicate. Drop payloads whose
idyou've already processed. - Order isn't guaranteed. A retry can arrive after a newer webhook for the same record.
- Your own changes come back. A record your app creates or updates through the API is sent to you as a webhook.
- Deletes for unknown ids. You can get a delete for a record you never saw, for example a block created and deleted within seconds. Ignore it.
- Volume. One host's bulk edit can send hundreds of webhooks at once. Store payloads and process them separately so your endpoint keeps answering within 4 seconds.
- Revoked access.
application_authorization_revokedmeans the host removed your app. Stop calling the API for thatuser_id. It is sent to your app's webhook URL only, not to per-connection subscriptions. - 410 unsubscribes. If a per-connection subscription's URL answers
410 Gone, OwnerRez deletes that subscription. If your app has "Send me a notification when a user webhook subscription is canceled automatically" turned on, OwnerRez also emails the account that owns your app, with a copy to the app's Additional Contact Email. Your app's webhook URL is never unsubscribed this way. - Empty fields are left out. Payloads use the API's JSON format, so a field with no value is omitted. See Response Format.
Failure Policy
OwnerRez pauses your app's webhooks when your endpoints fail too often: 100 or more deliveries within about an hour, with half or more failing. A failure is an error status code, a timeout (no answer within 4 seconds) or a connection error. Retries count as deliveries.
The pause covers your whole app: every connected account, per-connection subscriptions, and your app's webhook URL. When it happens:
- The account that owns your app receives an email stating that webhooks are paused, with a copy to the app's Additional Contact Email.
- Nothing is sent while paused, and nothing from the paused period is sent later, including retries that were waiting.
- Webhooks remain paused until you resolve the issue and click Re-enable Webhooks on your app's page under Developer/API settings.
After re-enabling, catch up on what you missed with GET /v2/bookings?since_utc=<5 hours before the pause started>, because retries that were waiting when the pause started were dropped too. See Catching up after a gap.

