Topolo Docs Topolo Platform
Open workspace

Create a Socialize brand workspace

Create an Auth-owned workspace and its Socialize profile, then reconcile both sides before retrying an uncertain result.

Outcome

Create an Auth-owned workspace and its Socialize profile, then reconcile both sides before retrying an uncertain result.

Action: app_topolo_socialize.brands.create.

Before you start

  1. Verify the original principal and intended organization. Use supported workspace discovery to check the actual caller’s creation eligibility for Socialize; Auth makes the final runtime decision. Organization ownership or an app permission alone does not prove creation is allowed.
  2. Published permission is app_topolo_socialize.workspace:write. Review the requested name, optional description/default choice and both Auth/local-profile effects; validate and plan the actual request before confirming.
  3. The route requires authenticated original user id/email, organization and authorization context. Do not forge X-Auth headers or assume an API-key-only principal supplies every field this route needs.

Discover the creation boundary

  • Use supported workspaces.list for Socialize to inspect current workspaces and caller creation policy before a mutation; retain the before-list to reconcile uncertainty.
  • This is a new workspace, so no new id may be guessed as a resource binding. Follow the actual creation plan’s context; after success, use data.id and supported discovery to resolve the new workspace.

Request

POST /api/brands
FieldRequiredMeaning
nameYes1–100 characters before source-route trimming. Auth owns the resulting workspace name and applies its own policy.
descriptionNoUp to500characters, stored only in Socialize.
isDefaultNoExplicit requested default selection forwarded to Auth. Omit to defer to Auth policy; verify actual outcome.

Do not add appId, organizationId, workspaceId, creator or idempotency fields to this action input. Current schema rejects undeclared fields.

Effects

  • Delegates canonical workspace creation to Auth with resolved Socialize app id, original organization, trimmed name and isDefault only when supplied. Description stays Socialize-owned; it is not sent as Auth workspace identity.
  • After Auth success, synchronizes the local brand mirror and optionally updates its description. Auth creation, mirror synchronization and local description update are not shown as one transaction. A later502/500 or interrupted response can leave a canonical workspace and partial local state.
  • The returned memberCount is hardcoded0 and logoUrl empty on this path, not an authoritative query of grants or existing memberships. Auth owns the name, slug, owner and actual default status; these are not included in this response.
  • When an Idempotency-Key HTTP header is already supplied by a supported transport, this handler forwards it to Auth. The action input schema has no idempotencyKey field; do not invent a CLI/MCP option or assume automatic replay protection. Existing-workspace reconciliation remains mandatory after uncertainty.

Interpret the response

HTTP201 returns {data:{...}}. data.id is the new canonical workspace id, not a local brand alias. The response contains local description/logo/memberCount, organizationId and timestamps; it omits workspace name, slug, owner and default flag. Auth numeric createdAt values are normalized to ISO time by this route; strings are preserved. Placeholder timestamps below illustrate shape, not live execution.

Worked examples

All examples are source-derived, synthetic and unrun. They do not authorize creating a real workspace.

Create a reviewed editorial workspace

Source-derived synthetic and unrun. Assumes Auth creation policy allows the original caller’s reviewed request and returns the illustrated workspace identity. No real workspace was created.

{
  "name": "Example editorial",
  "description": "Example editorial workspace",
  "isDefault": false
}

Illustrative HTTP201 body:

{
  "data": {
    "id": "ws_socialize_example",
    "description": "Example editorial workspace",
    "logoUrl": "",
    "memberCount": 0,
    "organizationId": "org_example",
    "createdAt": "2026-10-21T00:00:00.000Z",
    "updatedAt": "2026-10-21T00:00:01.000Z"
  }
}

Verify data.id in Auth-owned workspace discovery, then its Socialize profile. Verify actual default status separately; it is not returned here.

Create with no optional profile fields

Source-derived synthetic and unrun. isDefault is omitted rather than fabricated; default selection remains Auth policy.

{
  "name": "Example team"
}

Illustrative HTTP201 body:

{
  "data": {
    "id": "ws_socialize_other_example",
    "description": "",
    "logoUrl": "",
    "memberCount": 0,
    "organizationId": "org_example",
    "createdAt": "2026-10-21T01:00:00.000Z",
    "updatedAt": "2026-10-21T01:00:01.000Z"
  }
}

Read the actual created workspace and default state; the empty local description/logo and zero reported memberCount do not establish an empty or deletable Auth workspace.

Refusals and recovery

StatusConditionNext step
400invalid_jsonCorrect malformed JSON before a newly reviewed call; do not assume the earlier uncertain request had no effect.
400validation_errorInspect flattened route validation issues for name/description/isDefault. Name is length checked before trimming and Auth applies its own validation; do not rely on whitespace-only names.
400organization_requiredUse the original authorized organizational context, without inventing organizationId input or changing the shared default.
401unauthorizedThe required authorization context is absent. Authenticate through the supported flow and reverify the actual principal.
502workspace_creation_failedAuth success lacked an expected returned workspace id. Reconcile existing workspaces before any repeat; do not assume creation was rolled back.
500failed_to_create_brandPreserve request evidence and discover Auth/local state. This can follow Auth creation or local writes; do not replay blindly.

Auth non-success responses are forwarded with their actual status/payload before local mirror creation. Do not replace them with invented common409/403 carrier examples or infer Auth’s effect state from an HTTP code alone. ApplicationError branches retain their problem-detail form; generic exceptions use the source-specific failed_to_create_brand response. Outer gateway/authentication refusals can differ.

No transactional rollback is guaranteed across Auth workspace creation and local profile synchronization. Preserve before-state and discover the exact created id after uncertainty before a separately authorized repair. The published compensating action points to workspaces.delete, whose app path asks Auth to archive only after local emptiness checks. Its current policy, default-workspace restriction, actual transport and user approval must be qualified separately; do not automatically delete/archive or invent a rollback for a partially created/default workspace.

Verify the result

  • Retain data.id, then verify that exact canonical workspace through supported workspace discovery in the original organization, including actual name/default status. A successful app response alone is not a complete Auth policy proof.
  • Use brands.get for that workspace’s local profile and compare its organization and intended description. brands.list is cached and can reconcile memberships; do not rely on a stale list alone or invoke a tight polling loop.
  • After an uncertain result, discover the original intended workspace before another create. Reconcile Auth identity and local profile separately; a valid name is not a unique id or a safe deduplication key by itself.

Change log

2026-10-21: Added source-qualified creation guidance, canonical Auth/local-profile separation, policy/default boundaries, two synthetic unrun worked examples and partial-write reconciliation. Reviewed source f8e30bad6947f868302f24e9cb31b6a2bdd1fbf6; current declaration marker bc22ce7a2ceaa4396388794c4d42895c777bed76. No deployed serving-source association, business execution or provider/test result is claimed.