<!--
PROVENANCE - verbatim vendor documentation, do not edit the body.

Source: Entrata Developer Portal, "Webhooks" page (order 8) attached to the
        "Entrata APIs" API (id 5471c3a8-e16f-3b80-93b3-006060e705db).
Portal: https://developer.entrata.com/  (Gravitee.io SPA - the page is NOT
        readable by a plain HTTP fetch of that URL; it renders client-side.)
Backing portal API (public, no auth required):
        https://developer-api.entrata.com/portal/environments/DEFAULT/apis/5471c3a8-e16f-3b80-93b3-006060e705db/pages/f20ffc4a-cdd7-46c0-8ffc-4acdd776c07e/content
Vendor updated_at: 2026-03-04T02:35:43.83Z  (contentRevisionId revision 1)
Captured: 2026-07-31

To re-fetch:
  curl -sL "https://developer-api.entrata.com/portal/environments/DEFAULT/apis/5471c3a8-e16f-3b80-93b3-006060e705db/pages/f20ffc4a-cdd7-46c0-8ffc-4acdd776c07e/content"

To list all portal doc pages:
  curl -sL "https://developer-api.entrata.com/portal/environments/DEFAULT/apis/5471c3a8-e16f-3b80-93b3-006060e705db/pages?page=1&size=200"
-->

# Webhooks
Webhooks are a mechanism for receiving real-time updates from Entrata. By delivering event information to your server as it happens, webhooks eliminate the need for constant polling and help you avoid API rate limits. Webhook queueing ensures reliable delivery, even if your server experiences temporary downtime. Webhooks streamline your integration with Entrata, allowing you to build more efficient and responsive applications.

## Webhook Event Types
Currently available webhook events are listed below. Each event type indicates the triggering action for the webhook. For instance, workorder.status.update messages are triggered when a work order status is changed.


| Name | Payload | Details |
| --- | --- | --- |
| lease.completed | {"ClientId":"int","PropertyId":"int","LeaseId":"int",<br>"CustomerId":"string","ApplicationStatusId":"int",<br>"ApplicationStageId":"int"} | N/A |
| lease.partially.completed | {"ClientId":"int","PropertyId":"int","LeaseId":"int",<br>"CustomerId":"string","ApplicationStatusId":"int",<br>"ApplicationStageId":"int"} | N/A |
| lease.started | {"ClientId":"int","PropertyId":"int","LeaseId":"int",<br>"CustomerId":"string","ApplicationStatusId":"int",<br>"ApplicationStageId":"int"} | N/A |
| oa.application.events | {"ClientId":"int","PropertyId":"int","LeaseId":"int",<br>"ProductId":"int","ApplicationId":"int", "ApplicationStageId":"int","ApplicationStatusId":"int",<br>"NewApplicantId":"int","TriggeredByApplicantId":"int", "TriggeredByCompanyUserId":"int",<br>"EventName":"string"} | "oa" is an acronym for "online application" |
| workorder.status.update | {"ClientId":"int","PropertyId":"int","LeaseId":"int",<br>"CustomerId":"int","MaintenanceRequestId":"int",<br>"MaintenanceStatus":"string"} | Work order statuses are client defined. Work order status *types* can be "suspended", "completed", or "cancelled" |

## Delivery and Idempotency
Entrata webhooks are delivered at least once, which means there's a chance the same message could be sent to your endpoint multiple times. To prevent duplicate processing, utilize the MessageID found in every webhook message. Store this ID on your server, and before processing any new webhook, check if you've already handled a message with that ID. If you have, discard the duplicate.

## Message Payload
When a webhook is triggered for its event type a corresponding JSON payload is posted to the webhook’s URL via HTTP. The JSON payload contains the following name-value pairs:
* **Type** - The type of message. For a notification, the type is “Notification”.
* **MessageID** - A universally unique identifier (UUID), unique for each message published. For a notification that Entrata resends during a retry, the message ID of the original message is used.
* **Topic Arn** - The Amazon Resource Name (ARN) for the topic that this message was published to.
* **Message** - The “Message” value specified when the notification was published to the topic.
* **Timestamp** - The time (Mountain Time) when the notification was published.
* **SignatureVersion** - Version of the signature used.
  * If the SignatureVersion is 1, Signature is a Base64-encouded SHA1withRSA signature of the Message, MessageId, Subject (if present), Type, and Timestamp values.
  * If the SignatureVersion is 2, Signature is a Base64-encoded SHA256withRSA signature of the Message, MessageID, Subject (if present), Type, and Timestamp values.
* **Signature** - Base64-encoded SHA1withRSA or SHA256withRSA signature of the Message, MessageID, Subject (if present), Type, and Timestamp values.

The following HTTP POST message is an example of a Notification message to an HTTP endpoint:

```
{
    "Type" : "Notification",
    "MessageId" : "946e6b34-ef7f-48fb-a8b7-e60a8540deed",
    "TopicArn" : "client-4823:workorder.status.update:9",
    "Message" :
        "{\"ClientId\":4923,
        \"PropertyId\":12345,
        \"LeaseId\":1234567,
        \"CustomerId\":1439583,
        \"MaintenanceRequestId\":79833,
        \"MaintenanceStatus\":\"Completed\"}",
    "Timestamp" : "2024-10-25T04:03:09Z",
    "SignatureVersion" : "1",
    "Signature": "Signature"
}
```



## Setup Your Server
To receive webhook payloads you must expose a public HTTP/S endpoint on your server that responds with a 2xx status code.

Entrata sends a Signature that can be used with the MessageID to verify a webhook payload.

```
function validateDigitalSignature(data: string, receivedSignature: string): boolean {
   const verify = crypto.createVerify('RSA-SHA1');
   verify.update(data);
   return verify.verify(publicKey, receivedSignature, 'base64');
}

const notification = '{
    "Type" : "Notification",
    "MessageId" : "946e6b34-ef7f-48fb-a8b7-e60a8540deed",
    "TopicArn" : "client-4823:workorder.status.update:9",
    "Message" : "{
        \"ClientId\":4923,
        \"PropertyId\":12345,
        \"LeaseId\":1234567,
        \"CustomerId\":1439583,
        \"MaintenanceRequestId\":79833,
        \"MaintenanceStatus\":\"Completed\",
        "Timestamp" : "2024-10-25T04:03:09Z",
        "SignatureVersion" : "1",
        "Signature": "Signature"}';
const obj = JSON.parse(notification);
let data = obj.Message.concat( obj.MessageId, obj.Type, obj.Timestamp, obj.TopicArn)
const publicKey = fs.readFileSync('public-key.pem', 'utf-8');

// Validate the digital signature
const isSignatureValid = validateDigitalSignature(data, obj.Signature);
console.log('Signature Validation Result:', isSignatureValid);
```

## Getting Started
### Partners
Contact apisupport@entrata.com with the following information:
* A brief description of what you are trying to accomplish with Entrata webhooks
* The webhook event types you want access to
* The URL(s) you will use to receive webhook calls
* The Entrata client name
* The Entrata client subdomain

Entrata will respond once setup is complete with a public key you can use to verify a webhook message’s signature.
### Clients
Contact apisupport@entrata.com with the webhook event types and URL(s) you will use to receive webhook calls. Entrata will add the webhook events and the associated URLs to your account. Entrata will also respond with a public key you can use to verify a webhook message’s signature, and that you can proceed with the setup steps listed below in the Entrata platform:
#### Current API Users
If your company IS an API User in “Apps” → “API Access”:
* In “API Access”, search for your company’s name
* Select “Manage” in your company’s row
* Select the “Web Service Permission” tab
* Navigate to the bottom of the screen and select the webhooks you want to receive webhook calls from
* Click “Save”
#### New API Users
If your company IS NOT an API User in “Apps” → “API Access”:
* In “API Access”, select “Add API User” 
* Search for your company’s name
* Select “Enable Access” in your company’s row
* Select the properties you want to allow API and webhook access to
* Click “Save and continue”
* In the “Data Permissions” step, navigate to the bottom of the screen and select the webhooks you want to receive webhook calls from
* Click “Save”
