Menu

Referência da API · Media Planner

Planos

media_planner · plans · 7 operações

GET/v1/media-planner/plans

List media plans

media_planner.plans.list

LeituraIdempotenteDesde 2026-11-01

Lists the organization's media plans, newest first (by start date), paginated by cursor (limit up to 200). Each plan has its window (start_date/end_date in ms and start_day/end_day as YYYY-MM-DD), currency, mode (campaigns, platforms or account), status (draft, active, archived), planned budget (total_budget in the plan's currency, or null when its rows mix currencies, and budget_by_currency, the real total by currency) and, once synced, the spend (total_spent, with the same rule, and spent_by_currency); amounts are rounded to 2 decimals. Filters: status, mode, and from/to (YYYY-MM-DD) for plans whose window overlaps that range. The mode and from filters fill the page (plans are read until limit plans match, up to 600 per call; a rare filter can bring a shorter page with has_more: follow next_cursor). It does not include the rows: use media_planner.plans.get or media_planner.campaigns.list. Requires view access to the Media Planner. 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).

Escopo
media_planner:read
Permissão
Ver o módulo
Tool do MCP
media_planner_plans_listNa superfície completa; na compacta, mb_execute_operation com id: "media_planner.plans.list".

Custo declarado: até 601 leituras e 0 escritas por chamada (contam na cota diária).

Parâmetros

limitintegerqueryopcional

How many items this page brings at most (see the maximum and the default in the schema).

Padrão: 50

cursorstringqueryopcional

The next_cursor of the previous page, exactly as it came (only for the same list and filters); without it, the first page.

statusenumqueryopcional

Only plans in this status (default: all).

Valores: draft, active, archived

modeenumqueryopcional

Only plans of this granularity (campaigns, platforms or account).

Valores: campaigns, platforms, account

fromstringqueryopcional

Only plans whose window ends on or after this day.

tostringqueryopcional

Only plans whose window starts on or before this day.

Resposta

dataarray<object>
has_moreboolean
next_cursorstring

Erros

Exemplo

curl "https://api.mb-suite.com/v1/media-planner/plans" \
  -H "Authorization: Bearer $MB_API_KEY"

Testar com a sua API key de teste

Com uma API key de teste o pedido vai sempre para a sua organização de prática: dados de exemplo que você pode reiniciar.

curl "https://api.mb-suite.com/v1/media-planner/plans" \
  -H "Authorization: Bearer $MB_TEST_KEY"
GET/v1/media-planner/plans/{plan_id}

Get one media plan with its rows

media_planner.plans.get

LeituraIdempotenteDesde 2026-11-01

Returns a media plan with its rows (campaigns, platform rows or account rows, in their display order; the first campaigns_limit, 100 by default and up to 500, with campaigns_truncated when there are more: media_planner.campaigns.list pages the rest). Each row has its platform, budget and currency, own flight dates if any, status, labels, the link to a real campaign (campaigns mode) and the known spend (last_synced_cost, last_synced_at; manual_spend in the platforms and account modes). Pass include_campaigns=false for the plan alone. total_budget is in the plan's currency (null when its rows mix currencies: read budget_by_currency); created_by_name goes next to created_by. Not found (media_plan_not_found) if the id is not a plan of this organization. Requires view access to the Media Planner. 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).

Escopo
media_planner:read
Permissão
Ver o módulo
Tool do MCP
media_planner_plans_getNa superfície completa; na compacta, mb_execute_operation com id: "media_planner.plans.get".

Custo declarado: até 502 leituras e 0 escritas por chamada (contam na cota diária).

Parâmetros

plan_idstringrotaobrigatório

Media plan id (from media_planner.plans.list).

include_campaignsbooleanqueryopcional

Include the plan's rows (default true), in their display order.

Padrão: true

campaigns_limitintegerqueryopcional

How many rows come inline (default 100, up to 500); with more, campaigns_truncated is true and media_planner.campaigns.list pages the rest.

Padrão: 100

Resposta

idstring

Media plan id.

namestring

Plan name.

statusenum

draft, active or archived.

Valores: draft, active, archived

modeenum

campaigns, platforms or account: fixed for the life of the plan.

Valores: campaigns, platforms, account

start_datenumber

First day of the plan (epoch ms, 00:00 UTC). Send it back as start_day (YYYY-MM-DD).

end_datenumber

Last instant of the plan's last day (epoch ms, UTC).

currencystring

The plan's currency (ISO code).

total_budgetnumber | null

Planned budget of the plan in its currency; null when rows use another currency too (then read budget_by_currency, never add currencies).

created_atnumber

Epoch ms.

updated_atnumber

Epoch ms.

start_daystring

First day of the plan (YYYY-MM-DD): the format media_planner.plans.update takes.

end_daystring

Last day of the plan (YYYY-MM-DD, inclusive).

budget_by_currencyobject

Planned budget by currency (ISO code → amount): the plan's real total when it mixes currencies.

total_spentnumber | null

Known spend of the plan in its currency, after a cost sync; null when there is spend in another currency too (read spent_by_currency).

spent_by_currencyobject

Known spend by currency (ISO code → amount).

account_total_spendobject

Platforms and account modes: total spend of the connected ad accounts per platform (platform id → amount, in the currency of account_spend_meta).

account_spend_metaobject

Per platform: the currency of account_total_spend and how many ad accounts it adds up.

account_total_spend_synced_atnumber

When account_total_spend was last synced (epoch ms).

notesstring

Free notes of the plan.

carryover_enabledboolean

Whether the plan can receive the unspent balance of a finished plan.

carryover_platformsarray<string>

Platforms included in the carryover (absent or empty = all).

carryover_stateobject

The carryover this plan received or dismissed.

carryover_consumed_bystring | null

The plan that took this plan's unspent balance (null or absent: still available).

source_strategy_idstring

The Strategy Generator strategy the plan was created from, if any.

created_bystring

Who created the plan (uid).

created_by_namestring | null

That person's name (null when MB Suite does not know it: a former member).

campaignsarray<object>

The plan's rows in display order (with include_campaigns).

campaigns_truncatedboolean

true when the plan has more rows than campaigns_limit: read the rest with media_planner.campaigns.list.

Erros

Exemplo

curl "https://api.mb-suite.com/v1/media-planner/plans/{plan_id}" \
  -H "Authorization: Bearer $MB_API_KEY"

Testar com a sua API key de teste

Com uma API key de teste o pedido vai sempre para a sua organização de prática: dados de exemplo que você pode reiniciar.

curl "https://api.mb-suite.com/v1/media-planner/plans/{plan_id}" \
  -H "Authorization: Bearer $MB_TEST_KEY"
POST/v1/media-planner/plans

Create a media plan

media_planner.plans.create

EscritaDesde 2026-11-01

Creates a media plan: name, window (start_date and end_date as YYYY-MM-DD, inclusive), currency (ISO code) and mode, which is fixed for the life of the plan: campaigns (rows are planned campaigns, each can be linked to a real one to sync its spend), platforms (one row per ad platform; the spend is the total of the platform's connected accounts) or account (one row per currency; the spend adds up every connected account). Optional: notes, status (draft by default, or active), carryover_enabled and carryover_platforms (to receive the unspent balance of a finished plan), template_id (campaigns mode: seeds the campaigns of a template with budget 0) and campaigns (initial rows, with the rules of media_planner.campaigns.create). The plan's totals are computed from its rows. Returns the plan and its rows. Requires full access to the Media Planner. 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).

Escopo
media_planner:write
Permissão
Editar no módulo
Tool do MCP
media_planner_plans_createNa superfície completa; na compacta, mb_execute_operation com id: "media_planner.plans.create".
Eventos que pode emitir
media_planner.campaign.changed

Custo declarado: até 110 leituras e 402 escritas por chamada (contam na cota diária).

Parâmetros

namestringcorpoobrigatório

Plan name (e.g. "November 2026").

start_datestringcorpoobrigatório

First day of the plan (YYYY-MM-DD).

end_datestringcorpoobrigatório

Last day of the plan (YYYY-MM-DD, inclusive).

currencystringcorpoobrigatório

The plan's currency (ISO code, e.g. USD, ARS): the default of its rows.

modeenumcorpoopcional

Granularity, fixed for the life of the plan: campaigns (rows are planned campaigns), platforms (one row per ad platform, spend = the platform's accounts) or account (one row per currency, spend = all connected accounts).

Valores: campaigns, platforms, account · Padrão: "campaigns"

notesstringcorpoopcional

Free notes of the plan.

statusenumcorpoopcional

draft (default) or active.

Valores: draft, active · Padrão: "draft"

carryover_enabledbooleancorpoopcional

Let this plan receive the unspent balance of a finished plan (carryover).

Padrão: false

carryover_platformsarray<enum>corpoopcional

Platforms included in the carryover (empty = all).

Valores: google_ads, meta_ads, tiktok_ads, linkedin_ads, twitter_ads, other

template_idstringcorpoopcional

Campaigns mode: seed the plan with the campaigns of a template (own, inherited from the workspace or a published system template), with budget 0.

campaignsarray<object>corpoopcional

Initial rows, with the same rules as media_planner.campaigns.create.

Resposta

plan_idstring

The new plan's id.

planobject

The new plan.

campaignsarray<object>

Its rows, as created.

Erros

Exemplo

curl -X POST "https://api.mb-suite.com/v1/media-planner/plans" \
  -H "Authorization: Bearer $MB_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "name": "NAME",
  "start_date": "START_DATE",
  "end_date": "END_DATE",
  "currency": "CURRENCY"
}'

Testar com a sua API key de teste

Com uma API key de teste o pedido vai sempre para a sua organização de prática: dados de exemplo que você pode reiniciar.

curl -X POST "https://api.mb-suite.com/v1/media-planner/plans" \
  -H "Authorization: Bearer $MB_TEST_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "name": "NAME",
  "start_date": "START_DATE",
  "end_date": "END_DATE",
  "currency": "CURRENCY"
}'
PATCH/v1/media-planner/plans/{plan_id}

Update a media plan

media_planner.plans.update

EscritaIdempotenteDesde 2026-11-01

Updates the plan, with the fields to change inside updates ({ plan_id, updates: { … } }): name, notes, window (start_date/end_date, YYYY-MM-DD), currency, status (draft or active; active also reactivates an archived plan) and carryover settings (carryover_enabled, carryover_platforms; an empty list means all platforms). The mode cannot change (duplicate the plan instead), and archiving goes through media_planner.plans.archive, which also closes its campaigns. Changing the window does not move the rows' own flight dates. Unknown fields are rejected; an update that changes nothing returns changed: false. Requires full access to the Media Planner. 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).

Escopo
media_planner:write
Permissão
Editar no módulo
Tool do MCP
media_planner_plans_updateNa superfície completa; na compacta, mb_execute_operation com id: "media_planner.plans.update".

Custo declarado: até 1 leituras e 1 escritas por chamada (contam na cota diária).

Parâmetros

plan_idstringrotaobrigatório

Media plan id (from media_planner.plans.list).

updatesobjectcorpoobrigatório

The fields to change (at least one); the rest stay as they are.

Resposta

planobject

The plan as it is now.

changedboolean

false when the values sent were already the current ones: nothing was written.

Erros

Exemplo

curl -X PATCH "https://api.mb-suite.com/v1/media-planner/plans/{plan_id}" \
  -H "Authorization: Bearer $MB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "updates": {}
}'

Testar com a sua API key de teste

Com uma API key de teste o pedido vai sempre para a sua organização de prática: dados de exemplo que você pode reiniciar.

curl -X PATCH "https://api.mb-suite.com/v1/media-planner/plans/{plan_id}" \
  -H "Authorization: Bearer $MB_TEST_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "updates": {}
}'
POST/v1/media-planner/plans/{plan_id}/duplicate

Duplicate a media plan

media_planner.plans.duplicate

EscritaDesde 2026-11-01

Copies a plan with its rows into a new plan (typically next month's): optional name (default '<name> (Copy)', in the caller's language: (Copia), (Cópia)), start_date/end_date (when the window changes, every row takes the new window), status (active by default), carryover_enabled, carryover_platforms (empty = all) and notes (an empty string leaves the copy without notes); whatever is not sent comes from the original plan. Rows keep platform, budget, currency, labels and their link to real campaigns, but never the spend, the carryover (each budget goes back to its original amount), the Auto-Budget bookkeeping, the manual spend or the comments. campaign_status_mode: smart (default; completed campaigns come back active), draft (all drafts) or exact. Same mode as the original. To build next month's plan with what was agreed: exclude_campaign_ids leaves rows out of the copy, and campaign_overrides sets the budget (in the row's currency) and/or the status of a row in the copy. Every id must be a row of the original plan (400 unknown_campaign_ids with details.campaign_ids), a row can be overridden once and never when it is excluded (400 campaign_override_conflict), and leaving out every row is 400 no_campaigns_to_copy; budgets are numbers from 0 (invalid_input otherwise). The plan's totals come from the copied rows. Optional dry run: with dry_run=true nothing is written (no confirm_token needed): it runs the same checks and fails with the same errors, or returns a Preview whose counts say campaigns, excluded, budget_overrides, status_overrides and total_budget, whose items are the copied rows (up to 50) and whose warnings flag rows copied paused or cancelled and rows copied with budget 0, plus plan (name, start_day, end_day, status, mode, currency, carryover_enabled, carryover_platforms, total_budget, budget_by_currency), campaigns (per copied row: source_campaign_id, name, platform, currency, budget, original_budget, status, source_status) and excluded_campaign_ids. Removing a wrong copy later needs a key allowed to delete: check the dry run first. Reads the original plan and its rows (up to 500); writes the plan and one document per copied row. Returns the new plan. Requires full access to the Media Planner. 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).

Escopo
media_planner:write
Permissão
Editar no módulo
Tool do MCP
media_planner_plans_duplicateNa superfície completa; na compacta, mb_execute_operation com id: "media_planner.plans.duplicate".

Custo declarado: até 502 leituras e 501 escritas por chamada (contam na cota diária).

Parâmetros

plan_idstringrotaobrigatório

Media plan id (from media_planner.plans.list).

namestringcorpoopcional

Default: the original name + ' (Copy)', in the caller's language.

start_datestringcorpoopcional

The copy's first day (YYYY-MM-DD; default: the original's). When the window changes, every row takes the new window.

end_datestringcorpoopcional

The copy's last day (YYYY-MM-DD, inclusive; default: the original's).

statusenumcorpoopcional

Default active.

Valores: draft, active

campaign_status_modeenumcorpoopcional

smart (default): completed campaigns come back active, the rest keep their status; draft: all drafts; exact: same statuses.

Valores: smart, draft, exact

carryover_enabledbooleancorpoopcional

Whether the copy can receive a carryover (default: the original's).

carryover_platformsarray<enum>corpoopcional

Platforms included in the copy's carryover (empty = all). Default: the original plan's.

Valores: google_ads, meta_ads, tiktok_ads, linkedin_ads, twitter_ads, other

notesstringcorpoopcional

The copy's notes (an empty string leaves it without notes). Default: the original plan's.

exclude_campaign_idsarray<string>corpoopcional

Rows of the original plan that the copy leaves out (row ids from media_planner.campaigns.list). Each one must be a row of that plan.

campaign_overridesarray<object>corpoopcional

Per-row changes in the copy: budget and/or status of a row of the original plan, at most once per row and never for an excluded row.

Resposta

plan_idstring

The copy's id.

planobject

The copy.

campaign_countnumber

Rows copied.

Erros

Exemplo

curl -X POST "https://api.mb-suite.com/v1/media-planner/plans/{plan_id}/duplicate" \
  -H "Authorization: Bearer $MB_API_KEY"

Testar com a sua API key de teste

Com uma API key de teste o pedido vai sempre para a sua organização de prática: dados de exemplo que você pode reiniciar.

curl -X POST "https://api.mb-suite.com/v1/media-planner/plans/{plan_id}/duplicate" \
  -H "Authorization: Bearer $MB_TEST_KEY"
POST/v1/media-planner/plans/{plan_id}/archive

Archive a media plan

media_planner.plans.archive

EscritaIdempotenteDesde 2026-11-01

Archives a plan and closes its campaigns: scheduled ones become cancelled, active and paused ones become completed (drafts, completed and cancelled stay as they are); each change is kept in the campaign history and the plan.archived webhook fires. Call it with dry_run=true first to see the transitions (no confirm_token needed). Archiving is a status, not a deletion: media_planner.plans.update with status active reactivates the plan (campaign statuses do not go back). Idempotent: an archived plan with nothing to close returns changed: false. Requires full access to the Media Planner. 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).

Instruções para agentes

Tell the person how many campaigns changed status (transitions) when archiving.

Escopo
media_planner:write
Permissão
Editar no módulo
Tool do MCP
media_planner_plans_archiveNa superfície completa; na compacta, mb_execute_operation com id: "media_planner.plans.archive".

Custo declarado: até 502 leituras e 501 escritas por chamada (contam na cota diária).

Parâmetros

plan_idstringrotaobrigatório

Media plan id (from media_planner.plans.list).

Resposta

planobject

The plan as it is now.

changedboolean

false when it was already archived.

transitionsarray<object>

How many rows went from each status to another.

total_campaignsnumber

Rows of the plan.

Erros

Exemplo

curl -X POST "https://api.mb-suite.com/v1/media-planner/plans/{plan_id}/archive" \
  -H "Authorization: Bearer $MB_API_KEY"

Testar com a sua API key de teste

Com uma API key de teste o pedido vai sempre para a sua organização de prática: dados de exemplo que você pode reiniciar.

curl -X POST "https://api.mb-suite.com/v1/media-planner/plans/{plan_id}/archive" \
  -H "Authorization: Bearer $MB_TEST_KEY"
DELETE/v1/media-planner/plans/{plan_id}

Delete a media plan

media_planner.plans.delete

IrreversívelDesde 2026-11-01

Deletes a plan with its rows and its campaign change history. It goes to the 30-day trash, where an owner or admin can restore it (platform.trash.restore); the comments of each campaign and the record of sent emails are kept and come back with it. The trash keeps up to 150 records with a plan, the rows first: when the history does not fit, its oldest entries are left out (the dry run warns and the trash item says linked_truncated), and a plan whose rows alone do not fit is refused before anything is deleted with 409 media_plan_too_large_for_trash (delete some rows first with media_planner.campaigns.bulk.delete). If the plan had received another plan's balance by carryover, that balance becomes available again (restoring the plan takes it again, or answers 409 carryover_source_consumed if another plan took it meanwhile). The last sync breakdown is discarded (the next sync rebuilds it). Outside the app it needs a dry run (which counts rows and history) and a confirm_token, except a REST DELETE with a key allowed to delete. Requires full access to the Media Planner.

Com uma API key, este DELETE roda direto: o registro fica 30 dias na lixeira e a resposta traz o seu trash_item_id. Com um token OAuth, e pelo MCP, pede dry_run → confirm_token.

Escopo
media_planner:write e «Permitir exclusões» (media_planner:delete no OAuth)
Permissão
Editar no módulo
Tool do MCP
media_planner_plans_deleteNa superfície completa; na compacta, mb_execute_operation com id: "media_planner.plans.delete".

Custo declarado: até 1100 leituras e 1100 escritas por chamada (contam na cota diária).

Parâmetros

plan_idstringrotaobrigatório

Media plan id (from media_planner.plans.list).

Resposta

oktrue

Always true.

deleted_campaignsnumber

Rows deleted with the plan.

released_carryovernumber

Finished plans whose balance this plan had received: it is available to carry over again.

trash_item_idstring

The trash item this deletion left: the item_id of platform.trash.restore (POST /trash/{item_id}/restore). Missing if nothing went to the trash.

trash_item_idsarray<string>

Only when the deletion left more than one copy: all of them, the first being trash_item_id.

trash_expires_atnumber

When the copy leaves the trash for good (epoch ms): 30 days after the deletion.

Erros

Exemplo

curl -X DELETE "https://api.mb-suite.com/v1/media-planner/plans/{plan_id}" \
  -H "Authorization: Bearer $MB_API_KEY"

Testar com a sua API key de teste

Com uma API key de teste o pedido vai sempre para a sua organização de prática: dados de exemplo que você pode reiniciar.

curl -X DELETE "https://api.mb-suite.com/v1/media-planner/plans/{plan_id}" \
  -H "Authorization: Bearer $MB_TEST_KEY"