Menu

API reference · Client Portal

Invitations

client_portal · invitations · 5 operations

GET/v1/client-portal/invitations

List the portal invitations

client_portal.invitations.list

ReadIdempotentSince 2026-11-01

Lists the invitations to this workspace's client portal, newest first, paginated by cursor (limit up to 200). status: pending (default: sent and still valid for its 30 days), accepted (the client registered: accepted_by_uid is their client id), cancelled, expired (pending past its 30 days; client_portal.invitations.resend revives it) or all. With pending or expired a page can hold fewer than limit items: keep paging while has_more. Each invitation: email, display_name, the accounts and sections the client will get, status, who invited and when, expires_at. It never returns the registration link. Only owners and admins.

Scope
client_portal:read
Permission
View the module · Only owner, admin
MCP tool
client_portal_invitations_listOn the full surface; on the compact one, mb_execute_operation with id: "client_portal.invitations.list".

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

Parameters

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.

statusenumqueryoptional

pending (default: sent and still valid), accepted (the client registered), cancelled, expired (pending past its 30 days) or all.

Values: pending, accepted, cancelled, expired, all · Default: "pending"

Response

dataarray<object>
has_moreboolean
next_cursorstring

Errors

Example

curl "https://api.mb-suite.com/v1/client-portal/invitations" \
  -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/client-portal/invitations" \
  -H "Authorization: Bearer $MB_TEST_KEY"
GET/v1/client-portal/invitations/{invitation_id}

Get a portal invitation

client_portal.invitations.get

ReadIdempotentSince 2026-11-01

Returns one portal invitation by id: email, display_name, the accounts and sections the client gets on registering, status (pending, accepted, cancelled or expired, computed from expires_at), who invited and when, accepted_at and accepted_by_uid (the new client's id) once accepted. Not found (portal_invitation_not_found) if it is not an invitation of this workspace. It never returns the registration link. Only owners and admins.

Scope
client_portal:read
Permission
View the module · Only owner, admin
MCP tool
client_portal_invitations_getOn the full surface; on the compact one, mb_execute_operation with id: "client_portal.invitations.get".

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

Parameters

invitation_idstringpathrequired

Portal invitation id, from client_portal.invitations.list.

Response

idstring

The invitation id.

emailstring

Who was invited.

display_namestring | null

Their name, if given.

assigned_child_org_idsarray<string>

The Accounts they will see.

enabled_modulesobject
statusenum

pending, accepted, cancelled or expired (a pending one past its 30 days).

Values: pending, accepted, cancelled, expired

invited_bystring

The user id of who invited them.

invited_by_namestring

Their name.

created_atnumber

When it was created (epoch ms).

expires_atnumber

When it expires (epoch ms): 30 days after it was sent or resent.

accepted_atnumber | null

When it was accepted (epoch ms).

accepted_by_uidstring | null

The user id that accepted it.

cancelled_atnumber | null

When it was cancelled (epoch ms); null for an invitation cancelled before the date was recorded.

Errors

Example

curl "https://api.mb-suite.com/v1/client-portal/invitations/{invitation_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 "https://api.mb-suite.com/v1/client-portal/invitations/{invitation_id}" \
  -H "Authorization: Bearer $MB_TEST_KEY"
POST/v1/client-portal/invitations

Invite a client to the portal (sends an email)

client_portal.invitations.create

WriteSince 2026-11-01

Invites a person outside the agency to this workspace's client portal and SENDS them an email through Amazon SES with a link to create their account (valid 30 days). They will see the assigned_child_org_ids (accounts of this workspace, at least one; an id from another organization fails with portal_account_invalid) and the sections from module_preset (complete, reports_only or default; default when omitted) adjusted by enabled_modules. The email must have a valid format and cannot be on a platform domain (portal_email_invalid). Fails with portal_not_configured (409) while the portal has no subdomain (client_portal.settings.get shows it) and with portal_invitation_exists (409) when the email already has a pending invitation (resend or cancel that one). Returns the invitation and email_sent: when false the invitation exists but the email did not go out (retry with client_portal.invitations.resend). Not idempotent: every successful call sends an email. Outside the app it runs as a dry run first (it checks the email, the accounts, that the portal is set up and that there is no pending invitation, and says who gets the email) and needs the confirm_token. Fires client_portal.client.invited; client_portal.client.registered fires when the person creates their account. Only owners and admins.

Instructions for agents

Tell the person the invitation email went to the client (or, if email_sent is false, that it was created but the email failed and can be resent) and that it expires in 30 days. Never ask for or share the registration link: the client uses the one in the email.

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
client_portal:write
Permission
Edit in the module · Only owner, admin
MCP tool
client_portal_invitations_createOn the full surface; on the compact one, mb_execute_operation with id: "client_portal.invitations.create".

Declared cost: up to 508 reads and 6 writes per call (they count against the daily quota). Touches an external platform (ses): it counts against the external operations quota.

Parameters

emailstringbodyrequired

The client's email: the invitation is sent there and only an account with this email can accept it. Platform domains (mb-suite.com, mediabros.com…) are not allowed.

assigned_child_org_idsarray<string>bodyrequired

Accounts (client organizations of this workspace) the client sees in the portal. At least one; replaces the whole list.

display_namestringbodyoptional

Optional name for the client; when empty, the email is used until they register.

module_presetenumbodyoptional

Starting point for the client's sections: complete (all 14), reports_only (monitors, dashboards and reports), default (what a new client gets in the app: everything except social_insights, social_competitors, seo_rankings and seo_site_auditor).

Values: complete, reports_only, default

enabled_modulesobjectbodyoptional

Portal sections to turn on (true) or off (false) for this client, applied on top of module_preset (or of the current setting when editing). Keys: monitors, dashboards, reports, paid_insights, paid_media, social_insights, social_media, social_competitors, seo, seo_rankings, seo_site_auditor, ai_chat, apps_ads_visualizer, apps_utm_builder. Overview and Profile are always visible.

Response

invitation_idstring
invitationobject
email_sentboolean

Errors

Example

curl -X POST "https://api.mb-suite.com/v1/client-portal/invitations" \
  -H "Authorization: Bearer $MB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "ana@example.com",
  "assigned_child_org_ids": [
    "ASSIGNED_CHILD_ORG_ID"
  ],
  "dry_run": true
}'

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. In the practice organization this operation is not simulated (it reaches another platform): it answers 409 sandbox_external_unavailable.

POST/v1/client-portal/invitations/{invitation_id}/resend

Resend a portal invitation email

client_portal.invitations.resend

WriteSince 2026-11-01

Renews a pending or expired invitation for another 30 days and SENDS its email again through Amazon SES, with the portal's current address. An accepted or cancelled invitation cannot be resent (portal_invitation_not_pending, 409); an expired one whose email already has a newer pending invitation fails with portal_invitation_exists. If the email cannot be sent the invitation stays renewed and the call fails with the email provider's error (details.platform ses): 503 external_unavailable or 429 external_rate_limited (retry later: it renews and sends again), 409 external_rejected when the provider refuses the address, or 409 external_outcome_unknown when it did not answer and the email may have gone out (check before resending). Not idempotent: every successful call sends an email. Only owners and admins.

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
client_portal:write
Permission
Edit in the module · Only owner, admin
MCP tool
client_portal_invitations_resendOn the full surface; on the compact one, mb_execute_operation with id: "client_portal.invitations.resend".

Declared cost: up to 7 reads and 1 writes per call (they count against the daily quota). Touches an external platform (ses): it counts against the external operations quota.

Parameters

invitation_idstringpathrequired

Portal invitation id, from client_portal.invitations.list.

Response

invitationobject
email_senttrue

Errors

Example

curl -X POST "https://api.mb-suite.com/v1/client-portal/invitations/{invitation_id}/resend" \
  -H "Authorization: Bearer $MB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "dry_run": true
}'

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. In the practice organization this operation is not simulated (it reaches another platform): it answers 409 sandbox_external_unavailable.

POST/v1/client-portal/invitations/{invitation_id}/cancel

Cancel a pending portal invitation

client_portal.invitations.cancel

WriteIdempotentSince 2026-11-01

Cancels a pending (or expired) invitation: its registration link stops working at once. It sends nothing. Idempotent: on a cancelled invitation nothing changes (changed=false). An accepted invitation cannot be cancelled (portal_invitation_not_pending, 409): the person is already a client; deactivate them with client_portal.clients.deactivate. To invite the same email again after cancelling, use client_portal.invitations.create. Only owners and admins.

Scope
client_portal:write
Permission
Edit in the module · Only owner, admin
MCP tool
client_portal_invitations_cancelOn the full surface; on the compact one, mb_execute_operation with id: "client_portal.invitations.cancel".

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

Parameters

invitation_idstringpathrequired

Portal invitation id, from client_portal.invitations.list.

Response

invitationobject
changedboolean

Errors

Example

curl -X POST "https://api.mb-suite.com/v1/client-portal/invitations/{invitation_id}/cancel" \
  -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/client-portal/invitations/{invitation_id}/cancel" \
  -H "Authorization: Bearer $MB_TEST_KEY"