# How to Integrate Retool with Propertybase

- Tool: Retool
- Difficulty: Intermediate
- Time required: 30 minutes
- Last updated: April 2026

## TL;DR

Connect Retool to Propertybase by creating a REST API Resource using Salesforce's REST API — since Propertybase runs on the Salesforce platform, you authenticate with Salesforce OAuth and use SOQL queries to access Propertybase's real estate objects including listings, transactions, contacts, and commissions.

## Build a Real Estate Brokerage Operations Panel Using Propertybase in Retool

Propertybase gives real estate brokerages a purpose-built CRM on top of Salesforce, complete with MLS listing management, transaction coordination, and commission tracking. While Propertybase's own interface works well for agents, operations managers and brokerage administrators often need cross-agent reporting views, commission pipeline summaries, and listing performance dashboards that Propertybase's standard UI doesn't easily provide. Retool delivers this through direct Salesforce API access.

Since Propertybase is built on Salesforce, your Retool integration uses Salesforce's mature REST API — the same API used for custom Salesforce integrations. Propertybase's data lives in custom Salesforce objects following Propertybase's naming convention (pb__ prefix for managed package objects). Once authenticated, you can run SOQL queries against listings, transactions, contacts, and commission records exactly as you would against any Salesforce org, giving you full flexibility to build whatever reporting or management views your brokerage needs.

This integration is particularly valuable for creating executive dashboards that show listing inventory by agent, transaction pipeline value, commission projections for the current month, and lead conversion rates — data that requires cross-joining multiple Propertybase objects and is difficult to view cohesively in Propertybase's native reports.

## Before you start

- A Propertybase account with API access enabled (requires Propertybase on Salesforce Enterprise or above)
- Salesforce System Administrator access to create a Connected App for OAuth authentication
- Your Salesforce org's instance URL (e.g., https://yourorg.my.salesforce.com)
- A Retool account with permission to create Resources
- Knowledge of Propertybase's custom object API names (pb__Listing__c, pb__Transaction__c, etc.) — consult your Propertybase admin or the Object Manager in Salesforce Setup

## Step-by-step guide

### 1. Create a Salesforce Connected App for Retool authentication

Since Propertybase runs on Salesforce, you'll create a Salesforce Connected App to authenticate Retool. Log into your Salesforce org with System Administrator credentials and navigate to Setup (gear icon → Setup). In the Quick Find box, search for 'App Manager' and click New Connected App.

Fill in the required fields: Connected App Name = 'Retool Integration', API Name = 'Retool_Integration', Contact Email = your admin email. In the API (Enable OAuth Settings) section, check 'Enable OAuth Settings'. For the Callback URL, enter https://retool.com/auth/verify — you'll update this later if needed.

In the Selected OAuth Scopes section, add: Access and manage your data (api), Perform requests on your behalf at any time (refresh_token, offline_access), and Access unique user identifiers (openid).

Save the Connected App. Salesforce will display the Consumer Key (client_id) and Consumer Secret (client_secret). Copy both values — you'll need them for Retool. Note: it may take 2-10 minutes for the Connected App to become active after saving.

For the OAuth 2.0 username-password flow (simpler for service accounts), you also need an API-enabled Salesforce user's username and password plus their security token (resetable from Profile → Reset My Security Token).

**Expected result:** A Salesforce Connected App named 'Retool Integration' exists in your Salesforce org with OAuth settings configured. You have the Consumer Key and Consumer Secret values ready for Retool resource configuration.

### 2. Configure a Salesforce REST API Resource in Retool

Go to the Resources tab in your Retool instance and click Add Resource. Select REST API from the resource type list. Name the resource 'Propertybase (Salesforce API)'.

In the Base URL field, enter your Salesforce org's instance URL followed by the API version path: https://yourorg.my.salesforce.com/services/data/v59.0. Replace 'yourorg' with your actual Salesforce org subdomain, and adjust the API version (v59.0) to the current Salesforce API version if needed.

For authentication, use the OAuth 2.0 username-password flow for service account access. In the Authentication section, add a default header: key = Authorization, value = Bearer {{ retoolContext.configVars.SF_ACCESS_TOKEN }}.

To obtain the access token, you'll run a one-time token exchange. Create a temporary JavaScript query that POSTs to https://login.salesforce.com/services/oauth2/token with your client_id, client_secret, username, password+security_token, and grant_type=password. Extract the access_token from the response and store it as a Retool configuration variable named SF_ACCESS_TOKEN.

For production use with token refresh, store both the access_token and instance_url from the OAuth response in configuration variables and implement a Retool Workflow that refreshes the token before it expires (Salesforce access tokens expire after 2 hours by default unless configured otherwise).

Add a second default header: key = Content-Type, value = application/json. Click Save Changes.

```
// One-time token exchange — run as a temporary JavaScript query
// POST to Salesforce OAuth token endpoint
const response = await fetch('https://login.salesforce.com/services/oauth2/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: new URLSearchParams({
    grant_type: 'password',
    client_id: 'YOUR_CONSUMER_KEY',
    client_secret: 'YOUR_CONSUMER_SECRET',
    username: 'api-user@yourorg.com',
    // Append security token directly to password with no space
    password: 'YourPassword' + 'YourSecurityToken'
  }).toString()
});
const data = await response.json();
// Store data.access_token as SF_ACCESS_TOKEN configuration variable
return { access_token: data.access_token, instance_url: data.instance_url };
```

**Expected result:** The Propertybase (Salesforce API) REST Resource is saved in Retool with the correct base URL and Authorization header configured. Configuration variables store the Salesforce access token securely.

### 3. Query Propertybase listings and real estate data with SOQL

Propertybase stores listing data in a custom Salesforce object named pb__Listing__c. To query it, use Salesforce's SOQL (Salesforce Object Query Language) via the REST API's query endpoint.

Create a query named getActiveListings and select the Propertybase resource. Set Method to GET. In the Path field, enter /query. Add a URL parameter: key = q, value = your SOQL query string.

For active listings:
SELECT Id, Name, pb__List_Price__c, pb__Status__c, pb__Days_On_Market__c, pb__Property_Type__c, pb__City__c, pb__State__c, pb__Bedrooms__c, pb__Bathrooms__c, Owner.Name FROM pb__Listing__c WHERE pb__Status__c = 'Active' ORDER BY pb__List_Price__c DESC LIMIT 100

Note: Propertybase field API names use the pb__ prefix. Consult your Salesforce Setup → Object Manager → pb__Listing__c → Fields & Relationships to see all available field names for your org.

Create a second query named getTransactions for transaction pipeline data:
SELECT Id, Name, pb__Close_Date__c, pb__Sales_Price__c, pb__Stage__c, pb__Buyer_Agent__r.Name, pb__Seller_Agent__r.Name, pb__Transaction_Type__c FROM pb__Transaction__c WHERE pb__Stage__c != 'Closed' ORDER BY pb__Close_Date__c ASC LIMIT 50

Bind getActiveListings to a Table component and getTransactions to a second table. Create a date filter using a DateRangePicker component that adds a WHERE clause: AND CreatedDate >= {{ dateRange.start }} AND CreatedDate <= {{ dateRange.end }}.

```
// SOQL query for Propertybase listings — use as q URL parameter
SELECT
  Id,
  Name,
  pb__List_Price__c,
  pb__Status__c,
  pb__Days_On_Market__c,
  pb__Property_Type__c,
  pb__Bedrooms__c,
  pb__Bathrooms__c,
  pb__City__c,
  pb__State__c,
  pb__Zip_Code__c,
  Owner.Name,
  CreatedDate,
  LastModifiedDate
FROM pb__Listing__c
WHERE pb__Status__c = 'Active'
  AND CreatedDate >= {{ dateRange.start || 'THIS_MONTH' }}
ORDER BY pb__Days_On_Market__c DESC
LIMIT {{ pagination.pageSize || 100 }}
OFFSET {{ (pagination.page - 1) * (pagination.pageSize || 100) || 0 }}
```

**Expected result:** The getActiveListings query returns Propertybase listing records as a JSON array under data.records. The transformer flattens relationship fields (Owner.Name) and formats price values. The Table displays active listings sorted by days on market.

### 4. Build commission pipeline and agent performance queries

Create SOQL queries against Propertybase's commission objects to build a commission tracking panel. Commission data in Propertybase is stored in the pb__Commission__c object linked to transactions and agent contacts.

Create a query named getCommissions:
SELECT Id, pb__Agent__r.Name, pb__Agent__r.Email, pb__Transaction__r.Name, pb__Gross_Commission__c, pb__Agent_Commission__c, pb__Status__c, pb__Expected_Payment_Date__c FROM pb__Commission__c WHERE pb__Expected_Payment_Date__c = THIS_QUARTER ORDER BY pb__Expected_Payment_Date__c ASC LIMIT 200

Create an aggregate SOQL query named getCommissionsByAgent for the summary chart:
SELECT pb__Agent__r.Name, SUM(pb__Agent_Commission__c) totalCommission, COUNT(Id) dealCount FROM pb__Commission__c WHERE pb__Status__c IN ('Pending', 'Approved') AND CALENDAR_YEAR(pb__Expected_Payment_Date__c) = THIS_YEAR GROUP BY pb__Agent__r.Name ORDER BY totalCommission DESC

Bind the aggregate query to a Chart component. Set chart type to Bar, x-axis to Name (agent name), y-axis to totalCommission. This gives brokerage managers a visual ranking of agent production.

Create a JavaScript transformer for the commissions table that formats currency values, calculates the split percentage, and highlights overdue commissions (expected payment date in the past but status still Pending).

For complex reporting across Propertybase objects that require multi-object joins and calculated fields beyond what SOQL supports directly, RapidDev's team can help design the right Retool architecture combining multiple queries with JavaScript aggregation.

```
// JavaScript transformer — format commission records for display
const records = data.records || [];
return records.map(rec => {
  const grossComm = parseFloat(rec.pb__Gross_Commission__c || 0);
  const agentComm = parseFloat(rec.pb__Agent_Commission__c || 0);
  const splitPct = grossComm > 0
    ? ((agentComm / grossComm) * 100).toFixed(1) + '%'
    : 'N/A';

  const payDate = rec.pb__Expected_Payment_Date__c
    ? new Date(rec.pb__Expected_Payment_Date__c)
    : null;
  const isOverdue = payDate && payDate < new Date() && rec.pb__Status__c === 'Pending';

  return {
    id: rec.Id,
    agent: rec.pb__Agent__r?.Name || 'Unknown',
    transaction: rec.pb__Transaction__r?.Name || 'N/A',
    gross_commission: `$${grossComm.toLocaleString('en-US', { minimumFractionDigits: 2 })}`,
    agent_commission: `$${agentComm.toLocaleString('en-US', { minimumFractionDigits: 2 })}`,
    split: splitPct,
    status: rec.pb__Status__c || 'Unknown',
    expected_date: payDate ? payDate.toLocaleDateString('en-US') : 'Not set',
    overdue: isOverdue
  };
});
```

**Expected result:** The commissions table displays formatted commission records with agent names, transaction references, gross and agent commission amounts, split percentages, and expected payment dates. Overdue pending commissions are flagged. The bar chart ranks agents by commission volume for the current year.

### 5. Join Propertybase contacts with listing and transaction data

Build a unified agent and contact lookup panel that combines Salesforce Contact records (agents, clients) with their associated listings and transactions. This gives brokerage managers a complete view of any agent's current activity.

Create a query named searchContacts:
SELECT Id, FirstName, LastName, Email, Phone, Title, Account.Name, pb__Agent_MLS_ID__c FROM Contact WHERE (FirstName LIKE '%{{ textInput_search.value }}%' OR LastName LIKE '%{{ textInput_search.value }}%' OR Email LIKE '%{{ textInput_search.value }}%') AND RecordType.Name = 'Agent' LIMIT 20

When a contact is selected from the search results, trigger two follow-up queries:

getAgentListings (GET, /query): SELECT Id, Name, pb__List_Price__c, pb__Status__c, pb__Days_On_Market__c FROM pb__Listing__c WHERE OwnerId = '{{ table_contacts.selectedRow.id }}' ORDER BY CreatedDate DESC LIMIT 20

getAgentTransactions (GET, /query): SELECT Id, Name, pb__Close_Date__c, pb__Sales_Price__c, pb__Stage__c FROM pb__Transaction__c WHERE (pb__Buyer_Agent__c = '{{ table_contacts.selectedRow.id }}' OR pb__Seller_Agent__c = '{{ table_contacts.selectedRow.id }}') ORDER BY pb__Close_Date__c DESC LIMIT 20

Display the agent contact details in a profile card at the top, with their active listings in one table and their transaction pipeline in a second table below. Add a stat row showing total active listings, pipeline transaction value, and closed deals this year.

```
// SOQL for agent active listings — use as q URL parameter
SELECT
  Id,
  Name,
  pb__List_Price__c,
  pb__Status__c,
  pb__Days_On_Market__c,
  pb__Property_Type__c,
  pb__City__c,
  pb__State__c
FROM pb__Listing__c
WHERE OwnerId = '{{ table_contacts.selectedRow.id }}'
  AND pb__Status__c IN ('Active', 'Under Contract', 'Pending')
ORDER BY CreatedDate DESC
LIMIT 20
```

**Expected result:** The contact search finds matching agents and displays their profile. Selecting an agent loads their active listings in one table and their open transactions in a second table. Summary stats show the agent's current production metrics at a glance.

## Best practices

- Store Salesforce OAuth tokens as Secret configuration variables in Retool — never expose access tokens in query bodies or URL parameters.
- Create a dedicated Salesforce API integration user with minimum required object permissions rather than using an admin account for the Retool connection.
- Use SOQL date literals (THIS_QUARTER, THIS_YEAR, LAST_N_DAYS:30) instead of hardcoded date strings for time-based filters — they adjust automatically without requiring query changes.
- Always use optional chaining (?.) when accessing SOQL relationship fields in JavaScript transformers, since related records may be null if the relationship is empty or inaccessible.
- Implement token refresh logic using a Retool Workflow that runs every 90 minutes to refresh the Salesforce access token before it expires, storing the new token in a configuration variable.
- Verify Propertybase custom object API names (pb__ prefix) in your specific org's Object Manager before writing SOQL queries — field names can vary by Propertybase version and customization.
- Use SOQL aggregate queries (GROUP BY with SUM, COUNT) for summary charts and dashboard metrics rather than fetching all records and aggregating in JavaScript — server-side aggregation is faster.
- Add LIMIT and OFFSET clauses to all SOQL queries to implement pagination — Salesforce returns a maximum of 2,000 records per query and will return an error without pagination for large datasets.

## Use cases

### Build a listing inventory and agent performance dashboard

Create a Retool app that shows all active listings in the brokerage with list price, days on market, assigned agent, and current status. Add filters for price range, listing type, and agent. Include a summary chart showing listing count per agent and average days on market by property type.

Prompt example:

```
Build a listing dashboard that runs a SOQL query against pb__Listing__c with Active status, displays address, list price, days on market, and agent name in a sortable Table, and includes a Bar chart showing listings per agent from a GROUP BY SOQL query.
```

### Transaction pipeline and closing tracker

Build a transaction management panel showing all open transactions with their expected closing date, transaction value, status, and assigned coordinator. Add a pipeline view showing transaction value at each stage (Under Contract, Inspection, Appraisal, Clear to Close) and highlight transactions with closing dates in the next 7 days.

Prompt example:

```
Create a transaction tracker that queries pb__Transaction__c for open transactions, shows closing_date, transaction_value, stage, buyer_agent, and seller_agent in a Table with conditional row formatting (red for past-due closing dates, yellow for closing this week), and includes a pipeline value chart by stage.
```

### Commission projection and payout panel

Build a commission management dashboard that shows all commission records for the current month, grouped by agent, with expected payout date, gross commission, and split percentages. Include a summary row per agent showing YTD earnings and a chart comparing commission volume month-over-month.

Prompt example:

```
Build a commission panel that queries pb__Commission__c joined with related agent Contact records, shows agent_name, transaction_id, gross_commission, agent_split_percentage, and expected_payout_date, with a summary row per agent and a Line chart of monthly commission totals for the past 12 months.
```

## Troubleshooting

### SOQL query returns 'INVALID_TYPE: pb__Listing__c is not supported' error

Cause: The Propertybase managed package custom objects are not installed in the Salesforce org, or the API user doesn't have visibility to these objects due to field-level security or profile restrictions.

Solution: Verify Propertybase is installed in your org by going to Setup → Installed Packages and checking for Propertybase. If installed, check that your API user's profile has object and field permissions for pb__Listing__c. In Salesforce Setup → Object Manager, search for 'pb__Listing__c' to verify the object exists and check its field-level security settings.

### All API queries return 401 Session expired or invalid error

Cause: The Salesforce access token has expired. Salesforce access tokens expire based on the org's session timeout settings (typically 2 hours) unless the Connected App is configured with 'Refresh Token Policy: No expiration'.

Solution: Refresh your access token by running the OAuth token exchange query again (POST to login.salesforce.com/services/oauth2/token) and updating the SF_ACCESS_TOKEN configuration variable with the new token. For long-lived integrations, configure your Salesforce Connected App to use refresh tokens and build a Retool Workflow that automatically refreshes the token before it expires.

### SOQL query with relationship fields returns null for related object fields

Cause: Using relationship field traversal (e.g., Owner.Name) for a relationship where the related record doesn't exist or the API user lacks read permission on the related object.

Solution: Verify the related records exist and the API user has read permission on the related object (e.g., User object for Owner.Name). In your JavaScript transformer, use optional chaining (rec.Owner?.Name || 'N/A') to handle null relationship fields gracefully without causing transformer errors.

```
// Safe relationship field access in transformer
agent_name: rec.pb__Agent__r?.Name || 'Unknown',
transaction_name: rec.pb__Transaction__r?.Name || 'N/A',
```

### SOQL query returns fewer records than expected despite matching WHERE conditions

Cause: Salesforce enforces record-level security (sharing rules) — the API user can only see records they have access to based on sharing settings and their role hierarchy position.

Solution: Use a Salesforce System Administrator user or a user with 'View All Data' permission for your Retool API integration if you need org-wide visibility. Alternatively, adjust the sharing rules for the pb__Listing__c and pb__Transaction__c objects to grant the API user broader access via role hierarchy or sharing rules configured in Setup → Sharing Settings.

## Frequently asked questions

### Does Propertybase have its own REST API separate from Salesforce?

No, Propertybase does not have its own independent REST API. Since Propertybase is built as a managed package on the Salesforce platform, it uses Salesforce's REST API and authentication system. You access Propertybase data by querying Salesforce's API with SOQL statements targeting Propertybase's custom objects (those with the pb__ prefix in their API names).

### How do I find the correct API names for Propertybase custom fields?

Log into your Salesforce org with admin access and navigate to Setup → Object Manager. Search for 'pb__Listing__c' (or other Propertybase objects). Click Fields & Relationships to see all field labels with their API names. The API name is what you use in SOQL queries. You can also run a SOQL query using SELECT FIELDS(ALL) FROM pb__Listing__c LIMIT 1 in Salesforce's Developer Console to see all available fields.

### Can I update Propertybase listing data from Retool?

Yes, you can update Propertybase records from Retool by sending PATCH requests to the Salesforce REST API's sobjects endpoint: PATCH /services/data/v59.0/sobjects/pb__Listing__c/{recordId} with a JSON body containing the fields to update. Only include the fields you're changing — Salesforce's PATCH is a true partial update. Ensure your Salesforce API user has Edit permissions on the pb__Listing__c object and specific fields.

### How many Propertybase records can I query at once in Retool?

Salesforce REST API returns a maximum of 2,000 records per SOQL query. If your query matches more than 2,000 records, use LIMIT and OFFSET in your SOQL query for pagination, or use the nextRecordsUrl field in the API response to fetch subsequent pages. For very large datasets (100,000+ records), consider running the data pull through a Retool Workflow that iterates through pages and writes results to a Retool Database for faster app-level queries.

### Does Propertybase's Retool integration work with Propertybase GO as well?

Propertybase GO is a separate SaaS product distinct from the Salesforce-based Propertybase platform. Propertybase GO has its own REST API with different authentication and endpoints — it does not use Salesforce's API. If you're using Propertybase GO, you would configure a REST API Resource using Propertybase GO's specific API documentation and authentication credentials rather than the Salesforce OAuth flow described in this guide.

---

Source: https://www.rapidevelopers.com/retool-integrations/propertybase
© RapidDev — https://www.rapidevelopers.com/retool-integrations/propertybase
