Retired endpointsMCP
Sales Agent — two endpoints retired
Both routes still exist but no longer do anything: every call returns410 Gone with error code 200128 (ENDPOINT_RETIRED, “This endpoint has been retired and no longer performs any action.”). They have been removed from the API reference.In MCP,
manage_sales_agent no longer has the create_plan_tasks and update_settings actions. Reading settings and plan tasks through search_sales_agent is unchanged.MCP
MCP — saved searches have their own tools
Writing a lead’s saved searches (property alerts and market snapshots) is now five separate tools, each with only its own parameters:The tool names match the old action names, and the arguments are the same with one exception:
pause_saved_searches takes categories as a top-level argument, not fields.categories. manage_leads no longer accepts these actions — calling it with one returns an error naming the tool to use.Reading saved searches stays in search_leads, which gains a scope parameter: pass scope: "saved_searches" with lead_id. lead_id on its own still works but is deprecated.Field changes
Leads — Update Lead no longer merges into an email duplicate by default
PUT /v1.0/leads/{leadId} — Update a lead — gains an optional query parameter, deduplicate (boolean, default false):falseor omitted — the lead is updated in place.true— when duplicate-lead merging is turned on for your account, and another lead in the same ownership scope shares this lead’s email address after the update, this lead is merged into that lead and is deleted.
deduplicate=true.New endpointsPermissions
Transactions — create custom fields
Two new endpoints bring transaction custom fields in line with lead custom fields, which you have been able to create through the API for some time.POST /v1.0/transaction/customfields— creates a transaction custom field on your team and returns it, id included, so you can populateLeadTransaction.customFieldsstraight away.GET /v1.0/transaction/forms?type=— lists the field groups defined for a transaction type.
Put the field in a group
A transaction custom field that belongs to no field group is invisible: it does not appear on the transaction detail page, as a list column, or in filters. PassformIds when you create the field, using ids from GET /v1.0/transaction/forms:Two differences from lead custom fields
anniversary_dateandhtmlare not available. Transactions have no recurring-date type, and HTML fields are not exposed through the API. Supported types:text,number,date,percentage,currency,single_select,multi_select.- Option lists accept both shapes. Transactions store a bare array, leads use an
optionwrapper. Either is accepted here and normalised, so["Pending","Closed"]and{"option":["Pending","Closed"]}behave identically.
Permissions
Narrower permissions for custom fields and notes
Two things an application used to get only as part of a much larger bundle can now be requested on their own.Both appear as their own line when you edit an application’s permissions — inside the group they belong to, alongside the broader items, each with its own checkbox. Communication is now Communication & Notes.If your integration creates custom fields, it no longer needs the right to create agents, accounts, offices or teams to do it.
Nothing to do for existing applications
Every application and every issued token keeps the access it already had. The new permissions were added alongside the existing ones, no endpoint became unreachable, and you do not need to reauthorize.New applications should ask for the narrower line rather than the bundle it was carved out of.Two things deliberately did not change.Reading custom field definitions —
GET /v1.0/teamFeatures/listCustomField and GET /v1.0/transaction/customfields — still comes with Team & Organization and Transactions view access respectively. Only creation was separated out.Writing notes is unchanged and still sits in that group on three separate items: POST /v1.0/notes shares Log calls, emails and texts manually, and create notes, while PUT and DELETE /v1.0/notes/{id} sit on Update notes and Delete manual log types and notes. Only reading was separated out.New endpoints
Leads — Saved searches: create, update, delete, pause and resume
The saved-searches resource is now read-write. A saved search and its listing alert are one object: a buyer search sends Property Alert emails (category: PROPERTY_ALERT), a seller search sends Market Snapshot emails (category: MARKET_SNAPSHOT), and the search filters and the delivery cadence travel together.POST /v1.0/leads/{leadId}/savedSearches— Create a property alert or market snapshot. Required:category,name(1–255 characters),alertFrequencyandcriteria. Takes the same values you would pick in the CRM: weekdays andAM/PMforschedule, cadence names (INSTANTLY,DAILY,WEEKLY,BIWEEKLY,MONTHLY, orNEVERto create it paused), and email addresses forrecipientEmails, which must belong to the lead. The lead needs at least one email address, and a search with the same filters as an existing one of the lead is refused.sendFirstEmailNowdefaults totruefor a property alert.PUT /v1.0/leads/{leadId}/savedSearches/{savedSearchId}— Update a saved search in place. Only the fields sent change;criteria, when sent, replaces every writable filter at once while filters the API cannot write are kept.categorycannot be changed, and searches the lead created on the website cannot be edited (2000011).DELETE /v1.0/leads/{leadId}/savedSearches/{savedSearchId}— Delete a saved search and stop its emails for good.POST /v1.0/leads/{leadId}/savedSearches/pause— Pause alerts without deleting the searches. Select bycategoriesor bysavedSearchIds, not both. Pausing sets the cadence toNEVER, keeps the conditions and schedule, and the search reads back asINACTIVEwith the cadence it replaced infrequencyBeforePause. Searches already off are reported asALREADY_INACTIVE, so repeating the call is safe.POST /v1.0/leads/{leadId}/savedSearches/resume— Resume alerts for the givensavedSearchIds, each at the cadence it ran at before it was paused. A search whose earlier cadence is unknown stays paused and is reported asPRIOR_FREQUENCY_UNKNOWN; setalertFrequencythrough the update endpoint instead.
results entry per selected search with result (PAUSED, RESUMED, ALREADY_INACTIVE, ALREADY_ACTIVE, PRIOR_FREQUENCY_UNKNOWN, NOT_CHANGED), previousAlertFrequency, alertFrequency and status.Criteria rules
criteria is shared by reads and writes. locations takes either named locations (cities, zipCodes, …) or mapCircles (centre, radius, unit of miles or kilometers, at most 100 miles), not both; omitting locations means no location filter. priceMin / priceMax, daysOnSite, purchaseTypes and includeOpenHouse apply to PROPERTY_ALERT only; soldPriceMin / soldPriceMax and daysSold apply to MARKET_SNAPSHOT only. Dropdown values such as propertyTypes and listingStatuses must match the options Lofty shows for the lead’s site exactly, including letter case. listingStatuses defaults to Active for a property alert and Sold for a market snapshot.Errors
A request rejected by validation or by a business rule answers HTTP200 with {"code": <error code>, "message": "..."} in place of the saved search — check code in the body, not the HTTP status. Unknown ids answer 404; leads the token’s user cannot see answer 403.Read endpoint changes
GET /v1.0/leads/{leadId}/savedSearches now returns frequencyBeforePause on an INACTIVE search — the cadence the resume endpoint restores — and documents the TERMINATED / REFUSED cadences left by older Lofty features, which can appear when reading but cannot be written. mapCircles[].unit is normalised to miles or kilometers.