Topolo Docs Topolo Platform
Open workspace

Set the Campaigns notification recipient — Campaigns

Stores one nonempty userId in the selected workspace’s app-local setting, replacing the stored recipient. It does not verify that user’s current membership, delivery eligibility or preferences and sends no notification by itself.

Set the Campaigns notification recipient

Stores one nonempty userId in the selected workspace’s app-local setting, replacing the stored recipient. It does not verify that user’s current membership, delivery eligibility or preferences and sends no notification by itself.

Outcome and boundaries

Stores one nonempty userId in the selected workspace’s app-local setting, replacing the stored recipient. It does not verify that user’s current membership, delivery eligibility or preferences and sends no notification by itself.

Before you start

  • Confirm the intended environment and current credential organization using whoami; discover the exact application/action before any call.
  • Required application permission: app_topolo_campaigns.workspace:write. Catalog discoverability is not permission to execute.
  • Discover an authorized canonical workspace and bind resourceType workspace/resourceId separately from action input.
  • All worked cases in this guide are hypothetical source-reviewed illustrations; no business action, live fixture, customer data or provider request was executed.
  • Canonical workspace minimum access is admin in addition to the application permission. After grant verification, the first request may create an app-local identity/recipient mirror even before the later app-permission check; this is not campaign-domain completion.

Discover the intended identifiers

  • Discover the canonical workspace and qualify the intended recipient through the legitimate user/membership owner. The action itself supplies no membership-discovery operation.

Action: app_topolo_campaigns.workspaces.notification_recipient.update · PUT /api/workspaces/{workspaceId}/notification-recipient.

Input fields

FieldRequiredMeaning and validation
workspaceIdYesCanonical workspace id discovered under the current organization and verified selected grant. string; minLength=1
userIdYesNonempty stored user identifier, not an email address. Qualify membership and delivery policy separately; the handler does not do so. string; minLength=1

Safe call sequence

Write the reviewed input to payload.json; fixture identifiers below are unusable examples. Validate before planning, bind the discovered resource separately, and execute only within actual authority.

topolo actions validate app_topolo_campaigns.workspaces.notification_recipient.update --data @payload.json --json
topolo actions plan app_topolo_campaigns.workspaces.notification_recipient.update --resource-type workspace --resource-id "$CAMPAIGNS_WORKSPACE_ID" --data @payload.json --json

The published action requires confirmation. Only after the exact mutation is authorized, use that same payload/context with --confirm on plan/call; no operation in this guide has been executed.

Worked cases

Every response below is synthetic and source-reviewed, not captured. HTTP status and body are explained independently; a structurally valid body alone never proves successful execution. Middleware may add a different error envelope.

Store an already-qualified recipient · HTTP 200

Input:

{
  "workspaceId": "workspace_example",
  "userId": "user_example"
}

Illustrative response:

{
  "workspaceId": "workspace_example",
  "notificationUserId": "user_example"
}

Same value again · HTTP 200

Input:

{
  "workspaceId": "workspace_example",
  "userId": "user_example"
}

Illustrative response:

{
  "workspaceId": "workspace_example",
  "notificationUserId": "user_example"
}

The value remains the same but metadata can be refreshed. This is not a delivered notification.

Whitespace recipient fails the handler · HTTP 400

Input:

{
  "workspaceId": "workspace_example",
  "userId": " "
}

Illustrative response:

{
  "error": "user_id_required"
}

Verify the outcome

  • Match returned workspaceId and notificationUserId. No separate setting-read action is qualified here; verify any later notification through Notify’s actual recipient/delivery evidence.

Refusals and recovery

  • HTTP 400 user_id_required: Correct the named input or retain the authoritative refusal in the same context.
  • HTTP 403 workspace_forbidden: The canonical workspace grant refused the selected resource. Resolve it with the access owner, not a guessed workspace.
  • HTTP 404 workspace_not_found: Correct the named input or retain the authoritative refusal in the same context.
  • HTTP 403 forbidden: Raw handler permission refusal. SDKs can normalize it to permission_denied. Keep the same intended resource; do not widen access.

Preserve the previously approved user id from an authoritative owner record before changing it. A reviewed update may restore that known value; the action has no clear/null input or delivery rollback.

Source and catalog limits

Published member-recipient wording is not a membership check in the reviewed route/store. No success or fixture proves current recipient eligibility.

Exact schemas and provenance

Input schema:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "workspaceId": {
      "type": "string",
      "minLength": 1
    },
    "userId": {
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "workspaceId",
    "userId"
  ],
  "additionalProperties": false
}

Output schema:

{
  "type": "object",
  "title": "Update notification recipient response",
  "description": "Operation result returned by workspaces.notification_recipient.update.",
  "properties": {
    "success": {
      "type": "boolean"
    },
    "id": {
      "type": "string"
    },
    "data": {
      "anyOf": [
        {
          "type": "object",
          "title": "workspace record",
          "properties": {
            "id": {
              "type": "string",
              "description": "Stable identifier when the workspace exposes one."
            }
          },
          "additionalProperties": true
        },
        {
          "type": "object",
          "additionalProperties": true
        }
      ]
    },
    "result": {
      "type": "object",
      "additionalProperties": true
    },
    "message": {
      "type": "string"
    }
  },
  "additionalProperties": true,
  "x-topolo-contract-source": "derived-action-metadata",
  "x-topolo-contract-precision": "structural"
}

Reviewed immutable source: TopoloCampaigns@cacbb8b12b4e19a662cf82d03a927aef3c3a35e8, apps/api/src/campaigns-store.ts. Fresh production catalog was read on 2026-10-20. Its publication metadata is not proof that this source is loaded. Output examples are not widened or rewritten to force schema success; the accompanying validation record classifies exact success, refusal, no-body and structural-schema limits.

Local input rejection example

This deliberately invalid input belongs to a pure schema check; it is never a planned or executed request. The closed action input schema must reject the extra field. It has no HTTP status or server response.

{
  "workspaceId": "workspace_example",
  "userId": "user_example",
  "__unsupported_field": true
}

The hidden companion labels this as ILLUSTRATIVE_LOCAL_SCHEMA_CHECK; its validation representation is not an action output.

Published output validation limits

Current published output qualification: the output schema accepts an empty object, a partial success marker, a partial data object and a refusal body. It therefore establishes only broad structure. Require the documented HTTP/domain result and source-shaped fields; missing fields or a schema-valid error are not success.

These observations come from pure checks of the exact published schema; they are not server responses or production captures.