Skip to main content
Retired endpointsMCP

Sales Agent — two endpoints retired

Both routes still exist but no longer do anything: every call returns 410 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):
  • false or 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.
Previously that merge ran on every update that changed a field, even one that did not touch email addresses, so a routine update could delete the lead being updated. If your integration relied on it, pass 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 populate LeadTransaction.customFields straight 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. Pass formIds when you create the field, using ids from GET /v1.0/transaction/forms:
Every id is checked before the field is created, so an unknown group or one already at its 50-field limit fails the whole request rather than leaving an unplaced field behind.

Two differences from lead custom fields

  • anniversary_date and html are 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 option wrapper. Either is accepted here and normalised, so ["Pending","Closed"] and {"option":["Pending","Closed"]} behave identically.
Field groups are read-only over the API — create, rename and delete them in the CRM.
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), alertFrequency and criteria. Takes the same values you would pick in the CRM: weekdays and AM / PM for schedule, cadence names (INSTANTLY, DAILY, WEEKLY, BIWEEKLY, MONTHLY, or NEVER to create it paused), and email addresses for recipientEmails, 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. sendFirstEmailNow defaults to true for 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. category cannot 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 by categories or by savedSearchIds, not both. Pausing sets the cadence to NEVER, keeps the conditions and schedule, and the search reads back as INACTIVE with the cadence it replaced in frequencyBeforePause. Searches already off are reported as ALREADY_INACTIVE, so repeating the call is safe.
  • POST /v1.0/leads/{leadId}/savedSearches/resume — Resume alerts for the given savedSearchIds, each at the cadence it ran at before it was paused. A search whose earlier cadence is unknown stays paused and is reported as PRIOR_FREQUENCY_UNKNOWN; set alertFrequency through the update endpoint instead.
Pause and resume return one 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 HTTP 200 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.