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.
Integration method
Yardi's REST APIs are accessed via Next.js API routes using OAuth 2.0 token-based authentication. Your Bolt.new app never calls Yardi's API directly from the client — all requests go through server-side API routes that attach the Bearer token and handle response parsing. The Yardi API URL, client credentials, and database instance name are stored in server-side environment variables.
Prerequisites
- 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
Obtain Yardi API Access and Credentials
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.
Pro tip: Ask your Yardi account manager specifically for 'REST API' credentials, not 'SOAP' credentials. Yardi has older SOAP/XML web services and newer REST APIs — the REST endpoints are significantly easier to work with from JavaScript.
Expected result: You have received your Yardi client_id, client_secret, database instance name, and API base URL from Yardi support.
Configure Environment Variables and Set Up Authentication
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.
Create a lib/yardi.ts file that: 1) Has a getYardiToken() function that calls the Yardi OAuth token endpoint with client_credentials grant type using YARDI_CLIENT_ID and YARDI_CLIENT_SECRET from environment variables, caches the token in memory with its expiration, and returns a valid token (refreshing automatically). 2) Has a yardiRequest(path, options) helper that calls the Yardi REST API at YARDI_API_BASE_URL with the Bearer token, handling errors. Use TypeScript.
Paste this in Bolt.new chat
1# .env file — all Yardi credentials are server-side only2# NEVER use NEXT_PUBLIC_ prefix for any Yardi credential3YARDI_API_BASE_URL=https://your-instance.yardi.com/yardiws/4YARDI_CLIENT_ID=your-client-id-guid5YARDI_CLIENT_SECRET=your-client-secret6YARDI_TOKEN_URL=https://your-instance.yardi.com/yardiws/token7YARDI_DATABASE=your-database-name8# Scope varies by Yardi deployment — confirm with your account manager9YARDI_SCOPE=yardiwsPro tip: Cache the OAuth access token in memory (module-level variable) rather than fetching a new one for every API request. Yardi tokens are valid for 1 hour — cache them and only refresh when within 5 minutes of expiration.
Expected result: lib/yardi.ts is created with token management and a request helper. TypeScript compiles without errors.
Create API Routes for Property and Unit Data
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.
Create Next.js API routes: 1) GET /api/yardi/properties that fetches all properties from Yardi and returns an array with propertyId, name, address, unit count, and occupancy rate. 2) GET /api/yardi/properties/[propertyId]/units that fetches all units for a property with unit number, bedrooms, rent, and occupancy status. 3) GET /api/yardi/leases/[leaseId] that fetches a specific lease with tenant info, start/end date, monthly rent, and outstanding balance. Use the yardiRequest helper from lib/yardi.ts.
Paste this in Bolt.new chat
1// app/api/yardi/properties/route.ts2import { NextResponse } from 'next/server';3import { yardiRequest } from '@/lib/yardi';45export async function GET() {6 try {7 // Endpoint path depends on your Yardi configuration8 // Consult your Yardi API documentation for exact paths9 const data = await yardiRequest('/properties', {10 method: 'GET',11 headers: { 'Accept': 'application/json' },12 });1314 // Normalize Yardi's response format to what your UI expects15 // Yardi field names vary by version — check your API docs16 const properties = Array.isArray(data) ? data : data?.properties ?? data?.value ?? [];17 const normalized = properties.map((p: Record<string, unknown>) => ({18 propertyId: p.PropertyID ?? p.id,19 name: p.PropertyName ?? p.name,20 address: `${p.AddressLine1 ?? ''}, ${p.City ?? ''}, ${p.State ?? ''}`.trim(),21 totalUnits: Number(p.TotalUnits ?? 0),22 occupiedUnits: Number(p.OccupiedUnits ?? 0),23 }));2425 return NextResponse.json({ properties: normalized });26 } catch (error) {27 console.error('Yardi properties fetch error:', error);28 return NextResponse.json({ error: 'Failed to fetch properties from Yardi' }, { status: 500 });29 }30}Pro tip: Yardi's REST response field names are not standardized across all API versions. Your Yardi API documentation (specific to your deployment version) is the authoritative reference — field names like 'PropertyID' or 'propertyId' vary by Yardi version and configuration.
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.
Build the Work Order / Maintenance Request Feature
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.
Create a POST /api/yardi/work-orders route that creates a maintenance work order in Yardi. Accept unitId, category, description, priority (low/medium/high/emergency), and contactPhone from the request body. Map these to Yardi's work order fields and POST to the Yardi work orders endpoint. Return the created work order ID. Also build a MaintenanceRequestForm React component with these fields and success/error states.
Paste this in Bolt.new chat
1// app/api/yardi/work-orders/route.ts2import { NextResponse } from 'next/server';3import { yardiRequest } from '@/lib/yardi';45const PRIORITY_MAP: Record<string, string> = {6 low: '3',7 medium: '2',8 high: '1',9 emergency: '0',10};1112export async function POST(request: Request) {13 try {14 const { unitId, category, description, priority, contactPhone } = await request.json();1516 if (!unitId || !category || !description) {17 return NextResponse.json(18 { error: 'unitId, category, and description are required' },19 { status: 400 }20 );21 }2223 // Field names depend on your Yardi version — consult your API documentation24 const workOrderPayload = {25 UnitID: unitId,26 Category: category,27 Description: description,28 Priority: PRIORITY_MAP[priority] ?? '2',29 ContactPhone: contactPhone ?? '',30 Status: 'Open',31 };3233 const result = await yardiRequest('/workorders', {34 method: 'POST',35 headers: {36 'Content-Type': 'application/json',37 'Accept': 'application/json',38 },39 body: JSON.stringify(workOrderPayload),40 });4142 const workOrderId = result?.WorkOrderID ?? result?.id ?? result?.workOrderId;43 return NextResponse.json({ success: true, workOrderId });44 } catch (error) {45 console.error('Yardi work order creation error:', error);46 return NextResponse.json({ error: 'Failed to create work order in Yardi' }, { status: 500 });47 }48}Pro tip: Ask your Yardi administrator for the list of valid work order categories configured in your Yardi instance. Using a category string that doesn't exist in Yardi's configuration will cause the API call to fail.
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.
Deploy and Configure Production Access
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.
Add error boundary components to all pages that call Yardi API routes. If an API call fails, show a user-friendly error message like 'Unable to connect to property management system. Please try again or contact support.' instead of a blank screen. Include a retry button that re-fetches the data.
Paste this in Bolt.new chat
Pro tip: Yardi production environments often have strict security controls. Test your deployment's connectivity to the Yardi API early — network restrictions are the most common deployment blocker and require IT coordination that can take days to resolve.
Expected result: The deployed app successfully connects to Yardi from the hosting infrastructure. All API routes return data correctly on the production URL.
Common 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.
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.
Copy this prompt to try it in Bolt.new
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.
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.
Copy this prompt to try it in Bolt.new
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.
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.
Copy this prompt to try it in Bolt.new
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'.
1// Token request must use form-encoded body, not JSON2const tokenResponse = await fetch(process.env.YARDI_TOKEN_URL!, {3 method: 'POST',4 headers: { 'Content-Type': 'application/x-www-form-urlencoded' },5 body: new URLSearchParams({6 grant_type: 'client_credentials',7 client_id: process.env.YARDI_CLIENT_ID!,8 client_secret: process.env.YARDI_CLIENT_SECRET!,9 scope: process.env.YARDI_SCOPE ?? 'yardiws',10 }),11});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.
1// Add this to debug field names in development2console.log('Raw Yardi response:', JSON.stringify(data, null, 2));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
Alternatives
Buildium has a publicly documented REST API with a developer portal and sandbox environment, making it far more accessible than Yardi for building property management integrations without an enterprise contract.
Propertybase is a CRM-focused property management platform built on Salesforce with accessible APIs — better suited for real estate agents and smaller portfolios than Yardi's enterprise focus.
CoStar provides commercial real estate data and analytics APIs — complementary to Yardi for market research and property valuation rather than operational property management.
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.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation