Lists deals newest-moved first, paginated by cursor (limit up to 200). Filter by pipeline_id, status (open by default; won, lost, or all) and owner_id, or get the deals of one person (person_id: as their primary person or among their persons) or one company (company_id); with person_id or company_id the other filters are applied to the page read (pass status all to see every deal of that person or company). Each deal carries what it already stores about its activity: last_activity_at, last_inbound_at, last_outbound_at, next_booking_at and action_state (whose move it is). Archived deals are left out unless include_archived is true; merged-away duplicates never appear. A seller with restricted scope only gets the deals they can see. Those filters apply to the page that was read, so a page can bring fewer than limit (even none) while has_more is true: keep following next_cursor until has_more is false. Use crm.deals.get for a single deal and crm.pipelines.list for the stage names. With Google Ads, LinkedIn or TikTok, their terms limit it through the API and the MCP: what they do not allow answers 403 platform_terms_restricted, and their records or fields are left out of the response (the permissions guide lists what each platform allows).
Scope
crm:read
Permission
View the module
MCP tool
crm_deals_listOn the full surface; on the compact one, mb_execute_operation with id: "crm.deals.list".
Declared cost: up to 201 reads and 0 writes per call (they count against the daily quota).
Parameters
limitintegerqueryoptional
How many items this page brings at most (default 20, up to 200).
Default: 20
cursorstringqueryoptional
The next_cursor of the previous page, exactly as it came (only for the same list and filters); without it, the first page.
pipeline_idstringqueryoptional
Only the deals of this pipeline (crm.pipelines.list).
statusenumqueryoptional
open (default), won, lost or all.
Values: open, won, lost, all
owner_idstringqueryoptional
Only the deals of this owner: a member's user id or an AI position's ai-… id.
person_idstringqueryoptional
Only the deals of this person: as their primary person or among their persons.
company_idstringqueryoptional
Only the deals of this company.
include_archivedbooleanqueryoptional
Include archived records (left out by default; merged-away duplicates never come).
Returns a deal with its denormalized company and primary person, stage, status, value, labels and custom fields, and its activity: last_activity_at, last_inbound_at (the lead's last message, email or missed call), last_outbound_at, next_booking_at (the next confirmed meeting) and action_state (whose move it is, since action_since). Not found if the id does not exist or the seller's scope hides it. With Google Ads, LinkedIn or TikTok, their terms limit it through the API and the MCP: what they do not allow answers 403 platform_terms_restricted, and their fields are left out of the response (the permissions guide lists what each platform allows).
Scope
crm:read
Permission
View the module
MCP tool
crm_deals_getOn the full surface; on the compact one, mb_execute_operation with id: "crm.deals.get".
Declared cost: up to 2 reads and 0 writes per call (they count against the daily quota).
Parameters
deal_idstringpathrequired
The deal, by id (crm.deals.list or crm.search).
Response
idstring
org_idstring
titlestring
valuenumber
The deal amount, in currency.
currencystring
ISO 4217 code of value.
pipeline_idstring
stage_idstring
statusenum
Values: open, won, lost
created_atnumber
updated_atnumber
stage_moved_atnumber
When the deal last changed stage, epoch ms.
stage_entered_atobject
When the deal first entered each stage it went through: stage id → epoch ms.
probabilitynumber
Win probability 0-100: the stage's, unless probability_overridden.
probability_overriddenboolean
true when the probability was set by hand (closing a deal sets 100 or 0 this way); false when it follows the stage.
expected_close_datenumber | null
Expected close date, epoch ms.
owner_idstring | null
The owner: a member's user id (members.members.list), or an AI position's ai-… id.
owner_namestring | null
The name of the owner, resolved when the record is read.
company_idstring | null
company_namestring | null
countrystring | null
ISO-2 country of the deal (its company's, otherwise its main contact's).
person_idsarray<string>
The deal's persons; the main contact is one of them.
primary_person_idstring | null
primary_person_namestring | null
primary_person_emailstring | null
primary_person_phonestring | null
label_idsarray<string>
custom_fieldsobject
won_atnumber | null
lost_atnumber | null
closed_atnumber | null
status_changed_atnumber | null
When the status last changed (won, lost or reopened), server time, epoch ms. Unlike won_at (the close date chosen by whoever marked it, which can be edited later), nobody edits it. Absent on deals whose status changed before 2026-10-13.
lost_reason_idstring | null
The lost reason (one of the pipeline's lostReasons).
lost_reason_notestring | null
rotting_stateenum | null
fresh, warning (two thirds of the stage's rotting days without moving) or rotting.
Values: fresh, warning, rotting
open_activity_countnumber | null
Pending tasks, calls and meetings of the deal.
overdue_activity_countnumber | null
Of those, the ones already past their due date.
source_channelstring | null
Where the deal came from: meta, google, tiktok, linkedin, whatsapp, web, manual, csv…
source_idstring | null
The lead source (crm.lead_sources.list).
external_lead_idstring | null
The lead id of the ads platform (Meta leadgen id, TikTok lead id).
submitted_atnumber | null
When the person submitted the lead form (platform time), epoch ms.
attributionobject | null
ai_scorenumber | null
The AI score 0-100 (ai_scoring.score).
ai_scoringobject | null
mrrnumber | null
Monthly recurring revenue from the quote's monthly lines, in currency.
line_itemsarray<object> | null
The quote's lines (crm.deals.update_quote), in currency.
total_discountnumber | null
total_discount_typeenum | null
Values: percent, amount
is_starredboolean
is_archivedboolean
archived_atnumber | null
merged_into_idstring | null
Set on a duplicate absorbed by a merge: the deal that kept it (lists never return these).
last_activity_atnumber | null
Last activity on the deal: an activity logged on it (note, task, call, meeting) or a message or email exchanged, epoch ms.
last_inbound_atnumber | null
Last contact FROM the lead (WhatsApp, a direct message, an email or a missed inbound call), epoch ms.
last_outbound_atnumber | null
Last contact TO the lead (a message, an email, a call or a sequence step), epoch ms.
next_booking_atnumber | null
The nearest confirmed meeting ahead, epoch ms; null or absent when there is none.
action_stateenum | null
Whose move it is: waiting_us (the lead wrote last), act_new (never contacted), overdue_task (a task or follow-up is overdue), scheduled (a meeting ahead), waiting_them (we wrote last) or none (closed or no signal). Recomputed on every message, booking, activity and call, and once a day.
Since when the deal is in its action_state, epoch ms; for scheduled, the time of the meeting (it can be in the future).
from_prospect_idstring | null
The inbox prospect this deal is the conversion of (crm.prospects.convert, or crm.deals.create with from_prospect_id): its history was linked to the deal.
linked_from_deal_idstring | null
The previous deal this one follows (a recurring or returning opportunity): set by «Create new deal» on a deal that came back, or by crm.deals.create. Traceability only: nothing was moved or copied from it.
linked_from_prospect_idstring | null
The previous prospect this deal follows (a returning lead), like linked_from_deal_id. Traceability only: unlike from_prospect_id, the deal is not that prospect converted.
created_by_idstring | null
Who created the deal: a member's user id (members.members.list), or an AI position's ai-… id.
created_by_namestring | null
The name of who created the deal, resolved when the record is read.
Returns the changelog of a deal (stage and pipeline changes, value, owner, won/lost/reopened, labels, persons, custom fields), newest first, paginated by cursor. field names the deal field that changed as it is published (stage_id, owner_id, custom_fields.<slug>). metadata.reason carries the reason given when persons were added or removed (crm.deals.persons.add or remove) and the handoff reason of an AI position. A seller with restricted scope gets an empty list for a deal that is not theirs (as in the app). Use it to understand what happened before acting on a deal. With Google Ads, LinkedIn or TikTok, their terms limit it through the API and the MCP: what they do not allow answers 403 platform_terms_restricted, and their fields are left out of the response (the permissions guide lists what each platform allows).
Scope
crm:read
Permission
View the module
MCP tool
crm_deals_events_listOn the full surface; on the compact one, mb_execute_operation with id: "crm.deals.events.list".
Declared cost: up to 103 reads and 0 writes per call (they count against the daily quota).
Parameters
deal_idstringpathrequired
The deal, by id (crm.deals.list or crm.search).
limitintegerqueryoptional
How many items this page brings at most (see the maximum and the default in the schema).
Default: 100
cursorstringqueryoptional
The next_cursor of the previous page, exactly as it came (only for the same list and filters); without it, the first page.
Creates a deal in a pipeline stage (the stage must belong to that pipeline: stage_not_in_pipeline) with an owner (owner_id, a member; without it the deal belongs to the caller), optional company, primary person and other persons, value (0 by default) and currency (the pipeline's by default), labels and custom fields. The primary person is always one of the deal's persons (without primary_person_id, the first of person_ids becomes it). Labels must be deal labels of the organization (label_not_found) and each custom field value must match its field (custom_field_unknown, custom_field_invalid). The probability is the stage's unless you send one (then it is kept as set by hand). A new deal starts with action_state act_new and is recomputed from its persons' history right after. Attribution is inherited from the primary person when they came from paid media. After responding, the activities, conversations and messages already linked to its persons and company are linked to the new deal too; link_existing_activity none skips that. For traceability, linked_from_deal_id or linked_from_prospect_id name the previous deal or prospect this one follows (saved on the deal and on its created event; nothing is copied). from_prospect_id means the deal is that inbox prospect converted (its history comes along and the event says converted): prefer crm.prospects.convert for that, and never send it together with linked_from_prospect_id (prospect_origin_conflict). Every origin must exist in the organization (deal_not_found, prospect_not_found). Requires create_deal. A seller with restricted scope creates only their own deals (owner_id omitted or their own uid), in any pipeline, as on the screen: a deal for someone else is denied with crm_action_denied. They can only link persons and a company they can already see (their own, unassigned, or of a deal of theirs), and only name origins they can see; any other is not found (person_not_found, company_not_found, deal_not_found, prospect_not_found). With from_prospect_id, as in crm.prospects.convert, they cannot convert a prospect that is not theirs when its person or company belongs to someone else and is outside what they can see: 403 prospect_contact_not_visible and no deal is created.
Scope
crm:write
Permission
Edit in the module
MCP tool
crm_deals_createOn the full surface; on the compact one, mb_execute_operation with id: "crm.deals.create".
Declared cost: up to 111 reads and 3 writes per call (they count against the daily quota).
Parameters
titlestringbodyrequired
The deal's name, as the board shows it.
pipeline_idstringbodyrequired
The pipeline, by id (crm.pipelines.list).
stage_idstringbodyrequired
A stage of that pipeline, by id (crm.pipelines.get lists them); another pipeline's stage is stage_not_in_pipeline.
valuenumberbodyoptional
The deal amount, in currency (0 by default).
currencystringbodyoptional
ISO 4217 code of value (USD, ARS…); by default the pipeline's currency (crm.pipelines.get).
owner_idstringbodyoptional
The owner, a member's user id (members.members.list or crm.team.list); without it the deal belongs to the caller.
company_idstringbodyoptional
The company, by id (crm.companies.list or crm.search).
primary_person_idstringbodyoptional
The deal's main contact, by id (crm.persons.list, crm.persons.lookup or crm.search). It is always one of the deal's persons; without it, the first of person_ids becomes the main contact.
person_idsarray<string>bodyoptional
The deal's persons, by id; the main contact is added if missing.
probabilitynumberbodyoptional
Win probability 0-100, set by hand; without it, the stage's probability (and it follows the stage when the deal moves).
expected_close_dateintegerbodyoptional
Expected close date, epoch ms.
label_idsarray<string>bodyoptional
Deal labels, by id (crm.labels.list with entity deal).
custom_fieldsobjectbodyoptional
Custom field values by key (the slug of crm.custom_fields.list with entity deal).
source_channelstringbodyoptional
Where the deal came from (meta, google, tiktok, linkedin, whatsapp, web, manual…); inherited from the main contact when they came from paid media.
source_idstringbodyoptional
The lead source, by id (crm.lead_sources.list).
from_prospect_idstringbodyoptional
The inbox prospect this deal is the conversion of: the deal's created event says converted and, with link_existing_activity all, the prospect's history is linked to the deal too. It must exist in this organization and, for a seller with restricted scope, be one she can see (her own, unassigned or an AI position's); otherwise prospect_not_found. Prefer crm.prospects.convert, which also marks the prospect converted.
linked_from_deal_idstringbodyoptional
The previous deal this one follows (a recurring or returning opportunity), for traceability: saved on the new deal and on its created event. Nothing is moved or copied from it. It must exist in this organization and, for a seller with restricted scope, be one she can see; otherwise deal_not_found.
linked_from_prospect_idstringbodyoptional
The previous prospect this deal follows (a returning lead), for traceability, like linked_from_deal_id; otherwise prospect_not_found. Not from_prospect_id, which means the deal IS that prospect converted: send one or the other (prospect_origin_conflict).
link_existing_activityenumbodyoptional
all (default): after responding, the activities, conversations and messages already linked to the deal's persons and company (and to from_prospect_id) are linked to the new deal too, so its timeline shows that history. none: the new deal starts with an empty timeline and nothing else is touched.
Updates one or more fields of a deal: title, value, currency, probability, expected close date, owner (member or AI position), company, primary person, persons, labels, custom fields, stage, pipeline or kanban position. person_ids and custom_fields replace the whole list or map: to add or remove persons use crm.deals.persons.add / remove, and to change some custom fields use merge_custom_fields (only the keys sent; null deletes one). Changing the stage or pipeline also requires move_stage / change_pipeline, and the resulting stage must belong to the resulting pipeline (stage_not_in_pipeline; moving to another pipeline needs one of its stages). A probability sent is kept as set by hand (probability_overridden becomes true); without one, a deal that changes stage takes the new stage's probability unless it was set by hand, and probability_overridden false puts it back to its stage's. The primary person is always one of the deal's persons: a person_ids list without it keeps it (change it with primary_person_id, remove it with crm.deals.persons.remove). Labels added must be deal labels of the organization (label_not_found) and custom field values that change must match their field (custom_field_unknown, custom_field_invalid). Editing won_at requires mark_won and a won deal. A stage, pipeline or kanban position equal to the current one is not a change: if nothing else changes, nothing is written or audited and changed comes back false. A seller with restricted scope can only add persons or a company they can already see (their own, unassigned, or of a deal of theirs); any other is not found (person_not_found, company_not_found). Making an AI position (ai-…) the owner starts its first turn right away (it may write to the lead; not when the deal's primary person is marked «Do not contact» or unsubscribed: the AI never writes first to them and waits, with next_run_reason do_not_contact, until they write) and counts as one AI call: outside the app that change needs a dry run and its confirm_token (any other update runs directly), and in the practice organization of test keys it fails with 409 sandbox_external_unavailable and nothing changes. Without AI credits for that first turn in the organization's pool (or with the subscription that pays them blocked), the turn does not call the AI and writes to no one: the deal goes at once to the position's escalation person (or to whoever the lead source's assignment rule picks), and the deal returned already shows that person as its owner. Returns the deal as saved. With Google Ads, LinkedIn or TikTok, their terms limit it through the API and the MCP: what they do not allow answers 403 platform_terms_restricted, and their fields are left out of the response (the permissions guide lists what each platform allows).
Needs confirmation: first dry_run: true (preview and confirm_token, valid 10 minutes and for one run), then the same body with confirm_token. In a few operations only with certain data: the description says when. Why and how: Dry run and confirm_token. In this one, only when: the owner changes to an AI position (owner_id ai-…): its first turn runs right away and it may write to the lead.
Scope
crm:write
Permission
Edit in the module
MCP tool
crm_deals_updateOn the full surface; on the compact one, mb_execute_operation with id: "crm.deals.update".
Moves a deal to a stage (and optionally to another pipeline). Stage ids belong to a pipeline: when moving across pipelines pass both; a stage of another pipeline, or one that does not exist, is stage_not_in_pipeline (400, with the stage ids of the pipeline in details). The deal takes the new stage's probability unless it was set by hand (probability_overridden). This is the same path as dragging the card in the kanban and triggers conversions and sequence triggers. Moving a deal to the stage it is already in changes nothing (changed false: the time in stage is not reset, no history entry, no audit); with a new kanban_order it only reorders the card within its column. To mark a deal won or lost use crm.deals.mark_won / crm.deals.mark_lost instead. With Google Ads, LinkedIn or TikTok, their terms limit it through the API and the MCP: what they do not allow answers 403 platform_terms_restricted, and their fields are left out of the response (the permissions guide lists what each platform allows).
Scope
crm:write
Permission
Edit in the module
MCP tool
crm_deals_moveOn the full surface; on the compact one, mb_execute_operation with id: "crm.deals.move".
Adds 1 to 20 persons to a deal without sending the whole list (crm.deals.update with person_ids replaces it, and two concurrent changes overwrite each other). Persons the deal already has are left as they are (already_linked); a person absorbed by a merge is followed to the record that kept it. If the deal had no primary person, the first one added becomes its primary person, with their name, email and phone, as on the deal page. reason (one line) is saved on each person_added event of the deal's history (metadata.reason) and in the audit. Idempotent: adding persons the deal already has writes nothing. Requires edit_deal. A person that does not exist is person_not_found; a seller with restricted scope can only add persons they can already see (their own, unassigned, or of a deal of theirs), any other is person_not_found too. A deal absorbed by a merge is deal_merged (409). Emits crm.deal.updated. With Google Ads, LinkedIn or TikTok, their terms limit it through the API and the MCP: what they do not allow answers 403 platform_terms_restricted, and their fields are left out of the response (the permissions guide lists what each platform allows).
Scope
crm:write
Permission
Edit in the module
MCP tool
crm_deals_persons_addOn the full surface; on the compact one, mb_execute_operation with id: "crm.deals.persons.add".
Declared cost: up to 85 reads and 25 writes per call (they count against the daily quota).
Parameters
deal_idstringpathrequired
The deal, by id (crm.deals.list or crm.search).
person_idsarray<string>bodyrequired
The persons, by id (1 to 20). A person absorbed by a merge is followed to the record that kept it.
reasonstringbodyoptional
Why, in one line (up to 500 characters): who introduced the person or asked to write to them. Saved on the deal's history events (metadata.reason) and in the audit.
Response
dealobject
addedarray<string>
The persons added (the record that kept a merged-away person).
already_linkedarray<string>
The persons the deal already had (in its list or as its primary person): left as they were.
Removes 1 to 20 persons from a deal without sending the whole list. Persons the deal does not have come back in not_linked; a merged-away person is followed to the record that kept it, and an id that is not a person of the organization is person_not_found (an id the deal still lists is removed even if the person no longer exists). For a seller with restricted scope, a person the deal does not have and they cannot see is person_not_found too. Removing the primary person makes the next person in the list the primary one (or leaves the deal without one), as on the deal page. reason (one line) is saved on each person_removed event (metadata.reason; every person that leaves gets one, also a primary person the deal did not list among its persons), on the primary_person_change it causes and in the audit. Idempotent: removing persons the deal does not have writes nothing. Requires edit_deal. A deal absorbed by a merge is deal_merged (409). Emits crm.deal.updated. With Google Ads, LinkedIn or TikTok, their terms limit it through the API and the MCP: what they do not allow answers 403 platform_terms_restricted, and their fields are left out of the response (the permissions guide lists what each platform allows).
Scope
crm:write
Permission
Edit in the module
MCP tool
crm_deals_persons_removeOn the full surface; on the compact one, mb_execute_operation with id: "crm.deals.persons.remove".
Declared cost: up to 85 reads and 25 writes per call (they count against the daily quota).
Parameters
deal_idstringpathrequired
The deal, by id (crm.deals.list or crm.search).
person_idsarray<string>bodyrequired
The persons, by id (1 to 20). A person absorbed by a merge is followed to the record that kept it.
reasonstringbodyoptional
Why, in one line (up to 500 characters): who introduced the person or asked to write to them. Saved on the deal's history events (metadata.reason) and in the audit.
Response
dealobject
removedarray<string>
The persons removed from the deal.
not_linkedarray<string>
The persons the deal did not have: nothing to remove.
Sets, replaces or clears (null) the external_lead_id: the lead id assigned by the ads platform (Meta leadgen id, TikTok lead id…) used to send offline conversions back and as the dedup key of lead imports. Change it deliberately. Requires edit_deal.
Scope
crm:write
Permission
Edit in the module
MCP tool
crm_deals_set_external_lead_idOn the full surface; on the compact one, mb_execute_operation with id: "crm.deals.set_external_lead_id".
Declared cost: up to 1 reads and 1 writes per call (they count against the daily quota).
Parameters
deal_idstringpathrequired
The deal, by id (crm.deals.list or crm.search).
external_lead_idstring | nullbodyrequired
The lead id of the ads platform (Meta leadgen id, TikTok lead id); null clears it.
Marks a deal won: status, probability 100, won_at (now, or a past date passed in won_at), action_state none, and optionally moves it to the pipeline's won stage (won_stage_id must be the stage marked as won in its pipeline, from crm.pipelines.get: any other is won_stage_invalid). Triggers conversions and sequence exits. Requires mark_won. Returns the deal as saved. With Google Ads, LinkedIn or TikTok, their terms limit it through the API and the MCP: what they do not allow answers 403 platform_terms_restricted, and their fields are left out of the response (the permissions guide lists what each platform allows).
Scope
crm:write
Permission
Edit in the module
MCP tool
crm_deals_mark_wonOn the full surface; on the compact one, mb_execute_operation with id: "crm.deals.mark_won".
curl-X POST "https://api.mb-suite.com/v1/crm/deals/{deal_id}/won" \
-H"Authorization: Bearer $MB_API_KEY"
Try it with your test API key
With a test API key the request always goes to your practice organization: example data you can reset.
curl-X POST "https://api.mb-suite.com/v1/crm/deals/{deal_id}/won" \
-H"Authorization: Bearer $MB_TEST_KEY"
POST/v1/crm/deals/{deal_id}/lost
Mark a deal as lost
crm.deals.mark_lost
WriteSince 2026-11-01
Marks a deal lost with an optional lost reason and note. lost_reason_id must be an active lost reason of the deal's pipeline (crm.pipelines.get lists them): any other is lost_reason_not_found. The deal keeps its stage (where it fell is a reporting fact) and its action_state becomes none. Triggers conversions and sequence exits. Requires mark_lost. With Google Ads, LinkedIn or TikTok, their terms limit it through the API and the MCP: what they do not allow answers 403 platform_terms_restricted, and their fields are left out of the response (the permissions guide lists what each platform allows).
Scope
crm:write
Permission
Edit in the module
MCP tool
crm_deals_mark_lostOn the full surface; on the compact one, mb_execute_operation with id: "crm.deals.mark_lost".
curl-X POST "https://api.mb-suite.com/v1/crm/deals/{deal_id}/lost" \
-H"Authorization: Bearer $MB_API_KEY"
Try it with your test API key
With a test API key the request always goes to your practice organization: example data you can reset.
curl-X POST "https://api.mb-suite.com/v1/crm/deals/{deal_id}/lost" \
-H"Authorization: Bearer $MB_TEST_KEY"
POST/v1/crm/deals/{deal_id}/reopen
Reopen a won or lost deal
crm.deals.reopen
WriteSince 2026-11-01
Reopens a won or lost deal into a stage of its pipeline (any other stage is stage_not_in_pipeline; an open deal is deal_not_closed, 409), clearing won_at, lost_at, closed_at and the lost reason. The deal goes back to the stage's probability (probability_overridden false: closing had set 100 or 0) and its action_state is recomputed from its history right after. Requires reopen_deal. Returns the deal as saved. With Google Ads, LinkedIn or TikTok, their terms limit it through the API and the MCP: what they do not allow answers 403 platform_terms_restricted, and their fields are left out of the response (the permissions guide lists what each platform allows).
Scope
crm:write
Permission
Edit in the module
MCP tool
crm_deals_reopenOn the full surface; on the compact one, mb_execute_operation with id: "crm.deals.reopen".
Archives (archived: true) or restores (false) a deal. An archived deal keeps its status and stage but leaves every list, forecast and report; this is NOT the trash (see crm.deals.delete). Sequences set to exit when the deal is archived take its enrollments out (off by default). Idempotent: nothing changes if the deal is already in that state. Requires edit_deal. With Google Ads, LinkedIn or TikTok, their terms limit it through the API and the MCP: what they do not allow answers 403 platform_terms_restricted, and their fields are left out of the response (the permissions guide lists what each platform allows).
Scope
crm:write
Permission
Edit in the module
MCP tool
crm_deals_archiveOn the full surface; on the compact one, mb_execute_operation with id: "crm.deals.archive".
Marks a deal as starred (a visual flag that enables the 'only starred' filter) or removes the star. Idempotent. Requires edit_deal. With Google Ads, LinkedIn or TikTok, their terms limit it through the API and the MCP: what they do not allow answers 403 platform_terms_restricted, and their fields are left out of the response (the permissions guide lists what each platform allows).
Scope
crm:write
Permission
Edit in the module
MCP tool
crm_deals_set_starredOn the full surface; on the compact one, mb_execute_operation with id: "crm.deals.set_starred".
Declared cost: up to 1 reads and 1 writes per call (they count against the daily quota).
Replaces the deal's quote: line items (product, unit price, quantity, discount, frequency one_time or monthly, tax) and a global discount. The server recomputes value and mrr from the lines; an empty line_items array clears the quote and keeps the manual value. Requires edit_deal.
Scope
crm:write
Permission
Edit in the module
MCP tool
crm_deals_update_quoteOn the full surface; on the compact one, mb_execute_operation with id: "crm.deals.update_quote".
Deletes a deal. It goes to the 30-day trash (owners and admins can restore it from CRM settings → Trash); its activities and conversations are kept and unlinked. Prefer crm.deals.archive when the deal should just leave the lists. Requires delete_deal (a seller with scope only deletes their own).
With an API key, this DELETE runs directly: the record stays 30 days in the trash and the response carries its trash_item_id. With an OAuth token, and through the MCP, it needs dry_run → confirm_token.
Scope
crm:writeand “Allow deletions” (crm:delete in OAuth)
Permission
Edit in the module
MCP tool
crm_deals_deleteOn the full surface; on the compact one, mb_execute_operation with id: "crm.deals.delete".
Adds and/or removes labels (ids from crm.labels.list with entity deal) on up to 500 deals at once. A label that is not a deal label of the organization is label_not_found (with details.unknown_ids). Deals that already have exactly those labels are left as they are (unchanged) and ids that do not exist are skipped (not_found). The dry run reads the same deals and names those that would change. Manager-tier only (owner, admin, crm_admin or sales_manager). Bulk: outside the screen it requires a dry run and a confirm_token.
Needs confirmation: first dry_run: true (preview and confirm_token, valid 10 minutes and for one run), then the same body with confirm_token. In a few operations only with certain data: the description says when. Why and how: Dry run and confirm_token.
Scope
crm:write
Permission
Edit in the module
MCP tool
crm_deals_bulk_update_labelsOn the full surface; on the compact one, mb_execute_operation with id: "crm.deals.bulk.update_labels".
Declared cost: up to 540 reads and 1000 writes per call (they count against the daily quota).
Parameters
deal_idsarray<string>bodyrequired
The deals (up to 500), by id (crm.deals.list).
to_addarray<string>bodyoptional
Label ids to add (crm.labels.list with entity deal), up to 20; send to_add, to_remove or both.
to_removearray<string>bodyoptional
Label ids to remove (crm.labels.list with entity deal), up to 20; send to_add, to_remove or both.
Response
updatednumber
How many deals changed.
unchangednumber
How many deals already were that way: not written.
not_foundarray<string>
The ids that do not exist in the organization (or are merged-away duplicates): skipped.
Sets the owner of up to 500 deals to a member (new_owner_id, from members.members.list or crm.team.list) and notifies them once. Deals that already belong to that owner are left as they are (unchanged); ids that do not exist in the organization are skipped and come back in not_found; updated counts the reassigned ones. The dry run reads the same deals and names those that would change. Manager-tier only. Bulk: outside the screen it requires a dry run and a confirm_token.
Needs confirmation: first dry_run: true (preview and confirm_token, valid 10 minutes and for one run), then the same body with confirm_token. In a few operations only with certain data: the description says when. Why and how: Dry run and confirm_token.
Scope
crm:write
Permission
Edit in the module
MCP tool
crm_deals_bulk_reassignOn the full surface; on the compact one, mb_execute_operation with id: "crm.deals.bulk.reassign".
Declared cost: up to 500 reads and 500 writes per call (they count against the daily quota).
Parameters
deal_idsarray<string>bodyrequired
The deals (up to 500), by id (crm.deals.list).
new_owner_idstringbodyrequired
The new owner: a member's user id (members.members.list or crm.team.list).
Response
updatednumber
How many deals changed.
unchangednumber
How many deals already were that way: not written.
not_foundarray<string>
The ids that do not exist in the organization (or are merged-away duplicates): skipped.
Moves up to 500 deals to a stage of a pipeline (both ids required; the stage must belong to that pipeline, otherwise stage_not_in_pipeline) with the same effects as moving them one by one (history, conversions, sequence triggers, run in series after responding). Each moved deal takes the stage's probability unless it was set by hand (probability_overridden). Deals already in that stage of that pipeline are left as they are (their time in stage is not reset, no history entry) and counted in unchanged; ids that do not exist are skipped (not_found). The dry run reads the same deals and names those that would move. Manager-tier only. Bulk: outside the screen it requires a dry run and a confirm_token.
Needs confirmation: first dry_run: true (preview and confirm_token, valid 10 minutes and for one run), then the same body with confirm_token. In a few operations only with certain data: the description says when. Why and how: Dry run and confirm_token.
Scope
crm:write
Permission
Edit in the module
MCP tool
crm_deals_bulk_moveOn the full surface; on the compact one, mb_execute_operation with id: "crm.deals.bulk.move".
Deletes up to 500 deals; each one goes to the 30-day trash and can be restored individually (platform.trash.list). deleted counts the deals that existed; the other ids come back in not_found. Manager-tier only, and the matrix must allow delete_deal. Outside the screen it requires a dry run and a confirm_token.
Needs confirmation: first dry_run: true (preview and confirm_token, valid 10 minutes and for one run), then the same body with confirm_token. In a few operations only with certain data: the description says when. Why and how: Dry run and confirm_token.
Scope
crm:writeand “Allow deletions” (crm:delete in OAuth)
Permission
Edit in the module · CRM action: delete_deal
MCP tool
crm_deals_bulk_deleteOn the full surface; on the compact one, mb_execute_operation with id: "crm.deals.bulk.delete".