# RentEngine Public API

Integrate your systems anywhere with RentEngine.

## Authorization

This API uses JWT Bearer token authentication. Follow these steps to obtain and use your API tokens:

### Obtaining API Tokens

1. Log in to your RentEngine [developer portal](https://app.rentengine.io/developer/portal)
2. In the top corner, click the "Create New API Key" button
3. Provide a name for your token (e.g., "Integration Name")
4. Click Create
5. Copy the token to your clipboard and save it securely as it will not be displayed again

**Important Security Notice:** Your token will only be displayed ONCE at creation time. Make sure to copy it and store it securely. For security reasons, we cannot display the token again after this point.

### Using API Tokens

Include your token in all API requests as a Bearer token in the Authorization header:

```
Authorization: Bearer your_token_here
```

### Token Security Best Practices

- Store tokens securely in environment variables or a secure vault
- Never hardcode tokens in your application code
- Do not share tokens in public repositories or client-side code
- Use separate tokens for different integrations or environments

### Token Permissions

Each token generated by a user will have the full permissions of the user that created it across all accounts associated with that user.
Actions will be logged in the name of that user & token.

### Invalidating Tokens

Tokens will not expire. (Well not for 100 years at least). If a token is compromised or no longer needed:

1. Log in to your RentEngine [developer portal](https://app.rentengine.io/developer/portal)
2. Find the token you wish to invalidate in the table in the API Keys section
3. Click the "Revoke Token" icon that looks like a trash can

Once revoked, a token cannot be restored. You'll need to create a new token if needed.

### Pagination

All list endpoints in the RentEngine API support pagination to efficiently handle large datasets. All paginated endpoints accept the same query parameters, but there are **two response formats** in use. Check the endpoint's response schema to determine which format it returns.

**Pagination Parameters (all list endpoints)**

- `limit` - Controls how many items to return per page (default: 50, max: 100)
- `page_number` - Specifies which page to retrieve (0-indexed, default: 0)

Example request with pagination:
```
GET /api/public/v1/lockboxes?limit=25&page_number=1
```

This would return the second page of results with 25 items per page.

#### Response Format A — Bare Array (legacy)

Most list endpoints return a bare JSON array containing only the requested page of items. The response does **not** include the total count or an explicit end-of-data marker.

Endpoints using this format include:
- `/lockboxes`
- `/lockbox_events`
- `/lockbox_installations`
- `/units`
- `/prospects`
- `/subteams`
- `/prescreening_templates`
- `/rental_applications`

Example response:
```json
[
  { "id": "...", "...": "..." },
  { "id": "...", "...": "..." }
]
```

To iterate, increment `page_number` until the response array is shorter than the requested `limit` — that indicates the last page.

#### Response Format B — Envelope with Page Metadata

Newer list endpoints wrap the data in an envelope that includes explicit pagination metadata, so you don't have to infer the end of the dataset from the array length.

Endpoints using this format include:
- `/rental_application_groups`

Example response:
```json
{
  "data": [
    { "id": "...", "...": "..." },
    { "id": "...", "...": "..." }
  ],
  "page": {
    "limit": 50,
    "page_number": 0,
    "has_more": true,
    "next_page_number": 1
  }
}
```

Fields in the `page` object:
- `limit` - The `limit` value used for this response (echoes the request)
- `page_number` - The 0-indexed page returned (echoes the request)
- `has_more` - `true` if additional pages are available, `false` on the final page
- `next_page_number` - The page number to request next, or `null` when `has_more` is `false`

To iterate, follow `next_page_number` until it is `null` (or `has_more` is `false`).

**Performance Considerations**

- Use appropriate `limit` values based on your needs. Smaller values reduce payload size but require more API calls, which can slow down performance and be subject to rate limits.
- When filtering data, apply filters in the query parameters first to reduce the total number of items that need to be fetched.

## Rate Limiting

To ensure fair usage and protect our infrastructure, all API endpoints are rate limited. Rate limits are applied per user (based on your API token).

**Default Rate Limits**

| Tier | Requests | Window |
|------|----------|--------|
| Standard | 30 | 5 seconds |
| Strict | 10 | 5 seconds |

Most endpoints use the "Standard" tier. Endpoints that return PII or
stream binary artifacts — `GET /rental_applications/{id}` and
`GET /rental_applications/{id}/documents/{documentId}` — use the
"Strict" tier (2 req/s).

**Rate Limit Headers**

All API responses include headers to help you track your rate limit status:

| Header | Description |
|--------|-------------|
| `X-RateLimit-Limit` | Maximum requests allowed in the current window |
| `X-RateLimit-Remaining` | Number of requests remaining in the current window |
| `X-RateLimit-Reset` | Unix timestamp (milliseconds) when the rate limit resets |

**Handling Rate Limits**

When you exceed the rate limit, you'll receive a `429 Too Many Requests` response with a `Retry-After` header indicating how many seconds to wait before retrying.

```json
{
  "error": "Too Many Requests",
  "message": "Rate limit exceeded. Please try again later.",
  "retryAfter": 4
}
```

**Best Practices**

- Monitor the `X-RateLimit-Remaining` header to avoid hitting limits
- Implement exponential backoff when retrying after a 429 response
- Cache responses when possible to reduce API calls
- Use webhooks for real-time updates instead of polling

## Webhooks

RentEngine provides webhooks to notify your systems about events in real-time. This allows you to build integrations that respond immediately to changes in your RentEngine data.

**Setting Up Webhooks**

Webhooks can be configured through the RentEngine [developer portal](https://app.rentengine.io/developer/portal). You'll need to specify:

1. The target URL where webhook events should be sent
2. The data you want to monitor (e.g., lockboxes, units, lockbox_events)
3. The event types you want to receive (INSERT, UPDATE, DELETE)
4. An optional API key that will be included in webhook requests to your endpoint

**Webhook Payload Structure**

Webhook payloads follow this general structure:

```json
{
  "type": "INSERT|UPDATE|DELETE",
  "table": "table_name",
  "record": { /* The current state of the record (null for DELETE) */ },
  "old_record": { /* The previous state of the record (null for INSERT) */ }
}
```

The specific fields in `record` and `old_record` will depend on the table that triggered the event.

**Event Types**

- `INSERT`: Sent when a new record is created
- `UPDATE`: Sent when an existing record is modified
- `DELETE`: Sent when a record is deleted

**Security Considerations**

- Webhook endpoints should be HTTPS to ensure secure transmission of data
- Validate the API key included in the webhook request to ensure it's coming from RentEngine
- Implement idempotency in your webhook handlers to prevent duplicate processing

**Webhook Delivery**

RentEngine uses a reliable delivery system (QStash) to ensure webhooks are delivered even during temporary outages. If your endpoint is unavailable, we'll retry delivery with exponential backoff.


Version: 1.1.1

## Servers

Production environment
```
https://app.rentengine.io/api/public/v1
```

Staging environment
```
https://staging-app.rentengine.io/api/public/v1
```

## Security

### BearerAuth

JWT Bearer token authentication. Use format 'Bearer {token}' in the Authorization header.

Type: http
Scheme: bearer
Bearer Format: JWT

### ApiKeyAuth

API key authentication for webhooks. The key is defined when setting up the webhook in the [developer portal](https://app.rentengine.io/developer/portal) and is delivered in the `X-API-Key` header on every webhook request.

Type: apiKey
In: header
Name: X-API-Key

## Download OpenAPI description

[RentEngine Public API](https://docs.rentengine.io/_bundle/openapi.yaml)

## Reporting

Operations for retrieving leasing performance reports and analytics

### Get unit leasing performance

 - [GET /reporting/leasing-performance/units/{unitId}](https://docs.rentengine.io/openapi/reporting/getunitleasingperformance.md): Retrieve leasing performance metrics for a specific unit within a date range.

This endpoint provides comprehensive leasing activity data including:
- Days on market
- Property health assessment
- Lead volume and conversion metrics
- Showing activity (scheduled, completed, upcoming)
- Application metrics
- Communication activity (texts, calls)
- Detailed showing feedback from completed showings

## Lockboxes

Operations for managing lockboxes

### Get lockboxes

 - [GET /lockboxes](https://docs.rentengine.io/openapi/lockboxes/getlockboxes.md): Retrieve lockboxes with optional filtering and pagination

### Create lockboxes

 - [POST /lockboxes](https://docs.rentengine.io/openapi/lockboxes/postlockboxes.md): Create new lockboxes (currently only SentriLock type is supported)

### Transfer lockboxes between accounts

 - [POST /lockboxes/transfer_accounts](https://docs.rentengine.io/openapi/lockboxes/postlockboxestransferaccounts.md): Moves lockboxes between accounts. The user must have access to both the lockboxes and the target account.

### Generate a lockbox code

 - [POST /lockboxes/generate_code](https://docs.rentengine.io/openapi/lockboxes/postgeneratelockboxcode.md): Generate a one-time code for a lockbox. The code can be generated by providing either a lockbox_id, serial_number, or unit_id. The code will be valid for the specified date.

## Lockbox Events

Operations for tracking and creating lockbox events

### Get lockbox events

 - [GET /lockbox_events](https://docs.rentengine.io/openapi/lockbox-events/getlockboxevents.md): Retrieve lockbox events with optional filtering and pagination

### Create lockbox events

 - [POST /lockbox_events](https://docs.rentengine.io/openapi/lockbox-events/postlockboxevents.md): Create new lockbox events (Install or Uninstall)

### Lockbox events

 - [POST LockboxEvents](https://docs.rentengine.io/openapi/lockbox-events/receive-lockbox-events.md)

## Lockbox Installations

Operations for retrieving lockbox installations

### Get lockbox installations

 - [GET /lockbox_installations](https://docs.rentengine.io/openapi/lockbox-installations/getlockboxinstallations.md): Retrieve lockbox installations with optional filtering and pagination. Lockbox installations can only be created by inserting a lockbox event with event_type "Install".

## Units

Operations for managing rental units

### Get units

 - [GET /units](https://docs.rentengine.io/openapi/units/getunits.md): Retrieve units with optional filtering and pagination

### Create or update a unit

 - [POST /units](https://docs.rentengine.io/openapi/units/postunit.md): Create a new unit or update an existing one.

## Insert vs Update
- Insert: When no id is provided, a new unit will be created. Required fields for creation include address, property_type, target_rental_rate, and account_id.
- Update: When an id is provided, an existing unit will be updated. No other fields are required.

## Address Updates
When updating a unit, if you include the address field, you must provide all address components (street_number, street_name, zip_code, state, city). Partial address updates are not supported.

## Structured Access Instructions
When providing structured_access_instructions, the showing_method field must also be set. The structure of the access instructions depends on the showing method:
- For "Self Guided", "Remote Guided", or "Remote Guided with Gated Access" methods: Include fields like lockbox_location, lockbox_code, etc.
- For "Accompanied" method: Include fields like assigned_user_ids, meeting_location, etc.

### Units

 - [POST UnitsEvents](https://docs.rentengine.io/openapi/units/receive-units-updates.md): Webhook for unit changes (creates, updates, deletes).
Only the below fields are included in the record and old_record objects.

## Prospects

Events related to prospective tenants

### Get prospects

 - [GET /prospects](https://docs.rentengine.io/openapi/prospects/getprospects.md): Retrieve prospects with optional filtering and pagination

### Prospects

 - [POST ProspectsEvents](https://docs.rentengine.io/openapi/prospects/receive-prospects-updates.md): Webhook for prospect changes (creates, updates, deletes).
Only the below fields are included in the record and old_record objects.

## Multifamily Properties

Operations for managing multifamily properties. Multifamily properties are used to syndicate large properties with paid advertising contracts to the paid rental feeds. For example, paid adverising contracts are required for the Zillow network if the building has more than 24 units, and for the Apartments.com if the building has more than 4 units. Other ILSs have different thresholds.

### Get multifamily properties

 - [GET /multifamily_properties](https://docs.rentengine.io/openapi/multifamily-properties/getmultifamilyproperties.md): Retrieve multifamily properties with optional filtering

### Create or update a multifamily property

 - [POST /multifamily_properties](https://docs.rentengine.io/openapi/multifamily-properties/postmultifamilyproperties.md): Create a new multifamily property or update an existing one

## Floorplans

Operations for managing floorplans associated with multifamily properties. Floorplans are used to syndicate units to the paid rental feeds for paid advertising contracts. They must be used in conjunction with a multifamily property.

### Get floorplans

 - [GET /floorplans](https://docs.rentengine.io/openapi/floorplans/getfloorplans.md): Retrieve multifamily_prs with optional filtering

### Create or update a floorplan

 - [POST /floorplans](https://docs.rentengine.io/openapi/floorplans/postfloorplans.md): Create a new floorplan or update an existing one

## Leasing Events

Events related to leasing events

### Create leasing events

 - [POST /leasing_events](https://docs.rentengine.io/openapi/leasing-events/postleasingevents.md): Create one or more leasing events. Additional event types will be supported in future releases.

Currently supported event types:
  - Assign to User — assign one or more users to a prospect. The context object must include an assignedToUserIds array. See AssignToUserContext.
  - Application Received — log that an application has been received from an external system. The context object accepts optional metadata about the external application; see ApplicationReceivedContext.

### Leasing events

 - [POST LeasingEvents](https://docs.rentengine.io/openapi/leasing-events/receive-leasing-events.md): Webhook for leasing events (creates, updates, deletes).
Leasing events of the following types are supported:
- "New"
- "Contacted, Awaiting Information"
- "Showing Desired"
- "Showing Scheduled"
- "Showing Complete"
- "Missed Showing"
- "Ghosting"
- "Application Sent to Prospect"
- "Application Received"
- "Application Pending"
- "Application in Owner Review"
- "Application Approved"
- "Withdrawn"
- "Application Rejected"
- "Prescreen Submitted"
- "Prescreen Rejected - Self reported credit"
- "Prescreen Rejected - Self reported income"
- "Prescreen Rejected - ID Verification"
- "Prescreen Approved"
- "Looking too early"
- "Lease out for signing"
- "Lease Signed"
- "Deposit Received"
- "Move-in Scheduled"
- "Moved In"
- "Unit of Interest Unavailable"
- "Not Interested"
- "Duplicate Lead"
- "Still Deciding"
- "HOA Application Sent To Prospect"
- "HOA Application Submitted"
- "HOA Application Approved"
- "HOA Application Rejected"
- "Showing Failed"
- "Showing Canceled"
- "Showing Confirmed"
- "Arrived for Showing"
- "Showing Started"
- "Log Note"
- "Assign to User"
- "Blocklist Prospect"
- "Unblock Prospect"
- "Reassign Showing"

## Subteams

Operations for managing subteams

### Get subteams

 - [GET /subteams](https://docs.rentengine.io/openapi/subteams/getsubteams.md): Retrieve subteams with optional filtering and pagination

## Prescreening Templates

Operations for managing prescreening templates used for prospect qualification

### Get prescreening templates

 - [GET /prescreening_templates](https://docs.rentengine.io/openapi/prescreening-templates/getprescreeningtemplates.md): Retrieve prescreening templates with optional filtering and pagination

## Showings

Operations for managing showing availability and scheduling

### Get unit showing availability

 - [GET /showings/availability](https://docs.rentengine.io/openapi/showings/getshowingavailability.md): Retrieve showing availability for a specific unit, including available and preferred showing windows

### Create a showing

 - [POST /showings/create](https://docs.rentengine.io/openapi/showings/createshowing.md): Create a new showing for a unit. This endpoint handles both new showings and rescheduling of existing showings.

## Prospect Types
- Self: Regular prospect who needs to complete prescreening
- Agent: Real estate agent who needs to provide a valid agent token

## Prescreening
For self prospects, the system will automatically run prescreening based on the unit's prescreen template.
If prescreening fails, the showing will not be created and an appropriate error will be returned.

## Agent Tokens
For agent prospects, a valid 6-character agent token must be provided in the agentTk field.

## Showing Methods
The desiredShowingMethod field allows specifying the preferred showing method:
- "Accompanied": Agent-guided showing
- "Self Guided": Self-guided showing
- "Remote Guided": Remote-guided showing
- "Remote Guided with Gated Access": Remote-guided showing with gate access

## Marketing

Operations for retrieving marketing listings for external display and embedding on websites

### Get marketing listings

 - [GET /marketing/listings/{accountId}](https://docs.rentengine.io/openapi/marketing/getmarketinglistings.md): Retrieve marketing listings for a specific account. This endpoint is designed for embedding listings on external websites and marketing platforms.

## Rental Applications

Operations for rental application groups, applicant records (with PII), and application documents.

### List rental application groups

 - [GET /rental_application_groups](https://docs.rentengine.io/openapi/rental-applications/listrentalapplicationgroups.md): Retrieve rental application groups with filters, sorting, and pagination. Each group
represents a single party applying to a unit and bundles one or more applicants.
The response embeds a non-PII summary for each applicant including screening status.

For the full applicant record including PII (personal details, income, address history),
fetch the individual applicant via GET /rental_applications/{id}.

### Get a rental application group

 - [GET /rental_application_groups/{id}](https://docs.rentengine.io/openapi/rental-applications/getrentalapplicationgroup.md): Retrieve a single rental application group with its applicants (non-PII summary),
screening status for each applicant, and the full decision history.

### Get a rental application

 - [GET /rental_applications/{id}](https://docs.rentengine.io/openapi/rental-applications/getrentalapplication.md): Retrieve a single rental application (applicant record) with all data broken out
and structured, including PII (personal details, income, address history, co-applicants,
pets, vehicles, custom questions). Includes a documents array with opaque
document_id values that can be passed to
GET /rental_applications/{id}/documents/{documentId} to stream the actual file bytes.

Access is gated by the authenticated user's permissions on the underlying account.

Rate limit: Strict tier — 2 req/s (10 per 5 seconds).

### Download a rental application document

 - [GET /rental_applications/{id}/documents/{documentId}](https://docs.rentengine.io/openapi/rental-applications/getrentalapplicationdocument.md): Stream the raw bytes of a document associated with a rental application.

The documentId is an opaque encrypted identifier returned by
GET /rental_applications/{id} on each entry in the documents array.
It identifies which underlying artifact to fetch — an applicant-uploaded file,
a TransUnion screening report (credit / criminal / eviction), or an ID
verification artifact (front / back / selfie). A fresh documentId is minted
on every detail fetch, so the same document yields a different value each
time — do not cache by this id.

Response Content-Type reflects the underlying document (typically
application/pdf for screening reports, image/jpeg for ID artifacts,
and the original MIME type for applicant uploads). By default the
Content-Disposition is inline; pass ?download=true to force
attachment for a browser download prompt.

Rate limit: Strict tier — 2 req/s (10 per 5 seconds).

### Rental application groups

 - [POST RentalApplicationGroups](https://docs.rentengine.io/openapi/rental-applications/receive-rental-application-group-updates.md): Webhook for rental application group changes. Emits the following semantic events:
- group.created when a new application group is created (INSERT).
- group.state_changed when the group's status transitions (for example, Submitted → Approved). The changes.status object describes the transition.
- group.unit_changed when the group's unit_id changes without a status change. The changes.unit_id object describes the transition.
- group.updated fallback for other meaningful UPDATE events.

When a single UPDATE contains multiple changes (for example, a status change and a unit change at the same time), the most specific event is emitted — group.state_changed wins over group.unit_changed, which wins over group.updated. All detected transitions are always included in the changes object, so subscribers that want granular detection can inspect changes regardless of the top-level event.

The record and old_record objects are whitelisted and do not include applicant PII. Fetch the group detail endpoint (GET /rental_application_groups/{id}) to retrieve non-PII group state and the applicant list, or GET /rental_applications/{id} for the full applicant record including PII.

### Rental applications

 - [POST RentalApplications](https://docs.rentengine.io/openapi/rental-applications/receive-rental-application-updates.md): Webhook for individual rental application changes. Emits the following semantic events:
- application.created when a new applicant record is created (INSERT).
- application.state_changed when the applicant's status transitions (for example, Incomplete → Submitted). The changes.status object describes the transition.
- application.updated fallback for other meaningful UPDATE events (for example, progress changes, move_in_date changes).

The record and old_record objects are whitelisted and do not include PII — fields such as personal_details, income_details, application_documents, address_history, and co_applicants are intentionally omitted. Fetch the rental application endpoint (GET /rental_applications/{id}) with a Bearer token to retrieve full PII after receiving a webhook.

