# How to Integrate Bolt.new with Yardi Voyager

- Tool: Bolt.new
- Difficulty: Intermediate
- Time required: 45 minutes
- Last updated: April 2026

## TL;DR

Yardi Voyager API gives Bolt.new apps access to units, leases, tenant data, and work orders from Yardi's property management platform — but only if you're a Yardi customer with an active API license. The integration uses OAuth 2.0 and REST calls via Next.js API routes. If you don't have Yardi access, Buildium or AppFolio offer more accessible APIs for property management apps.

## Yardi API Integration: Enterprise Property Management for Bolt Apps

Yardi Voyager is enterprise property management software for large commercial and residential portfolios. Its REST API provides access to units, leases, tenants, work orders, and financial data. Building on this data enables tenant portals, maintenance systems, and reporting dashboards.

Critical access requirement: Yardi's API requires both an active Yardi customer license and a separate API module enabled by Yardi. There is no free trial or public sandbox. You must be a Yardi customer and contact your account manager to enable API access. If you don't have Yardi access, see the alternatives section for Buildium and AppFolio, which have publicly available APIs.

For those with Yardi access, the integration uses OAuth 2.0 client credentials flow — suitable for server-to-server communication where your app acts on behalf of the property management company rather than individual users.

## Before you start

- An active Yardi Voyager software license (required — no free trial available)
- Yardi API module enabled by your Yardi account manager (separate from the software license)
- Your Yardi API credentials: client_id, client_secret, and database instance name from Yardi support
- Your Yardi REST API base URL (typically https://[your-instance].yardi.com/ysi_guestcard5/webservices/)
- A Bolt.new account with a Next.js project

## Step-by-step guide

### 1. Obtain Yardi API Access and Credentials

Yardi API access is not self-service. The process requires coordinating with Yardi support and your account manager. Here is what you need to request and what Yardi will provide:

First, verify you have an active Yardi Voyager license — this is the property management software itself, with annual licensing fees typically starting in the tens of thousands of dollars for enterprise deployments. If your organization uses Yardi, there will be a Yardi administrator or IT contact who manages the software.

Contact your Yardi account manager and request 'REST API access' or 'ILS Web Services API enablement.' Yardi will ask for your intended use case, the technical contact responsible for the integration, and may require a data use agreement. After approval, Yardi provisions an API client for your database instance and provides: client_id (a GUID), client_secret, your database instance name (appears in your Yardi URL), and the REST API base URL for your deployment.

If you are building a property management app and don't have Yardi access, consider these alternatives: Buildium has a developer-accessible REST API with a sandbox environment and no enterprise contract requirement. AppFolio's API is similarly more accessible. RentManager and Propertyware also have APIs. These alternatives let you build and test without the Yardi procurement barrier.

**Expected result:** You have received your Yardi client_id, client_secret, database instance name, and API base URL from Yardi support.

### 2. Configure Environment Variables and Set Up Authentication

Store your Yardi credentials in your Bolt.new project's .env file. All Yardi credentials are server-side only — no NEXT_PUBLIC_ prefix on any of them. The API base URL, client_id, and client_secret are sensitive configuration data that must never appear in browser-accessible code.

Yardi's REST API uses OAuth 2.0 Client Credentials flow for server-to-server authentication. Your app calls Yardi's token endpoint with client_id and client_secret, receives a short-lived access token (typically valid for 1 hour), and includes it as a Bearer token in all subsequent API requests. Token refresh must be handled automatically — create a token management utility that caches the current token and refreshes it when expired.

The token endpoint URL and scope vary by Yardi deployment. Your Yardi technical contact should provide the exact token URL. Common patterns include the database instance name in the URL path.

```
# .env file — all Yardi credentials are server-side only
# NEVER use NEXT_PUBLIC_ prefix for any Yardi credential
YARDI_API_BASE_URL=https://your-instance.yardi.com/yardiws/
YARDI_CLIENT_ID=your-client-id-guid
YARDI_CLIENT_SECRET=your-client-secret
YARDI_TOKEN_URL=https://your-instance.yardi.com/yardiws/token
YARDI_DATABASE=your-database-name
# Scope varies by Yardi deployment — confirm with your account manager
YARDI_SCOPE=yardiws
```

**Expected result:** lib/yardi.ts is created with token management and a request helper. TypeScript compiles without errors.

### 3. Create API Routes for Property and Unit Data

With authentication handled in lib/yardi.ts, build Next.js API routes that fetch property management data from Yardi's endpoints. Yardi's REST API follows standard REST conventions: GET requests for reading data, POST for creating records, PUT for updates.

The key endpoints for a tenant portal or property dashboard are: properties list (GET /properties), units for a property (GET /properties/{propertyId}/units), leases (GET /leases or GET /tenants/{tenantId}/leases), and work orders (GET /workorders). The exact endpoint paths vary by Yardi configuration — use your Yardi API documentation (provided when API access is granted) for the authoritative URL structure.

All API routes should proxy requests to Yardi, handling authentication transparently. The client (your React components) calls /api/yardi/properties and never knows the underlying Yardi URL exists.

```
// app/api/yardi/properties/route.ts
import { NextResponse } from 'next/server';
import { yardiRequest } from '@/lib/yardi';

export async function GET() {
  try {
    // Endpoint path depends on your Yardi configuration
    // Consult your Yardi API documentation for exact paths
    const data = await yardiRequest('/properties', {
      method: 'GET',
      headers: { 'Accept': 'application/json' },
    });

    // Normalize Yardi's response format to what your UI expects
    // Yardi field names vary by version — check your API docs
    const properties = Array.isArray(data) ? data : data?.properties ?? data?.value ?? [];
    const normalized = properties.map((p: Record<string, unknown>) => ({
      propertyId: p.PropertyID ?? p.id,
      name: p.PropertyName ?? p.name,
      address: `${p.AddressLine1 ?? ''}, ${p.City ?? ''}, ${p.State ?? ''}`.trim(),
      totalUnits: Number(p.TotalUnits ?? 0),
      occupiedUnits: Number(p.OccupiedUnits ?? 0),
    }));

    return NextResponse.json({ properties: normalized });
  } catch (error) {
    console.error('Yardi properties fetch error:', error);
    return NextResponse.json({ error: 'Failed to fetch properties from Yardi' }, { status: 500 });
  }
}
```

**Expected result:** The /api/yardi/properties endpoint returns property data from your Yardi instance. Verify by calling it directly and checking the response shape against your Yardi database.

### 4. Build the Work Order / Maintenance Request Feature

Work order creation is one of the highest-value features for a tenant portal. Tenants submit maintenance requests through your Bolt app, which creates work orders in Yardi that property managers can then track and assign through Yardi's native workflow.

The work order creation endpoint typically accepts: the unit ID or property ID, a category (plumbing, electrical, HVAC, etc.), description, priority level, and contact information. The exact required fields depend on your Yardi configuration and which work order types are enabled.

For incoming work orders from Bolt to Yardi, use a POST request with the work order data in the request body. Yardi should return the newly created work order ID, which you store in your database to link the tenant's submission to the Yardi record for status tracking.

```
// app/api/yardi/work-orders/route.ts
import { NextResponse } from 'next/server';
import { yardiRequest } from '@/lib/yardi';

const PRIORITY_MAP: Record<string, string> = {
  low: '3',
  medium: '2',
  high: '1',
  emergency: '0',
};

export async function POST(request: Request) {
  try {
    const { unitId, category, description, priority, contactPhone } = await request.json();

    if (!unitId || !category || !description) {
      return NextResponse.json(
        { error: 'unitId, category, and description are required' },
        { status: 400 }
      );
    }

    // Field names depend on your Yardi version — consult your API documentation
    const workOrderPayload = {
      UnitID: unitId,
      Category: category,
      Description: description,
      Priority: PRIORITY_MAP[priority] ?? '2',
      ContactPhone: contactPhone ?? '',
      Status: 'Open',
    };

    const result = await yardiRequest('/workorders', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
      },
      body: JSON.stringify(workOrderPayload),
    });

    const workOrderId = result?.WorkOrderID ?? result?.id ?? result?.workOrderId;
    return NextResponse.json({ success: true, workOrderId });
  } catch (error) {
    console.error('Yardi work order creation error:', error);
    return NextResponse.json({ error: 'Failed to create work order in Yardi' }, { status: 500 });
  }
}
```

**Expected result:** Submitting a maintenance request through the form creates a work order in Yardi and returns a work order ID. Verify by checking the Yardi interface to confirm the work order appears.

### 5. Deploy and Configure Production Access

Your Bolt.new app with Yardi integration needs to be deployed for production use. Since Yardi typically operates on corporate networks with IP allowlisting, coordinate with your IT team before deployment.

Many Yardi deployments are behind a corporate VPN or firewall, with API access restricted to approved IP addresses. If your Yardi instance is accessible only from the corporate network, your Bolt app's hosting server IP must be added to the Yardi API allowlist. Contact your Yardi system administrator with the IP addresses of your Netlify or Bolt Cloud deployment.

For Bolt Cloud or Netlify deployments, the outbound IP addresses may be variable (serverless functions use shared infrastructure). In this case, your Yardi administrator may need to use a broader IP range allowlist or you may need to set up a dedicated proxy server with a static IP. This is a common enterprise integration challenge — discuss the options with your IT team and Yardi support.

Deploy to Netlify or Bolt Cloud and add all YARDI_* environment variables to your hosting provider's dashboard. Test each API route after deployment to confirm connectivity to Yardi's servers from the hosting infrastructure.

**Expected result:** The deployed app successfully connects to Yardi from the hosting infrastructure. All API routes return data correctly on the production URL.

## Best practices

- Cache OAuth access tokens and only refresh when within 5 minutes of expiration — Yardi tokens are valid for 1 hour, and fetching a new token for each request is wasteful
- Never expose Yardi credentials on the client side — all API calls must go through server-side Next.js API routes
- Log raw Yardi API responses during development to verify field names match your specific Yardi version and configuration
- Handle Yardi downtime gracefully — show cached data with a 'data may be outdated' notice rather than a broken UI
- Coordinate IP allowlisting with your IT team before deployment — Yardi often restricts API access to approved IP ranges
- Use Buildium or AppFolio APIs if you're building a new property management app without existing Yardi infrastructure — they have public developer portals and free sandboxes
- Test API connectivity from the hosting environment early in the deployment process — network restrictions are the most common production blocker for Yardi integrations

## Use cases

### Tenant Self-Service Portal

Build a portal where tenants can log in to view their lease details, payment history, and outstanding balance. Tenants can submit maintenance requests that create work orders in Yardi, and view the status of existing requests. This reduces inbound phone and email volume to the property management office.

Prompt example:

```
Build a tenant portal that connects to the Yardi REST API. Create API routes for: 1) GET /api/yardi/tenant/[tenantId]/lease that fetches lease details, 2) GET /api/yardi/tenant/[tenantId]/balance that fetches outstanding balance, 3) POST /api/yardi/work-orders that creates a maintenance request. Build a dashboard showing lease info and a form to submit maintenance requests. Store Yardi credentials in environment variables.
```

### Property Manager Dashboard

Create an internal dashboard for property managers to see occupancy rates, upcoming lease expirations, and open work orders across all properties in their portfolio. This provides a consolidated view without requiring the manager to navigate Yardi's native interface.

Prompt example:

```
Create a property management dashboard that reads from the Yardi API. Fetch all properties and their units, calculate occupancy rate per property, list leases expiring in the next 90 days, and show open work orders sorted by priority. Display as a summary with cards and sortable tables. All Yardi API calls should go through server-side API routes.
```

### Maintenance Request Management

Build a streamlined maintenance request system that creates work orders in Yardi, assigns them to vendors, and sends status update notifications. The app acts as a front-end to Yardi's work order module with a better UX than Yardi's native interface.

Prompt example:

```
Build a maintenance request management system integrated with Yardi. Allow tenants to submit requests with category, description, and photos. API routes should create work orders in Yardi via POST /api/yardi/work-orders and fetch open orders for a property via GET /api/yardi/properties/[propertyId]/work-orders. Show a Kanban board view of work order statuses.
```

## Troubleshooting

### OAuth token request returns 401 Unauthorized or 'invalid_client' error

Cause: The client_id or client_secret is incorrect, or the token endpoint URL doesn't match the one for your Yardi database instance. Yardi has multiple deployment environments and each has its own token endpoint.

Solution: Verify the exact token endpoint URL with your Yardi account manager — it must match your specific database instance. Double-check client_id and client_secret values were copied correctly (no trailing spaces). Ensure the grant_type is 'client_credentials' and the Content-Type header is 'application/x-www-form-urlencoded'.

```
// Token request must use form-encoded body, not JSON
const tokenResponse = await fetch(process.env.YARDI_TOKEN_URL!, {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: new URLSearchParams({
    grant_type: 'client_credentials',
    client_id: process.env.YARDI_CLIENT_ID!,
    client_secret: process.env.YARDI_CLIENT_SECRET!,
    scope: process.env.YARDI_SCOPE ?? 'yardiws',
  }),
});
```

### API calls succeed in development but fail from the deployed app with connection refused or timeout

Cause: Yardi's API may be restricted to specific IP addresses, and your hosting provider's serverless function IPs are not on the allowlist.

Solution: Contact your Yardi system administrator to request that your deployment's outbound IP addresses be added to the Yardi API allowlist. For Netlify, find your function IP ranges in Netlify's documentation. Alternatively, set up a proxy server with a static IP that your deployment routes Yardi API calls through.

### Yardi API returns data but field names don't match what the code expects

Cause: Yardi's REST API field names are not standardized across versions. Different Yardi deployments and versions use different capitalization conventions (PropertyID vs propertyId vs property_id).

Solution: Log the raw response from a Yardi API call and inspect the actual field names returned by your specific Yardi deployment. Update the field name mappings in your normalization code to match.

```
// Add this to debug field names in development
console.log('Raw Yardi response:', JSON.stringify(data, null, 2));
```

## Frequently asked questions

### Can I access the Yardi API without being a Yardi customer?

No. Yardi's REST API is not publicly available. You must be an active Yardi Voyager software customer AND have the API module specifically enabled by Yardi for your account. There is no public sandbox, no free trial, and no way to test without a commercial Yardi relationship. If you need a property management API without existing Yardi infrastructure, Buildium and AppFolio have developer-accessible APIs.

### How do I connect Bolt.new to Yardi?

Contact your Yardi account manager to enable REST API access and obtain client_id, client_secret, and your API base URL. Store these in your .env file (server-side only). Build a token management utility that fetches OAuth 2.0 client credentials tokens. Then create Next.js API routes that use this token to proxy requests to Yardi's REST endpoints, returning formatted data to your React components.

### What data can I read from the Yardi API?

With API access enabled, Yardi provides endpoints for: property listings, unit details and availability, lease records (terms, rent amounts, dates), tenant contact information, rent payment history, maintenance work orders, financial data (income/expense reports), and vendor information. The specific endpoints available depend on which Yardi modules your organization has licensed.

### Is Yardi the best choice for a new property management app?

Yardi is appropriate only if your clients are existing Yardi customers who need a custom portal or dashboard built on their existing data. For new property management apps, Buildium's REST API is significantly more accessible with a free developer portal and sandbox. AppFolio, RentManager, and Propertyware are other alternatives with developer-friendly APIs that don't require enterprise contracts.

### Does Yardi API work with Bolt's WebContainer preview?

Outbound API calls work in Bolt's WebContainer, so the OAuth token exchange and REST calls can technically run in the preview. However, Yardi deployments are often restricted to specific IP allowlists, and the WebContainer's IP address may be blocked. More practically, Yardi API credentials are production credentials — use caution about connecting to a live property management database from a development environment.

---

Source: https://www.rapidevelopers.com/bolt-ai-integrations/yardi
© RapidDev — https://www.rapidevelopers.com/bolt-ai-integrations/yardi
