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.
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.
New toolsNew endpointsFixes

MCP Server

Released the Lofty MCP server — connect Claude, or any other Model Context Protocol client, to the Lofty API with nothing to install and no generated SDK:
Rather than one tool per endpoint, the server exposes four tools that cover the entire API: search_apis to find the operation matching an intent, describe_api to get that operation’s parameter schema, invoke_api to call it, and list_custom_fields to look up your team’s custom lead fields (which aren’t in any static schema). The tool list stays the same size as the API grows.Authentication uses your existing credentials — an API key or an OAuth 2.0 access token, with nothing to register specifically for MCP. Note that the MCP transport requires Authorization: Bearer <token> for both kinds, including API keys, which use the token prefix on the direct REST API. Calls run as the authenticated caller under the same permissions, scopes, and rate limits as a direct REST request.See the MCP Server documentation to get connected.

Leads — Saved searches

Added GET /v1.0/leads/{leadId}/savedSearches — returns every saved property search of a lead, including its conditions and alert delivery settings.
  • source — comma-separated origins to keep: AGENT_CREATED, LEAD_CREATED, SYSTEM_CREATED. Defaults to all. When migrating to another system, exclude SYSTEM_CREATED — the target usually generates its own, and importing ours duplicates the alerts.
  • includeInactive (default false) — include searches whose alerts are switched off. An INSTANTLY cadence counts as active, not off.
Returns an empty array when the lead has no saved searches, and 403 when the token’s user can’t access the lead.

Fixes

  • Tasks V2 / Calendar V2 — startAt / endAt are now parsed correctly when the time zone is supplied separately as timeZoneCode. A bare ISO timestamp such as 2026-03-01T15:00:00 sent alongside a timeZoneCode previously failed to parse and returned HTTP 500 (20005); timestamps carrying their own offset were unaffected. An offset in the string still takes precedence over timeZoneCode.
  • Time parameters — a timestamp that can’t be parsed now returns HTTP 400 (20012 INVALID_PARAMETER), with a message naming the offending value and the expected format, instead of HTTP 500 (20005).
New endpointsField changes

Agents V2 — Deactivate / Reactivate

Added two endpoints for managing an agent’s lifecycle without losing their data:
  • POST /v2.0/agents/{agentId}/deactivate — Releases the agent’s license seat and revokes all sessions and access tokens, while leaving their leads, deals, and data untouched. The caller needs MANAGE_TEAM_AGENT (or MANAGE_TEAM_AGENT_DEPARTMENT); the target can’t be the team owner, an office owner, or the caller.
  • POST /v2.0/agents/{agentId}/reactivate — Restores a deactivated agent’s access and re-occupies a seat (fails with SEAT_INSUFFICIENT if none are free).
Both endpoints always return HTTP 200 once authenticated — check the response body’s code field (absent or 0 means success) rather than the status. See Error Codes for the full list of failure codes.

Agents — Multi-license support

Agents can now hold up to 5 real estate license entries instead of one:
  • licenses (array of {label, value}) is now returned on GET /v1.0/me, GET /v1.0/users/{userId}, and GET /v1.0/members (both the paginated list and single-account lookup).
  • licenseId is now deprecated in favor of licenses.

Transactions V2 — Pipeline discovery & type filtering

  • Added GET /v2.0/transactions/pipelines — Returns each transaction type’s (Purchase, Listing, Lease, Other) configured stages, so you can look up valid status values instead of hardcoding team-specific stage names.
  • GET /v2.0/transactions gains a transactionType query parameter to filter by type, or All to return every type in one call. Defaults to Purchase; an unrecognized value now returns 400 (20012 INVALID_PARAMETER).
Field changes

Leads — remove tags on Update Lead

PUT /v1.0/leads/{leadId} gains two request fields for removing tags without resending the full list:
  • tagsRemove (string array) — removes the named tags from the lead. Names are matched literally; a name not currently on the lead is ignored. Applied after tags / tagsAdd.
  • clearAllTags (boolean, default false) — set to true to remove all tags from the lead. Takes precedence over tags / tagsAdd / tagsRemove.
Previously, removing a tag required replacing the entire tag set via tags.
New endpointsWebhooksField changesFixes
Added GET /v2.0/communication/agent — cursor-paginated search of an agent’s communications. Supports type=ALL to merge calls, texts, and emails; a query window of up to 90 days; and search_after-based pagination via an opaque cursor (replacing offset paging). The response includes data, nextCursor, hasMore, limit, and totalCount.

Webhooks — Ownership-based delivery

Added a permissionMode field on POST /v1.0/webhook:
  • 0 (default) — assignment-based delivery; unchanged behavior.
  • 1 — ownership-based delivery; the subscriber also receives callbacks for any lead within their ownership scope (team, office, or personally owned), not only assigned leads.

Field Changes

  • System Logs (GET /v1.0/systemLogs) — each entry now includes timelineTypeDesc, a human-readable event name paired with the integer timelineType, so you no longer need to map the integer yourself.

Fixes

  • Leads (GET /v1.0/leads) — the opportunity field is now correctly populated (it previously always returned empty).
New endpoints

Communications — single-record lookups

Added v2 endpoints to fetch a single communication by ID:
  • GET /v2.0/communication/call/{communicationId}
  • GET /v2.0/communication/text/{communicationId}
  • GET /v2.0/communication/email/{communicationId}
Single-record responses also surface manually-logged calls and their text content.
New endpointsField changesNew tools

Lofty CLI

Released @loftyai/lofty-cli — a command-line tool for the Lofty API. Manage leads, agents, listings, tasks, transactions, and more from your terminal.
See the Lofty CLI documentation for setup and command reference.Added GET /v2.0/transactions — paginated transaction search with keyword, lead, and date filters.

Lead Query Enhancements

New parameters for GET /v1.0/leads:
  • returnFields: Specify which fields to return (comma-separated), reducing payload size.
  • otherFilters: Pass custom LeadFilter overrides for advanced filtering.
  • key: Fuzzy search by name, phone, or email in a single parameter.

Field Changes

  • Calendar V2 — startTime / endTime now accept millisecond timestamps in addition to ISO 8601.
  • Manual Log (POST /v1.0/logType) — Added emailSubject, toEmail, fromEmail fields for email log entries.
  • Manual Log (POST /v1.0/logType) — The response now returns the created entry’s id.
  • Manual Log (GET /v1.0/logType) — Added sort / order parameters to control result ordering, and the response now includes the content field.
New endpointsNew featuresAuthentication

Sales Agents & AI

8 new endpoints for managing Sales Agent workflows:
  • GET /v2.0/sales-agents/by-lead — Get Sales Agent by lead ID
  • GET /v2.0/sales-agents/quota — Get current user’s quota
  • GET /PUT /v2.0/sales-agent/settings — Query and update settings
  • PUT /v2.0/sales-agents/working-lead/{leadId}/mute — Mute a working lead
  • POST /v2.0/working-leads/add — Batch add leads to working pool
  • POST /v2.0/plan-tasks/create — Batch create plan tasks

Intelligent Features (AI)

6 new AI-powered endpoints:
  • POST /v2.0/ai/call-script — Generate call script
  • GET /POST /v2.0/ai/call-summary — Get or trigger call summary generation
  • POST /v2.0/ai/prepare-insight — Generate prepare insight
  • GET /POST /v2.0/ai/lead-analysis — List or create lead analysis tasks

Calendar V2

Full CRUD + lifecycle management for calendar events:
  • GET /POST /v2.0/calendar — List and create events
  • PUT /DELETE /v2.0/calendar/{calendarId} — Update and delete events
  • POST finish/unfinish — Mark events as completed or reopen
  • GET /v2.0/calendar/meetings/available — List available meeting slots

Tasks V2 Enhancements

  • GET /v2.0/tasks/my-tasks — List tasks and appointments assigned to the current user
  • POST finish/unfinish — Mark tasks as completed or reopen

Lead Activity V2

  • GET /v2.0/leads/{leadId}/activities — Unified timeline with calls, texts, and emails in chronological order

Notifications

  • POST /v2.0/sales-agent/notification/app-push/send-task-reminder — Task reminder push
  • POST send-to-agent — Send system SMS or email to agent
  • POST /v2.0/sales-agent/ai-number/send-sms-to-agent — Send SMS via AI number

Agent Tags

  • POST /v1.0/agent/{agentId}/tag/add — Batch add tags with autoCreate support

Field Changes

  • Listing — Added propertyTypePrimary and propertyTypeSecondary to response
  • Note — Added noteId, noteType, idOfType fields
  • Calendar V2 — Added taskId field to calendar items

Authentication

  • Added OAuth 2.0 Client Credentials flow (/oauth/token) for server-to-server integrations
  • Added per-app rate limiting and token scope enforcement