Menú
Recursos
Registro de cambios
La API se versiona por fecha. Cada organización queda fijada en la versión con la que creó su primera API key; un pedido puede pedir otra viva con MB-Version. Un cambio que rompe sale siempre en una versión nueva, y la anterior sigue viva 12 meses.
Los cambios se publican en inglés.
2026-11-01
VigentePublicada el 2026-11-01- First public version of the MB Suite API: the CRM, the platform (keys, webhooks, trash, me, catalog), the organization's accounts, and every module that gets its operations registered during the rollout.
- snake_case everywhere; cursor pagination with
limit,cursor,has_moreandnext_cursor; one error format with a stablecode;Idempotency-Keyon POST, PATCH and DELETE; irreversible and bulk operations needdry_run+confirm_tokenexcept the simple DELETE of a restorable record. - Before its release (2026-10-15), this version changed for the early integrations in the ways listed next; they are part of 2026-11-01, not of a new version.
- Writes that send or change something outside MB Suite (an email, a WhatsApp message or SMS, a post or a reply on a network, a change in Meta or in another platform where its terms allow it through the API, a domain), that have a separate cost (AI, DataForSEO, a crawl), or that leave a send scheduled or switched on (a scheduled campaign or report, an activated flow, an enrollment into an active sequence) now need
dry_run+confirm_tokenthrough the API and the MCP, like bulk and irreversible operations (x-mb-confirm: always). Without the token the call is 409confirmation_required, withdetails.external(the platform) anddetails.effect(sends,sends_laterorpays). - A few of them need it only with certain data (
x-mb-confirm: conditional, the condition inx-mb-confirm-when;needs_confirmation_whenin the MCP), and without that data they run directly:seo_rankings.keywords.addandseo_rankings.keywords.importwhenfetch_search_volumeis true;members.invitations.createwhensend_emailis true;crm.deals.updateandcrm.prospects.updatewhen the owner changes to an AI position, andcrm.prospects.createwhen it is created with one;crm.conversions.config.set_enabledandsocial_inbox.positions.set_enabledwhen they switch it on;social_inbox.rules.set_enabledwhen it switches on a rule that replies by itself;social_inbox.positions.createandsocial_inbox.rules.createwhen the position, or a rule that replies, is created on;crm.ai_team.positions.createwhen the position is created on (payload.enabledtrue: created off, the default, it attends no one and runs directly);social_inbox.positions.updateandsocial_inbox.rules.updatewhen the change turns on a position that was off or switches a Community Manager that is on toauto_reply, or leaves answering by itself a rule that was not;deliveries.deliveries.createwhen it is created with aschedule. dry_run: trueworks on any write, through the REST API too (it was 400dry_run_not_supportedoutside bulk, irreversible and confirmable operations): it writes nothing, returns the operation's own preview or a generic one, and itsneeds_confirmationsays whether running it needs theconfirm_token. A read has no dry run: 400dry_run_not_supported, also through the MCP.- Inputs are strict: a field the operation does not declare, at any depth, is 400
unknown_field(paramnames the first one anddetails.unknown_fieldsall of them) instead of being silently dropped, so a misspelled filter never returns an unfiltered list and an update never answersokwithout changing anything. Maps (custom fields, headers, ids used as keys) and open objects still take any key, exceptscopeof the Social Inbox positions, which takes only its sources; the contract and the MCP schemas mark the strict objects withadditionalProperties: false. Acursorthat is not thenext_cursorof the same list is 400invalid_cursor. - In most operations the output carries only what its schema declares: undeclared fields (the organization repeated inside each record such as
organization_id, storage paths, ordering and normalization helpers) no longer come out. Internal fields (search indexes, denormalized access lists, locks) never come out, in any operation. - Renamed fields:
media_planner.templates.listandgetgive a system template's place asorder(it wasposition), like the organization's own templates;organizations.ai_usage.getgivesagents[].configured_model(it wasmodel);monitors.cross_account.getgroups its metrics asplatforms[].metrics(it wassections[].metrics);media_planner.cross_account.overviewgivesaccounts[].account_idandaccount_name(they wereorg_idandorg_name);alerts.history.listgives and filters byalert_id(it wasalert_config_id). - WhatsApp is one word in field names:
reminder_whatsappandon_whatsapp_replyin inputs (the oldreminder_whats_appandon_whats_app_replyare still accepted), andconfirmation_whatsapp_sent_at,dnd_whatsapp,whatsapp_soundandlast_seen_whatsapp_atin outputs. - Lists that now return a summary per row, with the whole record in their
get:crm.reengagement.listandweb_forms.forms.list(without each form'sfieldsandauto_responder). crm.ai_team.states.listandcrm.ai_team.states.getgivegoal_progress.fields_capturedas a map by the position's field keys (it was a list).- Defaults that changed:
fetch_search_volumeofseo_rankings.keywords.addandseo_rankings.keywords.importis false (fetching it is paid); a lead source created through the API hasai_qualification.enabledfalse unless it is sent (the AI scoring is paid);web_forms.forms.createleaves the form as a draft (enabledfalse) unless it is sent; and some lists return a smaller page whenlimitis left out: 20 incrm.deals.list,crm.persons.list,crm.prospects.list,crm.my_leads.listandcrm.lists.members.list; 25 inactivity.entries.list,crm.conversations.list,crm.calls.list,crm.sequences.enrollments.list,social_inbox.items.listandtask_management.tasks.list; 50 incrm.lead_sources.list. - Outputs that can come as null: a media plan's
total_budgetandtotal_spent(also in its webhook events) are null when the plan has amounts in more than one currency: readbudget_by_currency. Output schemas also declare as nullable the fields that can come empty. - A deletion that keeps a copy returns
trash_item_id(andtrash_item_idswhen it leaves more than one) withtrash_expires_at;platform.trash.restoretakes that id, orentity_type+entity_id. - Through the MCP,
idempotency_key(next toidinmb_execute_operation, or as an argument of each typed write tool) does what theIdempotency-Keyheader does in the REST API: the same key with the same call returns the stored result instead of running it again. crm.lead_sources.listno longer returns the webhook secret of each source:crm.lead_sources.getreturns it, one source at a time, to whoever can manage sources (never through the MCP).- Behavior that changed:
crm.assignment_rules.deletewith an id that does not exist is 404 (it answeredok);dashboards.inherited_explorer_views.removeof a view that is no longer inherited returnsremoved: false;child_orgs_countleaves out deleted Accounts;task_management.packs.applyno longer counts subtasks intasks_created;deliveries.deliveries.updatemergesemail_configwith the saved one field by field (nullclears a field) instead of replacing it whole. A send that starts the contact with a CRM person marked «Do not contact» or unsubscribed, which used to go out, is now refused before anything is sent with 409do_not_contact(details.recipientsanddetails.overridable):crm.email.send(the person found by any email in to or cc),crm.whatsapp.send_templateandcrm_phones.sms.send(found by the number). Only a person of the team can confirm it, withdo_not_contact_overrideon a closedbasis(transactional: about their account, a charge or support;requested_by_person: they asked us to write) and, outside the app, areason(400do_not_contact_reason_requiredwithout it); an AI agent's API key cannot (403do_not_contact_override_not_allowed), and a marketing WhatsApp template never goes to them, confirmed or not. A reply to what the person wrote after being marked still goes out, and the response says so indo_not_contact.crm.exports.createwrites a cell that a spreadsheet would read as a formula (one that starts with=,+,-or@, numbers and phones aside) with a leading', and fills adaterangecustom field with itsfromandto; a cell that already starts with apostrophes before a formula character gets one more ('=xis written''=x), andcrm.imports.createremoves that one apostrophe (a cell'@userimports as@user; it imported'@user).crm.exports.createtakesheadersfor deals too (it was 400; prospects still reject it): withlabelsthe header row has the deal table's column names in your language,statusandrottingcome in your language and checkbox custom fields as yes/no. In its deal CSVs,owneris the member's current name or, without one, the name stored on the deal (it fell back to the user id, which stays in theownerIdcolumn), user, member and members custom fields come by name (they came as user ids), andprobabilityis the one the forecast uses: the stage's unless it was set by hand (closed deals keep theirs). Persons and companies withheaders: labelsname the email, phone, last-modified, unsubscribe and bounce columns Email, Phone, Last modified, Unsubscribed date and Bounced date (they were Primary email, Primary phone, Updated, Unsubscribed and Bounced).crm.deals.updateandcrm.deals.movekeep a won or lost deal's probability when it changes stage or getsprobability_overridden: false(it took the stage's). - The AI teams of the CRM and the Social Inbox:
crm.ai_team.positions.createandcrm.ai_team.positions.updatereject anai_agent_idthat is not a saved agent of the organization (a draft neither) nor an MB Suite agent that exists and is not hidden (400ai_agent_not_found), or whose channel is notwhatsapp_crm(400ai_agent_not_eligible); they saved it.social_inbox.positions.createandsocial_inbox.positions.updategive 400ai_agent_not_eligiblefor a Community Manager agent whose channel is notsocial, and reject a source inscopethat does not exist (400invalid_input; it was dropped silently). They all check the agent only when it changes.ai_agent_not_foundcomes as 400invalid_requestwhen a write names an agent that is not there, and as 404 when reading or deleting one.crm.ai_team.positions.createis 409limit_reachedpast 25 AI positions per organization, as duplicating already was. Withinclude_brain,crm.ai_team.positions.getresolves the brain as the position's AI does on each turn: an MB Suite agent chosen as its own and, without a usable one, the organization's default agent for its type, withchosen_in(position,areasortype_default); for the same data, the agent andconfigured_agent_missingcan differ from before. crm.attribution.web_trackingcounts indeals,won(andtotal_deals,total_wonandconversion_rate) the deals generated by the leads of each group, the WhatsApp conversations and Web Forms submissions matched in the period: in the group of their lead, once each (the first lead of the period gets it), a prospect when converted, a merged deal as the deal it was merged into; archived deals and the earlier deal a returning contact lands in are left out. It counted the deals created in the period from a WhatsApp click, grouped by the deal's own attribution, so form leads came with 0 deals and some groups came with deals and no leads (those groups are gone). A Web Forms click referred by the organization's own site groups asdirect|direct|, andmatch_score_avgleaves out Web Forms submissions, which carry no score.x-mb-bulkgives the bulk limit asmax_items;maxItemsstill comes and is deprecated.- AI credits: the AI that an organization runs charges its AI credits everywhere. Re-indexing the knowledge of an agent after
ai.agents.update,ai.agents.update_liveorai.agents.create_with_keycharges the caller's credits; without them, the entry keeps the error code (ai_credits_exhausted,ai_personal_limitorpayment_required) and the agent keeps what was already indexed.social_brand_voice.profile.updatecan returnai_summary_statusno_credits(a save from the app whose person had no AI credits left: the summary was not rewritten), with the reason in the newai_summary_credits_code(one of those three codes). The AI blocks of a report instance carryai_error_codewhen their AI did not run for lack of AI credits.profile.documents.*,social_brand_voice.documents.*and thesocial_brand_voice.document.processedevent can carry those three codes inerror_messageorembedding_error(read but not indexed: status ready with embedding_status error). The scheduled runs of report deliveries do not write AI blocks: the PDF they send is built from the template, so the AI text never reached it (ai_modeis kept for later). Every model answer is charged by its real tokens (thinking as output, what the model read with its web tools as input, the model that answered), also an unusable one; a model that fails is not charged. The organization's automatic AI checks its credits first: without them, an AI position of the CRM hands the lead to its escalation person (crm.ai_team.positions.assignand assigning an AI position as owner withcrm.deals.updateorcrm.prospects.updatereturn the owner after that first turn) and a lead scored on arrival enters unscored, marked for the daily refresh (crm.leads.ingest). A completed Series post can come without copy, with the reason in the newcopies_error(ai_credits_exhausted,ai_personal_limit,payment_requiredorgeneration_failed). - Rank tracking keeps every position with its own engine, country and device:
seo_rankings.projects.listandseo_rankings.projects.getaddmeasured_pos_keys,combo_summaries(one per combination measured today that already has measurements, each with its ownprevious_summary) andretired_combos, andseo_rankings.projects.createandseo_rankings.projects.updatereturn the project with them;previous_summaryis always the check before of the same combination ascheck_summary, or null, and summaries addlast_checked_at.seo_rankings.keywords.listandseo_rankings.keywords.getmark each latest position withmeasured: what the project no longer measures is cleared, and a leftover may come withmeasured: false(the cleanup removes it): skip it (its history stays inseo_rankings.history.grid).seo_rankings.projects.updatethat removes a country or a device clears its latest positions and returnspositions_clearedandretired_pos_keys, and itsdry_runsays which combinations it would stop measuring and how many positions it would clear (running it needs noconfirm_token).seo_rankings.keywords.bulk.set_engines, andseo_rankings.keywords.addwhen it reactivates a keyword withengine_keys, clear the latest position of the countries a keyword leaves (the dry run ofseo_rankings.keywords.bulk.set_enginescounts them inpositions_cleared).seo_rankings.keywords.opportunitiesrejects aposition_keythe project does not measure (400rank_position_key_not_measured, withdetails.measured_pos_keys) and counts only the keywords measured there.seo_rankings.keywords.importrejects a device the project does not measure (400rank_import_device_not_in_project). Each row ofseo_rankings.cross_account.getnames its combination and addscombos, andavg_top10_pctuses each project's main combination. In demo organizationsseo_rankings.checks.triggerandseo_rankings.volume.fetchare 403demo_read_only, also on their dry run, andseo_rankings.keywords.addandseo_rankings.keywords.importnever fetch search volume. Webhooks: the seo_rankings.check.completed event addsprevious_summaryandcombo_summaries, the seo_rankings.project.updated event addsretired_pos_keysandpositions_cleared, and the summaries of the events addlast_checked_at. - The Social Inbox and
Idempotency-Key(2026-10-17): the Social Inbox eventitem.escalatedadds the reasonai_no_answer(in a private message, the AI came back empty twice, also on its retry, and the item goes to a person instead of staying unanswered), and its description says the AI Community Manager did not answer. A write whose response could not be stored (too large, or the save failed, also a response that cannot be written as text) answers a repeat with 409idempotency_response_unavailableinstead of running it again. - Routines for every Account (2026-10-18):
ai.work.routines.createandai.work.routines.updatetakescope.mode: all_accounts(withoutorg_ids; only with a template whoseall_accountsis true inai.work.routines.templates, which adds that field): the workspace and every Account of it the owner reaches with the template's modules, resolved again at each run, where the AI works only in the Accounts with something to report. A routine of every Account comes back withscope.modeall_accounts, emptyorg_idsandnames, andscope.total(how many Accounts it covered the last time); its preview has noitems. New 400 codes:ai_work_scope_all_accounts_templateandai_work_scope_no_accounts;ai_work_routine_trigger_accountsnow also coversall_accounts, andorg_idswithall_accountsis 400ai_work_scope_invalid.ai_work_template_unknownaddsdetails.allowed(the template keys that exist), and the preview of a routine with a template in this organization or in chosen Accounts may warn that there is nothing to review there. - LinkedIn documents and carousels (2026-10-20):
social_plannerposts takeformat: document(LinkedIn page and profile only: one PDF, PowerPoint or Word file of the media library, up to 100 MB and 300 pages) andlinkedin_settings.document_title(up to 100 characters;nullremoves it);linkedin_profilenow takescarouselanddocumenttoo. On LinkedIn acarouselnow goes out as a swipeable document that MB Suite builds from its 2 to 20 images, with a title (a feed post with several images still goes out as a grid): scheduling a LinkedIn carousel with fewer than 2 images, or with no text and no title, ispost_not_readywith the new issueslinkedin_carousel_too_few_imagesandlinkedin_document_title_missing, and a document post addslinkedin_document_invalid,linkedin_document_needs_format,linkedin_document_too_large,linkedin_document_too_many_pagesandlinkedin_document_encrypted. A post'smaster_mediaand a publish job'scontent_snapshotcan carrytype: document(ormedia_type: document) withpage_countanddocument_flags, and the snapshot of a LinkedIn document or carousel job,document_title.media_library.items.*,media_library.uploads.create(purpose: document_thumbnail) and themedia_library.item.*events addtype: document,page_countanddocument_flags; a document whose name lacks the extension of its type gets it. The sync of published posts no longer rewrites theformatof a post created in MB Suite, and posts brought from LinkedIn come asfeedordocument. Through an API key or the MCP, scheduling or publishing on LinkedIn answers 403platform_terms_restricted(its terms do not allow automated publishing); drafts work. - API & MCP per workspace (2026-10-20): an owner or admin of the workspace turns the API and the MCP on in Settings → API & MCP, and they apply to all its Accounts; they are included in active paid subscriptions, not in the free trial. A call to an organization whose workspace has not turned them on, or turned them off, is 403
platform_not_enabled; one where the subscription that applies is on its free trial or there is none is 403platform_requires_paid_plan, withdetails.plan(trialorno_plan).platform_disablednow only means that MB Suite has not opened them for the organization or the person. Turning them off deletes nothing: API keys, connections and webhooks work again when they are turned back on, and meanwhile no webhook events are generated.organizations.modules.listgivesblocked_reasonown_switchfor API & MCP andorganizations.modules.toggle_freeanswers it with 409module_has_own_switch: it has its own switch. - Email sending hold (2026-10-20): MB Suite pauses an organization's email sending when a campaign send or a flow has a hard bounce rate over 5% (with at least 50 sent and 10 hard bounces), or when MB Suite decides it. While it is paused,
email_marketing.campaigns.send_now(and its dry run),email_marketing.flows.activateandemail_marketing.templates.send_testare 409email_sending_paused(details.kindbounce_rateormanual,details.held_at); a scheduled campaign does not go out and goes back to draft withschedule_missed.codeemail_sending_paused; active flows send nothing; and the campaigns that were going out are cancelled withsend_held(held_at,kind,sent,total). Campaign stats addhard_bounced;email_marketing.usage.getaddssending_paused(paused,kind,since); and the dry runs ofemail_marketing.flows.enrollments.enroll,email_marketing.flows.enrollments.enroll_audienceandemail_marketing.flows.audiences.linksay so and countsending_paused. - AI tiers and extra credits (2026-10-20): credit packs are retired; an organization adds a monthly AI tier (plus, pro or max) and prepaid extra credits, used once the month's credits run out, up to a monthly cap set by the owner (both are bought and configured only in the app).
organizations.ai_usage.getaddsbalance.base_plan_credits,balance.tierandbalance.extra_credits(null whenbalance.paid_byisworkspace: they belong to whoever pays);balance.plan_credits_includedis the plan plus the tier;balance.total_remainingadds the extra credits usable now;balance.pack_credits_remainingis deprecated and carries those usable extra credits.ai_credits_exhaustedaddsdetails.detail:extras_limit(the owner's monthly cap for extra credits was reached) orfrozen(the extra credits are frozen). - Platforms with their own terms (2026-10-20): the terms of Google Ads, Google Business Profile, LinkedIn, TikTok and YouTube limit what can be done with their data and their APIs outside MB Suite's screens, and the API, the MCP and webhooks follow them (the permissions guide lists what is available for each one). A call they do not allow is 403
platform_terms_restricted, withdetails.platform,details.networkanddetails.access(none, orown_key: only an organization API key, through the REST API), and the MCP does not offer those operations. Where a response mixes platforms, their records are left out (a deal or prospect that came in through LinkedIn Lead Gen or TikTok, a person or company created or completed from them, a linked account, a connection, an Inbox item from TikTok or a LinkedIn comment) or come without their fields (the campaign names of a CRM record's attribution, the answers of a Google Ads lead form, a media plan'stotal_spentandspent_by_currency). Webhooks do not send the events that carry their data (a lead from their forms, a change in their campaigns, an alert on their metrics, a delivery whose PDFs map their accounts, the media plan cost sync) and send the rest without their fields; an event type already subscribed stays in the subscription.social_inbox.crm.create_prospectis 409 for a LinkedIn comment or mention (also in the app). New fields:origin_channelsin CRM people and companies,source_channelandorigin_channelsin the results ofcrm.search, andplatformsindeliveries.received.listand in the delivery events.