OAuth Apps let you create an app that can be granted permission to access other users accounts. We support two OAuth 2 user-authorization grants: the Authorization Code Grant: RFC 6749-Section 4.1 (web application flow), and the Device Authorization Grant (RFC 8628). If you only need to access your own account or are looking for a Client Credentials Grant-type flow, use a Personal Access Token instead.
- Setting up a new OAuth App
- Authorizing Users
- Authorizing Devices
- Revoking Access
- Handling User Revoked Access via Webhooks
- Getting Notified when Entities Change via Webhooks
- Updating the Webhook URL
- Common Issues & Questions
Setting up a new OAuth App
First, contact us at partnerhelp@ownerrez.com and let us know what you're building! We love hearing about new apps and scenarios using OwnerRez.
Then, go to Developer/API Settings in the dropdown arrow at the top-right of your OwnerRez screen, and create an app. Required fields:
| Fields | Information |
|
Name your app something recognizable to your users -- this will be shown during authorization. |
|
The link to your public homepage, or preferably a landing page describing how your app integrates with OwnerRez. |
| OAuth Redirect URL |
|
| Webhook URL/User/Password | The public URL where updates will be sent to your app from OwnerRez when the application is revoked by the user or when entities (eg, bookings, guests) are updated. This URL must start with https://. The user/password will be sent using basic authentication. |
| OAuth API scope | The scope of access for the API token. Choose either "Full" for access to all endpoints, or "Read" for GET requests only by limiting the scope to GET endpoints. Note that if you select "Read", you will not be able to create read & write tokens later. |
| Token expiration policy | Choose the recommended "Standard" (tokens expire in thirty days). |
You can also set a description and logo to further identify your app.
When you create your app, you'll be given a client secret starting with s_. Record this as you won't be able to access it again. If you need to, you can always regenerate a new secret for your app.
Authorizing Users
The flow to authorize users for your app is:
- Your app sends users to OwnerRez to request authorization
- Users are redirected back to your site by OwnerRez with a temporary code
- Your app exchanges the temporary code for an access token
- Your app accesses the OwnerRez API with the user's access token
- Grant Access to yourself
- Refreshing Tokens
⚠️ OwnerRez is currently phasing out permanent tokens, and all permanent tokens will be revoked in the future. We will notify you before this occurs.
This process follows the OAuth 2 Authorization Code Grant spec: RFC 6749-Section 4.1.
1) Request a user's authorization
To request user authorization, send the user to the OwnerRez OAuth App authorization URL https://app.ownerrez.com/oauth/authorize with the following parameters:
For example:
https://app.ownerrez.com/oauth/authorize?response_type=code&client_id=c_foobar
2) Users are redirected back to your site
After the user approves or rejects your request, OwnerRez redirects back to your site using the redirect_uri parameter you provided in step 1 or the Redirect URL from your app configuration if no redirect was provided in step 1.
If the user successfully authorized your application, we'll send back a temporary code in the code parameter as well as the state you provide in step 1 in the state parameter. The temporary code will expire after 10 minutes. If the state doesn't match the state you originally provided, then a third party altered the request and you should abort the process.
For example:
https://acmeapp.com/path/to?code=tc_12345&state=mystate
If the user declined to authorize your application or if some other error occurred, we'll send back error details in the error and error_description parameters. error is a machine readable string such as redirect_uri_mismatch or access_denied. error_description is optional and if specified will contain a human readable error message.
For example:
https://acmeapp.com/path/to?error=access_denied&error_description=The+user+denied+you+access
3) Exchange the temporary code for an access token
Once you have the temporary code from step 2, you can convert it into an Access Token by sending a POST request to the /oauth/access_token endpoint.
Temporary codes are valid for only 10 minutes and must be upgraded to an Access Token before they expire. Temporary codes can only be used once. If it's been more than 10 minutes or the code has been used, any subsequent requests will generate an error.
To exchange a temporary code for an Access Token, make a POST to the https://api.ownerrez.com/oauth/access_token endpoint using basic authentication where the username is the Client ID of your OAuth App and the password is the Client Secret of your OAuth app. Send the following parameters using the "application/x-www-form-urlencoded" format:
| Name | Description |
|---|---|
| grant_type | Required. Must be "authorization_code". |
| code | Required. The code you received as a response to Step 1. |
| redirect_uri | The URL in your application where users are sent after authorization, if sent in Step 1 -- must match exactly if sent. |
| code_verifier | Required if you sent a code_challenge in step 1: the original code_verifier. |
Here's an example curl:
curl -u c_foo:s_bar -d code=tc_baz -d grant_type=authorization_code -i -X POST https://api.ownerrez.com/oauth/access_token
The response will be JSON and include the resulting access_token and user_id. For example:
{
"access_token" : "at_foobarbaz",
"token_type" : "bearer",
"scope" : "full",
"user_id": 123456
}
In the case of a failure, the response will be a 400 status code and include JSON with error and (optionally) error_description attributes. For example:
{
"error" : "invalid_grant",
"error_description" : "It's been too long."
}
4) Access the OwnerRez API
Once you have a user's access token, use bearer token auth to access the API, as outlined in the Authentication guide.
5) Grant Access to yourself
Self-use access for your own OAuth app is allowed and includes the Reviews, Listings, and Messages endpoints, with no premium or partnership agreement required. Partnership agreements are required for apps accessing other OwnerRez users' accounts.
If you're connecting your own OAuth app to your own account, add yourself as a User to your app to receive webhooks (especially Messaging) for your account by clicking the Users tab → Grant Access To Me button.
6) Refreshing Tokens
Depending on your configuration, your tokens may expire after thirty days.
Whether tokens expire depends on your app's token expiration policy. Under the "Standard" policy (recommended), access tokens expire after 30 days and include a refresh token -- see Refreshing Tokens below. Under the legacy "None" policy, tokens don't expire unless deleted or revoked. However, permanent tokens are being phased out, and all tokens will eventually require expiration.
To keep your token up to date, repeat your post request to https://api.ownerrez.com/oauth/access_token with the body:
grant_type=refresh_token
refresh_token=rt_...
Store and use your new access and refresh tokens.
Note that attempting to refresh tokens that are not on the "Standard" expiration policy will result in an error. All token responses include refresh_token_supported an indication of whether the token can be refreshed. If you wish to convert an existing permanent token into a refresh token, and you can do so by submitting a POST request oauth/token with a grant_type of token_upgrade.
You may refresh your tokens after they have expired. Expired access tokens return HTTP 401 with WWW-Authenticate: Bearer error="token_expired" on API calls, but the refresh endpoint accepts a valid refresh token regardless.
POST to /oauth/token works interchangeably with oauth/access_token.
Authorizing Devices
Use this flow for command-line tools, AI agents and other apps that can't send the user to a web page and receive them back. The user approves your app in a browser, on the same device or another one, while your app waits for the answer. It follows the OAuth 2.0 Device Authorization Grant (RFC 8628).
- Request a device code
- Send the user to OwnerRez to enter the code
- The user approves your app
- Get the access token
1. Request a device code
Your app asks OwnerRez for two codes: a device code, which your app keeps and uses in step 4, and a user code, which the user enters in step 2. Send a POST request to https://api.ownerrez.com/oauth/device_authorization using basic authentication, where the username is the Client ID of your OAuth App and the password is its Client Secret. Send these optional parameters in the "application/x-www-form-urlencoded" format:
scope:readorfull. Defaults to your app's default scope.client_id: your app's Client ID. Basic authentication already identifies your app, so you can leave it out; if you send it, it must match.
The response contains:
device_code: the code your app sends in step 4 to check whether the user has approved. Don't show it to the user.user_code: the code the user enters to approve your app, in the format XXXX-XXXX.verification_uri: the page where the user enters the code,https://app.ownerrez.com/oauth/device.verification_uri_complete: the same page with the user code already filled in.expires_in: how many seconds both codes stay valid. Always 600 (10 minutes).expires_on: when both codes expire, in UTC (ISO 8601).interval: the minimum number of seconds to wait between checks in step 4. Starts at 5.
Sample response:
{
"device_code": "dc_...",
"user_code": "B3KM-7X2P",
"verification_uri": "https://app.ownerrez.com/oauth/device",
"verification_uri_complete": "https://app.ownerrez.com/oauth/device?user_code=B3KM-7X2P",
"expires_in": 600,
"expires_on": "2026-06-12T15:30:00.0000000Z",
"interval": 5
}
2. Send the user to OwnerRez to enter the code
Send the user to verification_uri_complete from step 1, such as https://app.ownerrez.com/oauth/device?user_code=B3KM-7X2P. Or show them the user_code and https://app.ownerrez.com/oauth/device, and let them type the code in. The page is on app.ownerrez.com because it uses the user's OwnerRez login.
The user can open it on the device running your app or on another device, such as their phone.
3. The user approves your app
The user signs in to OwnerRez if they aren't already signed in, then approves or denies your app. OwnerRez doesn't redirect back to your app; the page tells the user to close it and go back to their device. Your app learns the answer in step 4.
4. Get the access token
While the user decides, your app checks for approval by sending a POST request to https://api.ownerrez.com/oauth/token, with the same basic authentication as step 1 and this body:
grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=dc_...
Wait at least interval seconds between checks. Until the user decides, each check returns this error:
{
"error": "authorization_pending",
"error_description": "The authorization request is still pending."
}
Three other errors change what your app does next:
slow_down: your app checked too soon. Wait 5 seconds longer between checks from then on.access_denied: the user denied your app. To try again, start over from step 1.expired_token: the codes expired after 10 minutes. Start over from step 1.
Once the user approves, the next check returns the access token:
{
"access_token": "at_...",
"token_type": "bearer",
"scope": "full",
"user_id": 123456,
"user_display_name": "Beach House Rentals",
"refresh_token": "rt_...",
"expires_in": 2592000,
"expires_at": "2026-07-12T12:00:00.0000000Z",
"refresh_token_supported": true
}
Use it the same way as a user's access token: see Access the OwnerRez API and Refreshing Tokens.
Revoking Access
If the user decides they no longer want to use the integration, or you wish to disable it for them or on a specific device, you can revoke access by making the following call with basic authentication, where the username is the Client ID of your OAuth App and the password is the Client Secret of your OAuth app.
This process is the same for both device and user tokens.
DELETE https://api.ownerrez.com/oauth/access_token/<token>
For example:
curl -u c_foo:s_bar -i -X DELETE https://api.ownerrez.com/oauth/access_token/at_baz
Handling User Revoked Access via Webhooks
Users can also revoke access to your app from within OwnerRez. To handle this case, you must handle the webhooks sent from OwnerRez when an account is revoked. Your app also receives entity webhooks for the types you turn on (see Webhooks). This one tells you a host removed your app.
We will POST to the Webhook URL you specify in your OAuth App settings, sending the username and password you specify using basic authentication. The revoke is also sent to any per-connection subscriptions for application_authorization_revoked on that account. Each distinct URL gets it once, so a subscription that uses your app’s webhook URL doesn’t cause a second delivery.
The webhook body will be JSON in the following format:
{
"id": "5d2c8e41-9a6f-4b07-b3e8-1f4a7c9d2e60",
"action" : "application_authorization_revoked",
"user_id" : 347311458
}
Getting Notified when Entities Change via Webhooks
It's important for your app to know when bookings or guest records change in OwnerRez without having to make many requests, in a loop, throughout the day. To help you know when bookings or guest records change, OwnerRez can send a POST request to your application any time a booking or guest record changes. Read more about webhooks in the OwnerRez Webhooks support article.
Updating the Webhook URL
Changing the Webhook URL in your OAuth app settings doesn't change existing per-connection subscriptions. OwnerRez has two ways to deliver webhooks, and it uses both:
- Your app's webhook URL (OAuth app settings, Developer tab). One URL for every connected account, for the webhook types you turn on there.
- Per-connection subscriptions (
POST /v2/webhooksubscriptions). A URL per connected account, filtered by type, action, and, optionally, category.
If both cover the same event for the same account, you receive it twice, once at each URL. Pick one.
To move a subscription to a new URL, delete it (DELETE /v2/webhooksubscriptions/{subscriptionId}) and create a new one. To send everything to your app’s URL instead, delete the subscriptions.
To see the subscriptions, open your app’s page and go to the Webhook Subscriptions tab, or list a connection’s subscriptions with GET /v2/webhooksubscriptions; it returns only your app’s subscriptions.
Common Issues & Questions
Why am I getting a 403?
403 errors most often occur due to missing User-Agent headers, suspicious content, or a blocked IP address. If you suspect you have fallen foul of our IP block list, please contact us at partnerhelp@ownerrez.com.
Why can't I enable Messaging webhooks?
Self-use access for your own OAuth app is allowed, including Message webhooks. See Grant Access to Yourself.
If you are building an OAuth app that you plan to market to others, Message webhooks require a partnership agreement between your business and OwnerRez.To gain access, please contact us at partnerhelp@ownerrez.com with the subject line Messaging API Access.
Why can't I query Listing endpoints?
Listing endpoints requires a partnership agreement between your business and OwnerRez. To gain access, please contact us at partnerhelp@ownerrez.com with the subject line Listing Endpoints Access.