Menu

API reference · Branding

Portal domains

branding · portal_domains · 3 operations

POST/v1/branding/portal-domains

Add a client portal address

branding.portal_domains.add

WriteIdempotentSince 2026-11-01

Registers an address for the organization's client portal: a full hostname, either <label>.mb-suite.com (its MB Suite subdomain: the label follows the same rules as branding.subdomain.set) or its own domain (portal.youragency.com, never mb-suite.com itself nor a hosting provider's domain). Validates that no other organization nor this organization's team access uses it, registers it with the hosting provider and saves it enabled; a custom domain starts unverified (verification_record may come back; its CNAME must point to cname.vercel-dns.com; then branding.portal_domains.verify). One subdomain and one custom domain per portal. A different MB Suite subdomain replaces the current one in this same call: the new one is registered and saved first, then the old one is released (previous_host; previous_released_from_hosting false when the hosting provider did not release it — it no longer opens the portal), so the portal is never left without an address. A second custom domain is 409 portal_domain_already_set (remove the current one first: it has its own DNS and verification). The same address again changes nothing. Fires branding.domain.added (and branding.domain.removed for a replaced subdomain). Owners and admins with edit access to Branding and to the Client Portal.

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

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

Parameters

domainstringbodyrequired

The full hostname: portal.youragency.com (its own domain) or clients.mb-suite.com (an MB Suite subdomain).

Response

domainobject
verification_recordobject | null
changedboolean
previous_hoststring
previous_released_from_hostingboolean

Errors

Example

curl -X POST "https://api.mb-suite.com/v1/branding/portal-domains" \
  -H "Authorization: Bearer $MB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "domain": "DOMAIN",
  "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/branding/portal-domains/verify

Verify the client portal's custom domain

branding.portal_domains.verify

WriteIdempotentSince 2026-11-01

Asks the hosting provider whether the client portal's custom domain is ready (ownership verified and the CNAME configured). When it is, the address is marked verified and starts serving the portal (fires branding.domain.verified, once); otherwise returns verified false with configured, the verification_record still to publish (if any) and message. Not found when the portal has no custom domain (subdomains need no verification). Owners and admins with edit access to Branding and to the Client Portal.

Scope
branding:write
Permission
Edit in the module · Only owner, admin
MCP tool
branding_portal_domains_verifyOn the full surface; on the compact one, mb_execute_operation with id: "branding.portal_domains.verify".
Events it can emit
branding.domain.verified

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

Parameters

No parameters.

Response

domainobject
verifiedboolean
configuredboolean
verification_recordobject | null
messagestring | null

Errors

Example

curl -X POST "https://api.mb-suite.com/v1/branding/portal-domains/verify" \
  -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. In the practice organization this operation is not simulated (it reaches another platform): it answers 409 sandbox_external_unavailable.

DELETE/v1/branding/portal-domains/{domain}

Remove a client portal address

branding.portal_domains.remove

IrreversibleSince 2026-11-01

Removes one of the client portal's addresses (domain is the full hostname, exactly as branding.domains.get lists it): it stops opening the portal, it is released from the hosting provider (released_from_hosting false if another organization also has it or the provider failed: the organization is cleaned anyway) and cleared from the portal settings. An address that is not one of this organization's portal addresses is not found (nothing is ever released on someone else's behalf). The domain's DNS records are not touched. There is no trash: to undo, add it again. Outside the app it needs a dry run and its confirm_token. Fires branding.domain.removed. Owners and admins with edit access to Branding and to the Client Portal.

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
branding:write and “Allow deletions” (branding:delete in OAuth)
Permission
Edit in the module · Only owner, admin
MCP tool
branding_portal_domains_removeOn the full surface; on the compact one, mb_execute_operation with id: "branding.portal_domains.remove".
Events it can emit
branding.domain.removed

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

Parameters

domainstringpathrequired

The full hostname: portal.youragency.com (its own domain) or clients.mb-suite.com (an MB Suite subdomain).

Response

removedtrue
domainobject
released_from_hostingboolean

Errors

Example

curl -X DELETE "https://api.mb-suite.com/v1/branding/portal-domains/{domain}" \
  -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.