# How to Integrate Bolt.new with CoStar

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

## TL;DR

CoStar's property data API is enterprise-only — it requires an active CoStar Suite subscription (starting at several hundred dollars per month) and a separately negotiated API access agreement. There is no public free tier or developer sandbox. For Bolt.new apps targeting commercial real estate, CoStar's REST API uses OAuth 2.0 and works through a standard API route. For teams without CoStar access, Zillow, Estated, or ATTOM Data offer developer-accessible alternatives.

## Building a Commercial Real Estate Dashboard in Bolt.new with CoStar

CoStar is the dominant data provider for commercial real estate, covering over 6 million commercial properties in the US with detailed data including property characteristics, ownership history, lease comps, sale comps, tenant information, and market analytics. It is the go-to platform for brokers, investors, lenders, and corporate real estate teams. However, it is important to set accurate expectations upfront: CoStar is an enterprise product, not a developer-friendly consumer API. Accessing CoStar's data programmatically requires an active CoStar Suite subscription — a platform used by over 1.6 million CRE professionals at annual costs starting in the hundreds of dollars per month — plus a separate API access negotiation with CoStar's enterprise team. There is no public developer tier, no free sandbox environment, and no self-service API key signup.

For organizations that have a CoStar Suite subscription, the API is a powerful addition to Bolt.new apps. The REST API uses OAuth 2.0 client credentials flow for authentication and returns comprehensive property data, comparable transactions, market analytics, and geographic search results. Bolt.new's API route pattern handles this integration cleanly — OAuth token acquisition happens server-side, credentials are stored in environment variables, and your React dashboard displays the data. The WebContainer supports all outbound HTTPS calls needed for OAuth and API requests.

For teams without CoStar access, several developer-accessible alternatives cover residential and some commercial real estate use cases. Zillow's Bridge API provides residential property data through an application process. Estated (estated.com) offers property records, ownership, and tax data for US residential and commercial properties with a developer-friendly REST API and free trial tier. ATTOM Data Solutions provides comprehensive property data including ownership, transaction history, and valuations via a paid API with a free trial. This guide covers both the CoStar integration for enterprise users and the alternative path for teams in the exploration phase.

## Before you start

- An active CoStar Suite subscription — required to obtain API credentials (no self-service developer tier exists)
- CoStar API credentials (Client ID and Client Secret) obtained through CoStar's enterprise API access program — contact your CoStar account representative
- A Bolt.new project using Next.js (required for the API route pattern that handles OAuth token acquisition securely)
- Basic understanding of OAuth 2.0 client credentials flow — your API route will exchange client credentials for a bearer token before each set of API calls
- For the alternative path without CoStar access: an ATTOM Data API key (attomdata.com) or Estated API key (estated.com) — both offer free trials

## Step-by-step guide

### 1. Understand CoStar API access requirements and alternatives

Before starting the integration, it is essential to verify whether you have — or can obtain — CoStar API access. This matters because the path forward is entirely different depending on the answer. CoStar's data is among the most valuable and most closely guarded in the real estate industry, which is reflected in its access model.

CoStar API access requires two things: (1) an active CoStar Suite subscription, which is a commercial product priced per user per month in the hundreds of dollars range (CoStar does not publish pricing publicly — it is negotiated). (2) A separate API access agreement with CoStar's API team. The API is not self-service — you cannot go to a developer portal and generate credentials. Instead, your organization's CoStar account representative opens a request with CoStar's integration team, who reviews your use case, your data security practices, and the technical requirements of your application before issuing credentials.

If your organization already has a CoStar subscription and you want API access, the process is: contact your CoStar account manager, describe the application you are building (internal tool, client portal, etc.), explain that you need API credentials for a web application integration, and ask them to initiate the API access request. CoStar's review process typically takes 2-4 weeks. Once approved, you receive a Client ID and Client Secret (OAuth 2.0 client credentials) specific to your account and use case.

If you are in the exploration phase without a CoStar subscription, three alternatives provide legitimate developer API access to real estate data. Estated (estated.com) covers US property ownership records, tax assessor data, valuation estimates, and deed history for both residential and commercial properties. Pricing starts at free for limited requests, with paid tiers for production use — true self-service developer access. ATTOM Data (attomdata.com) is a comprehensive property data platform with a REST API covering 155 million US properties, including transaction history, demographics, and risk scores. They offer a free trial with no credit card required. Zillow's Bridge API (zillow.com/howzit/zillow-bridge-api) covers residential property data and requires an application approval but is free for approved partners.

The CoStar API endpoint base URL is https://api.costar.com and uses OAuth 2.0 client credentials flow. Authentication returns a bearer token with a configurable expiry (typically 1 hour) that must be included in all subsequent API requests as an Authorization header.

**Expected result:** You have either (1) CoStar API credentials (Client ID and Client Secret) ready to configure, or (2) an alternative API key from Estated or ATTOM Data for the non-CoStar path.

### 2. Implement OAuth 2.0 token acquisition in the API route

CoStar's API uses OAuth 2.0 client credentials flow, which is different from most simpler API integrations. Instead of a single static API key, you have a Client ID and Client Secret that you exchange for a time-limited access token before making data requests. The access token typically expires after 3600 seconds (1 hour), so your API route must handle token acquisition and refresh.

In Bolt.new, all of this authentication logic belongs in a server-side Next.js API route — never in React components. Your Client ID and Client Secret must stay on the server side to prevent unauthorized use. The API route handles: (1) checking if a valid cached token exists, (2) requesting a new token from CoStar's OAuth endpoint if needed, (3) making the actual data API call with the token, and (4) returning the data to the React frontend.

For token caching, a simple module-level object works well in Next.js serverless functions. Store the token and its expiry timestamp; before each request, check if the stored token is still valid (with a 60-second safety buffer). If expired, request a new token. This caching prevents making an OAuth round-trip for every API call.

Prompt Bolt to generate this complete authentication setup. Review the generated code to confirm that process.env.COSTAR_CLIENT_ID and process.env.COSTAR_CLIENT_SECRET are used for the OAuth request, and that no credentials appear in any client-side files. The OAuth token endpoint for CoStar is https://api.costar.com/oauth2/token — verify this with your CoStar account representative as endpoint URLs can vary by region or data tier.

```
// lib/costar.ts
const COSTAR_BASE = 'https://api.costar.com';
const TOKEN_ENDPOINT = `${COSTAR_BASE}/oauth2/token`;

interface TokenCache {
  accessToken: string;
  expiresAt: number;
}

// Module-level token cache (persists across requests in the same serverless instance)
let tokenCache: TokenCache | null = null;

async function getAccessToken(): Promise<string> {
  const clientId = process.env.COSTAR_CLIENT_ID;
  const clientSecret = process.env.COSTAR_CLIENT_SECRET;

  if (!clientId || !clientSecret) {
    throw new Error('CoStar credentials not configured (COSTAR_CLIENT_ID, COSTAR_CLIENT_SECRET)');
  }

  // Return cached token if still valid (with 60-second buffer)
  const now = Date.now();
  if (tokenCache && tokenCache.expiresAt > now + 60_000) {
    return tokenCache.accessToken;
  }

  // Request new token using client credentials flow
  const body = new URLSearchParams({
    grant_type: 'client_credentials',
    client_id: clientId,
    client_secret: clientSecret,
  });

  const response = await fetch(TOKEN_ENDPOINT, {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: body.toString(),
  });

  if (!response.ok) {
    const error = await response.text();
    throw new Error(`CoStar OAuth failed: ${response.status} ${error}`);
  }

  const data = await response.json();
  tokenCache = {
    accessToken: data.access_token,
    expiresAt: now + data.expires_in * 1000,
  };

  return tokenCache.accessToken;
}

export async function costarFetch<T>(
  endpoint: string,
  options: RequestInit = {}
): Promise<T> {
  const token = await getAccessToken();
  const response = await fetch(`${COSTAR_BASE}${endpoint}`, {
    ...options,
    headers: {
      ...options.headers,
      Authorization: `Bearer ${token}`,
      'Content-Type': 'application/json',
      Accept: 'application/json',
    },
  });

  if (!response.ok) {
    throw new Error(`CoStar API error: ${response.status} ${response.statusText}`);
  }

  return response.json();
}
```

**Expected result:** lib/costar.ts provides authenticated CoStar API access with automatic token caching. The .env file has placeholder credentials ready for your real CoStar Client ID and Client Secret.

### 3. Build property search API routes and React components

With the authentication layer in place, create the Next.js API routes that handle specific CoStar data requests. Each API route corresponds to a type of data: property search, property details, market analytics, or comparable transactions. These routes use the costarFetch utility from lib/costar.ts and transform the API response into a clean shape that your React components consume.

CoStar's REST API has endpoints for geographic search (find properties near a lat/long or within a polygon), property detail (get full details for a property ID), market statistics (vacancy rates, rent trends, absorption by market and property type), and comparables (recent sales and leases near a subject property). The exact endpoint paths and request parameters are documented in CoStar's API documentation, which is provided to registered API users through a developer portal accessible after approval.

For the React dashboard, prompt Bolt to create a property search page. The key UI elements are: a search bar with location input and property type filter, a results panel showing property cards, and a map view using Mapbox or Google Maps. Mapbox GL JS is particularly well-suited for this use case because it supports large property datasets, custom marker clustering, and interactive property detail popups. Use a public Mapbox token stored as NEXT_PUBLIC_MAPBOX_TOKEN (safe for client-side use) for the map component, since the Mapbox token is a publishable key that controls billing rather than data access.

The React component fetches from /api/costar/search with the user's search criteria as query parameters. The API route translates these to CoStar API parameters, makes the authenticated request, and returns a simplified array of properties. This proxy pattern is essential — it keeps the CoStar credentials server-side while providing a clean, consistent interface for the React components.

```
// app/api/costar/search/route.ts
import { NextResponse } from 'next/server';
import { costarFetch } from '@/lib/costar';

interface CoStarPropertyResult {
  propertyId: string;
  address: { deliveryAddress: string; city: string; state: string };
  propertyType: string;
  buildingSize: number;
  yearBuilt: number;
  location: { lat: number; lng: number };
}

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const location = searchParams.get('location') ?? '';
  const propertyType = searchParams.get('propertyType') ?? '';
  const minSF = searchParams.get('minSF');
  const maxSF = searchParams.get('maxSF');

  if (!location) {
    return NextResponse.json({ error: 'Location is required' }, { status: 400 });
  }

  try {
    // CoStar property search endpoint — exact path varies by API tier
    // Confirm endpoint with your CoStar account representative
    const queryParams = new URLSearchParams({
      location,
      ...(propertyType && { propertyType }),
      ...(minSF && { minBuildingSize: minSF }),
      ...(maxSF && { maxBuildingSize: maxSF }),
      pageSize: '20',
    });

    const data = await costarFetch<{ properties: CoStarPropertyResult[] }>(
      `/v1/properties/search?${queryParams}`
    );

    const properties = data.properties.map((p) => ({
      id: p.propertyId,
      address: p.address.deliveryAddress,
      city: p.address.city,
      state: p.address.state,
      propertyType: p.propertyType,
      squareFeet: p.buildingSize,
      yearBuilt: p.yearBuilt,
      lat: p.location.lat,
      lng: p.location.lng,
    }));

    return NextResponse.json({ properties });
  } catch (error) {
    const message = error instanceof Error ? error.message : 'Unknown error';
    return NextResponse.json({ error: message }, { status: 500 });
  }
}
```

**Expected result:** The property search API route returns CoStar property data in a clean format. The React dashboard displays property cards with address, type, and square footage. The map shows property pins at the correct geographic coordinates.

### 4. Use alternative APIs (Estated or ATTOM) without CoStar access

If your organization does not have a CoStar subscription, this step provides a complete integration path using Estated or ATTOM Data — both offering developer-accessible APIs for real estate data. While these APIs cover primarily residential and some light commercial properties rather than CoStar's pure commercial focus, they are excellent for apps targeting property investors, real estate agents, homebuyers, or general property research.

Estated (estated.com) is the most developer-friendly option. Sign up at estated.com, verify your email, and go to Settings → API Keys to generate a key. Estated's API uses a simple REST pattern with your API key as a query parameter — no OAuth flow required. The primary endpoint is GET https://apis.estated.com/v4/property?token=YOUR_KEY&street=123+Main+St&city=Austin&state=TX&zip=78701. The response includes ownership information, property characteristics (bedrooms, bathrooms, square footage, lot size), tax assessor data, current value estimates, and deed/sale history.

ATTOM Data (attomdata.com) requires a free trial signup and provides a more comprehensive commercial and residential dataset. After signup, you receive an API key for the header: apikey: YOUR_KEY. ATTOM's property detail endpoint is GET https://api.attomdata.com/propertyapi/v1.0.0/property/detail?address1=123 Main St&address2=Austin%2C TX%2078701. ATTOM is particularly strong for transaction history, school ratings, neighborhood demographics, and risk scores.

For either alternative, the integration pattern is identical to the CoStar approach: store the API key in .env (ESTATED_API_KEY or ATTOM_API_KEY), create a Next.js API route that proxies the request, and return a normalized property data shape to your React components.

```
// app/api/properties/lookup/route.ts
// Alternative to CoStar using Estated API — developer-friendly with free tier
import { NextResponse } from 'next/server';

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const street = searchParams.get('address') ?? '';
  const city = searchParams.get('city') ?? '';
  const state = searchParams.get('state') ?? '';
  const zip = searchParams.get('zip') ?? '';

  const apiKey = process.env.ESTATED_API_KEY;
  if (!apiKey) {
    return NextResponse.json({ error: 'ESTATED_API_KEY not configured' }, { status: 500 });
  }

  if (!street || !city || !state) {
    return NextResponse.json({ error: 'Address, city, and state are required' }, { status: 400 });
  }

  try {
    const params = new URLSearchParams({
      token: apiKey,
      street,
      city,
      state,
      ...(zip && { zip }),
    });

    const res = await fetch(`https://apis.estated.com/v4/property?${params}`);
    if (!res.ok) throw new Error(`Estated API error: ${res.status}`);

    const data = await res.json();
    const prop = data.data;

    if (!prop) {
      return NextResponse.json({ error: 'Property not found' }, { status: 404 });
    }

    return NextResponse.json({
      address: prop.address?.formatted_street_address,
      city: prop.address?.city,
      state: prop.address?.state,
      zip: prop.address?.zip_code,
      squareFeet: prop.structure?.total_area_sq_ft,
      yearBuilt: prop.structure?.year_built,
      bedrooms: prop.structure?.beds_count,
      bathrooms: prop.structure?.baths,
      estimatedValue: prop.valuation?.value,
      ownerName: prop.owner?.name,
      lastSalePrice: prop.deeds?.[0]?.sale_price,
      lastSaleDate: prop.deeds?.[0]?.sale_date,
    });
  } catch (error) {
    const message = error instanceof Error ? error.message : 'Unknown error';
    return NextResponse.json({ error: message }, { status: 500 });
  }
}
```

**Expected result:** The property lookup API route returns real property data from Estated for any US address. The React dashboard shows ownership information, property characteristics, and estimated values without requiring a CoStar subscription.

## Best practices

- Always cache OAuth access tokens to avoid making an authentication round-trip on every API request — CoStar tokens expire after 1 hour, so cache with a 60-second safety buffer
- Store COSTAR_CLIENT_ID and COSTAR_CLIENT_SECRET in .env (development) and your hosting platform's environment variables (production) — never in client-side code or git commits
- For teams without CoStar access, Estated or ATTOM Data are legitimate developer-accessible alternatives that can be integrated with the same API route pattern while CoStar access is being arranged
- Add geographic bounding boxes to CoStar property search queries — unrestricted searches can return extremely large datasets that slow down your app and consume API quota
- Use Mapbox GL JS for the property map component rather than Google Maps for real estate applications — Mapbox handles large property datasets with better performance and has more flexible styling for CRE use cases
- Implement pagination in your property search UI — CoStar searches can return hundreds of results, and loading them all at once creates a poor user experience and high API usage
- Include error handling that distinguishes between authentication failures (credentials problem) and data access failures (subscription/tier issue) so you can debug integration problems faster

## Use cases

### Commercial Property Search Dashboard

A searchable dashboard that lets users find commercial properties by location, property type (office, retail, industrial, multifamily), and size range. Property results display on a map with detail cards. Uses CoStar's property search endpoint with geographic filters, or ATTOM Data as an accessible alternative.

Prompt example:

```
Build a commercial property search dashboard using a real estate data API. Create a Next.js page with: (1) a search form with fields for city/state, property type dropdown (Office, Retail, Industrial, Multifamily, Land), min/max square footage, and a search button. (2) An API route at /api/properties/search that calls the real estate API with COSTAR_CLIENT_ID and COSTAR_CLIENT_SECRET from process.env. (3) A results grid showing property cards with address, type, square footage, and year built. (4) A Mapbox map (use NEXT_PUBLIC_MAPBOX_TOKEN) showing property pin locations. Use Tailwind CSS for styling.
```

### Market Analytics Dashboard

An internal tool for CRE professionals showing market-level analytics: average rent per square foot, vacancy rates, absorption data, and cap rate trends by market and property type. Data is fetched from CoStar's market analytics endpoints and displayed as charts using a charting library.

Prompt example:

```
Create a market analytics dashboard for commercial real estate. Build a Next.js page with charts showing quarterly vacancy rate trends, average rent per SF, and net absorption for a selected market. Create an API route at /api/markets/analytics that calls the CoStar market analytics endpoint with COSTAR_CLIENT_ID and COSTAR_CLIENT_SECRET. Use Chart.js or Recharts to display line charts for each metric. Add a market selector dropdown for major US cities. Handle the OAuth token acquisition inside the API route and cache the access token.
```

### Property Comp Report Builder

A tool for generating comparable sales and lease reports for a subject property. Users input a property address, and the app fetches recent sales comps and lease comps within a defined radius from CoStar's comparable transactions endpoints. Results export to a formatted table for broker use.

Prompt example:

```
Build a comparable sales report tool. Create a form where users input a property address and search radius (0.5, 1, 2, or 5 miles). Create an API route at /api/comps/sales that calls the CoStar comparable sales endpoint, fetching properties sold in the last 24 months within the specified radius. Return results with sale price, price per SF, sale date, property type, and cap rate. Display results in a sortable table with a CSV export button. Store COSTAR_CLIENT_ID and COSTAR_CLIENT_SECRET in .env.
```

## Troubleshooting

### CoStar OAuth token endpoint returns 401 or 403 Unauthorized

Cause: The Client ID or Client Secret in .env is incorrect, or the CoStar API access has not been fully provisioned. CoStar credentials are environment-specific — credentials for the sandbox (if one exists) are different from production credentials.

Solution: Verify COSTAR_CLIENT_ID and COSTAR_CLIENT_SECRET in your .env file exactly match what CoStar provided. Check with your CoStar account representative whether API access has been fully activated — provisioning sometimes takes additional time after credential generation. Confirm you are using the correct token endpoint URL for your region and API tier.

```
# .env — ensure no trailing spaces or quotes around values
COSTAR_CLIENT_ID=your_client_id_here
COSTAR_CLIENT_SECRET=your_client_secret_here
# No quotes, no spaces around the = sign
```

### CoStar API returns 403 Forbidden on data endpoints even with a valid token

Cause: Your CoStar API access tier may not include the specific endpoint or data type being requested. CoStar APIs are access-controlled by subscription level — a CoStar for Lenders subscription has different endpoint access than a CoStar Suite subscription.

Solution: Contact your CoStar account representative with the specific endpoint path returning 403 to confirm whether it is included in your API access agreement. CoStar's API documentation (accessible in the developer portal after approval) lists which endpoints are available for each access tier.

### Estated API returns an empty 'data' field for a known address

Cause: Estated may not have data for the specific property, or the address format does not match what Estated expects. Estated's coverage is primarily US residential — some rural addresses and commercial properties may have limited data.

Solution: Verify the address format: Estated works best with a clean street address (number + street name, no apartment numbers in the street field). Use the zip parameter when available to improve matching accuracy. Check Estated's API logs in their dashboard to see how the request was parsed. For commercial properties, consider ATTOM Data which has better commercial property coverage.

```
// Separate apartment/unit numbers — don't include in street param
// Correct:
const params = new URLSearchParams({
  token: apiKey,
  street: '123 Main St',     // No apartment number here
  unit: 'Apt 4B',             // Unit in separate param if needed
  city: 'Austin',
  state: 'TX',
  zip: '78701',
});
```

## Frequently asked questions

### Is CoStar's API free to use in a Bolt.new app?

No. CoStar's API is enterprise-only and requires an active CoStar Suite subscription plus a separate API access agreement negotiated through CoStar's enterprise team. There is no free developer tier, no sandbox environment, and no self-service API key signup. API access pricing is bundled with CoStar subscription costs and negotiated with your account representative.

### Does Bolt.new work with CoStar's API?

Yes, technically. CoStar's API uses standard HTTPS REST with OAuth 2.0 authentication, which works perfectly in Bolt.new's WebContainer via a Next.js API route. The integration challenge is not technical — it is access. You need a CoStar Suite subscription and a negotiated API agreement before you can obtain the Client ID and Client Secret needed to authenticate.

### What real estate data APIs work without a CoStar subscription?

Estated (estated.com) offers US property ownership, tax, and valuation data with a self-service developer account and free trial. ATTOM Data (attomdata.com) provides comprehensive property records, transaction history, and neighborhood data with a free trial. Both use simple API keys and work with the same Bolt.new API route pattern described in this guide. For residential listings with MLS data, Zillow's Bridge API is available to approved partners.

### Can I test CoStar API integration in Bolt.new's preview before deploying?

Yes — outbound API calls from Next.js API routes work in Bolt's WebContainer preview. If you have CoStar credentials, you can test property searches and view real data directly in the Bolt preview. Webhooks (if CoStar supports event notifications) would require a deployed URL, but standard REST API queries work in development.

### How do I deploy a Bolt.new CoStar app to Netlify?

Connect your GitHub repository to Netlify using Bolt's Netlify integration or the Netlify dashboard. Add COSTAR_CLIENT_ID and COSTAR_CLIENT_SECRET as environment variables in Netlify's site settings before deploying. Your Next.js API routes run as Netlify Functions and will receive the credentials via process.env. The OAuth token caching in lib/costar.ts works within a single serverless function invocation.

---

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