Menu

API reference · Media Planner

Comments

media_planner · comments · 6 operations

GET/v1/media-planner/plans/{plan_id}/campaigns/{campaign_id}/comments

List the comments of a campaign

media_planner.comments.list

ReadIdempotentSince 2026-11-01

Lists the internal comments of a row of a media plan (campaign, platform or account row), oldest first, paginated by cursor: content (sanitized HTML), author, mentioned member uids, and edit date. Comments from before the unified comment system carry author_id instead of created_by_id. Requires view access to the Media Planner.

Scope
media_planner:read
Permission
View the module
MCP tool
media_planner_comments_listOn the full surface; on the compact one, mb_execute_operation with id: "media_planner.comments.list".

Declared cost: up to 204 reads and 0 writes per call (they count against the daily quota).

Parameters

plan_idstringpathrequired

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

campaign_idstringpathrequired

Row id inside the plan: a campaign, a platform row or an account row (from media_planner.campaigns.list).

limitintegerqueryoptional

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

Default: 50

cursorstringqueryoptional

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

Response

dataarray<object>
has_moreboolean
next_cursorstring

Errors

Example

curl "https://api.mb-suite.com/v1/media-planner/plans/{plan_id}/campaigns/{campaign_id}/comments" \
  -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 "https://api.mb-suite.com/v1/media-planner/plans/{plan_id}/campaigns/{campaign_id}/comments" \
  -H "Authorization: Bearer $MB_TEST_KEY"
GET/v1/media-planner/plans/{plan_id}/comments

List the comments of every row of a plan

media_planner.comments.list_plan

ReadIdempotentSince 2026-11-01

Lists in one call the internal comments of every row of a media plan (campaign, platform or account rows), paginated by cursor (limit up to 200): each comment with its content (sanitized HTML), author, mentioned member uids and dates, plus campaign_id and campaign_name, the row it is on. Ordered by row and then by comment id, a stable order for paging but not a chronological one: sort by created_at if you need it. Comments of a deleted row are not listed (they come back when the row is restored from the trash, as in media_planner.comments.list); because of that, a page can bring fewer than limit while has_more is true: follow next_cursor. Use it to find a comment by id or to read a whole plan's notes instead of calling media_planner.comments.list once per row. Reads only that plan's comments (the page plus one) and the rows of the page; not found (media_plan_not_found) if the plan is not in this organization, and 400 invalid_cursor for a cursor that is not from this list. Requires view access to the Media Planner.

Scope
media_planner:read
Permission
View the module
MCP tool
media_planner_comments_list_planOn the full surface; on the compact one, mb_execute_operation with id: "media_planner.comments.list_plan".

Declared cost: up to 402 reads and 0 writes per call (they count against the daily quota).

Parameters

plan_idstringpathrequired

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

limitintegerqueryoptional

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

Default: 50

cursorstringqueryoptional

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

Response

dataarray<object>
has_moreboolean
next_cursorstring

Errors

Example

curl "https://api.mb-suite.com/v1/media-planner/plans/{plan_id}/comments" \
  -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 "https://api.mb-suite.com/v1/media-planner/plans/{plan_id}/comments" \
  -H "Authorization: Bearer $MB_TEST_KEY"
POST/v1/media-planner/plans/{plan_id}/campaigns/{campaign_id}/comments

Comment on a campaign

media_planner.comments.create

WriteSince 2026-11-01

Adds an internal comment to a row of a media plan (simple HTML or text, sanitized; up to 10,000 characters). mentions are member uids to notify (only members of this organization or of its workspace get the notice, with a link to the campaign). Returns the comment. Requires full access to the Media Planner.

Scope
media_planner:write
Permission
Edit in the module
MCP tool
media_planner_comments_createOn the full surface; on the compact one, mb_execute_operation with id: "media_planner.comments.create".

Declared cost: up to 5 reads and 2 writes per call (they count against the daily quota).

Parameters

plan_idstringpathrequired

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

campaign_idstringpathrequired

Row id inside the plan: a campaign, a platform row or an account row (from media_planner.campaigns.list).

contentstringbodyrequired

Simple HTML or text (sanitized).

mentionsarray<string>bodyoptional

Uids of members to notify (members.members.list; in an account, also the workspace's). Others are not saved: they come back in ignored_mentions.

Default: []

Response

comment_idstring

The new comment's id.

commentobject

The comment.

ignored_mentionsarray<string>

Mentioned uids that are not members of the organization or its workspace: not saved nor notified.

Errors

Example

curl -X POST "https://api.mb-suite.com/v1/media-planner/plans/{plan_id}/campaigns/{campaign_id}/comments" \
  -H "Authorization: Bearer $MB_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "content": "CONTENT"
}'

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/media-planner/plans/{plan_id}/campaigns/{campaign_id}/comments" \
  -H "Authorization: Bearer $MB_TEST_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "content": "CONTENT"
}'
PATCH/v1/media-planner/plans/{plan_id}/campaigns/{campaign_id}/comments/{comment_id}

Edit a campaign comment

media_planner.comments.update

WriteIdempotentSince 2026-11-01

Replaces the content (and the mentions) of a comment of a campaign. Only its author can edit it (403 comment_author_only); only newly added mentions are notified. Returns the updated comment. Requires full access to the Media Planner.

Scope
media_planner:write
Permission
Edit in the module
MCP tool
media_planner_comments_updateOn the full surface; on the compact one, mb_execute_operation with id: "media_planner.comments.update".

Declared cost: up to 6 reads and 1 writes per call (they count against the daily quota).

Parameters

plan_idstringpathrequired

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

campaign_idstringpathrequired

Row id inside the plan: a campaign, a platform row or an account row (from media_planner.campaigns.list).

comment_idstringpathrequired

Comment id (from media_planner.comments.list).

contentstringbodyrequired

The new text: simple HTML or text (sanitized).

mentionsarray<string>bodyoptional

The full list of mentions of the edited comment, uids of members (only new ones are notified; others come back in ignored_mentions).

Default: []

Response

commentobject

The comment as it is now.

ignored_mentionsarray<string>

Mentioned uids that are not members of the organization or its workspace: not saved nor notified.

Errors

Example

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

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 PATCH "https://api.mb-suite.com/v1/media-planner/plans/{plan_id}/campaigns/{campaign_id}/comments/{comment_id}" \
  -H "Authorization: Bearer $MB_TEST_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "content": "CONTENT"
}'
DELETE/v1/media-planner/plans/{plan_id}/campaigns/{campaign_id}/comments/{comment_id}

Delete a campaign comment

media_planner.comments.delete

IrreversibleSince 2026-11-01

Deletes a comment of a campaign, of this plan or of a previous one (the history). Its author or an owner/admin of the organization can delete it (403 comment_delete_denied otherwise). It goes to the 30-day trash, where an owner or admin can restore it (platform.trash.restore). Outside the app it needs a dry run and a confirm_token, except a REST DELETE with a key allowed to delete. Requires full access to the Media Planner.

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
media_planner:write and “Allow deletions” (media_planner:delete in OAuth)
Permission
Edit in the module
MCP tool
media_planner_comments_deleteOn the full surface; on the compact one, mb_execute_operation with id: "media_planner.comments.delete".

Declared cost: up to 3 reads and 2 writes per call (they count against the daily quota).

Parameters

plan_idstringpathrequired

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

campaign_idstringpathrequired

Row id inside the plan: a campaign, a platform row or an account row (from media_planner.campaigns.list).

comment_idstringpathrequired

Comment id (from media_planner.comments.list).

Response

oktrue

Always true.

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.

Errors

Example

curl -X DELETE "https://api.mb-suite.com/v1/media-planner/plans/{plan_id}/campaigns/{campaign_id}/comments/{comment_id}" \
  -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 DELETE "https://api.mb-suite.com/v1/media-planner/plans/{plan_id}/campaigns/{campaign_id}/comments/{comment_id}" \
  -H "Authorization: Bearer $MB_TEST_KEY"
GET/v1/media-planner/plans/{plan_id}/comments/history

Comments on the same real campaign in previous plans

media_planner.comments.history

ReadIdempotentSince 2026-11-01

Returns what was said about the same real campaign in the organization's previous plans: the comments of the rows linked to the same ad-platform campaign (campaign_id of a linked row of this plan, or mapped_campaign_id directly) in plans that started before this one, grouped by plan (most recent first), paginated by cursor (limit = plans per page, up to 20). Empty when the row is not linked. Requires view access to the Media Planner.

Scope
media_planner:read
Permission
View the module
MCP tool
media_planner_comments_historyOn the full surface; on the compact one, mb_execute_operation with id: "media_planner.comments.history".

Declared cost: up to 500 reads and 0 writes per call (they count against the daily quota).

Parameters

plan_idstringpathrequired

The current plan: the history comes from plans that started before it.

campaign_idstringqueryoptional

A linked row of the plan (its real campaign id is looked up).

mapped_campaign_idstringqueryoptional

The real campaign id on the ad platform (instead of campaign_id).

limitintegerqueryoptional

Previous plans per page.

Default: 6

cursorstringqueryoptional

next_cursor of the previous page of this same history.

Response

dataarray<object>
has_moreboolean
next_cursorstring

Errors

Example

curl "https://api.mb-suite.com/v1/media-planner/plans/{plan_id}/comments/history" \
  -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 "https://api.mb-suite.com/v1/media-planner/plans/{plan_id}/comments/history" \
  -H "Authorization: Bearer $MB_TEST_KEY"