Topolo Docs Topolo Platform
Open workspace

List saved Socialize voice presets and templates

Distinguish saved workspace voices from appended shipped templates and understand their different response projections.

Outcome

Read the authorized workspace’s saved voices together with the shipped starting templates. The combined list contains two kinds of records, with different ownership and timestamp meaning.

Action: app_topolo_socialize.brand_voice.presets.list.

GET /api/brand-voice/presets

Before you start

Verify the original credential, production environment and intended organization. Discover and bind an actually granted canonical Socialize workspace separately from action input. A preset/audit id is not a workspace id; never forge identity or switch principal after refusal.

This route resolves getBrandForVoice through resolveBrandId before the handler. Omitted workspace selection follows verified default resolution; a refused named workspace is not silently replaced. Original API-key bindings narrow grants. Workspace authorization may synchronize the local brand mirror even for declared read-only actions.

Published permission: app_topolo_socialize.posts:read. Discover current concrete resource/permission eligibility with the original credential.

Request

{}

Keep the actual workspace binding separate from these fields. Validate and plan against the current discovered contract before the read.

Effects and response semantics

The handler reads repository.getPresetsByBrand using workspace_id=?, orders stored rows by is_default DESC then name ASC, maps them, and filters out stored isBuiltin:true rows. Custom saved records appear first; five built-in templates are then appended in shipped source order. This is not a single global alphabetical order.

The published optional limit is a positive integer up to the current schema maximum, but this handler does not read or apply that query field. Do not promise that limit bounds the result or use repeated limit values as pagination. There is no offset, cursor, count or hasMore field; the current query returns all matching stored rows before built-ins are appended.

Normal output is {success:true,presets:[...]}, not items or data. With no custom rows, the reviewed source still appends all five built-in templates; an empty custom workspace is not a successful empty combined list. A future build may ship a different built-in list.

Custom records use the full stored rowToPreset mapping, including author-context fields; JSON-backed fields become objects/arrays, booleans compare stored integers to1 and timestamps remain stored values. A malformed populated JSON-backed value can fail the handler and produce its500/internal_error response; the implementation does not silently omit that record or return partial success.

Appended templates instead have brandId:system, createdBy:system, isBuiltin:true and isDefault:false. The handler creates createdAt/updatedAt strings at read time for each template. They are not persisted creation/change evidence, a hash-stable response or a selected workspace default. Author-context fields are not added by this built-in mapping.

No saved preset/default mutation, copy, post generation or provider/model call occurs in the preset-list handler; possible preceding workspace mirror synchronization remains separate. A global structural schema or generic resource $.items[].id does not supply the precise presets response projection or authorize a returned system template as a workspace.

Complete worked responses

One saved default followed by all shipped templates

Complete source-derived synthetic/unrun projection. Assumes exactly the shown non-builtin stored row in the verified fixture workspace and valid JSON-backed fields. All five template timestamps illustrate the read clock, not stored creation times; identical example times are not a guarantee of real clock equality. Fictional ids authorize no access.

Input:

{}

Response:

{
  "success": true,
  "presets": [
    {
      "id": "voice_fixture_saved",
      "brandId": "ws_fixture_brand",
      "name": "Fixture saved voice",
      "description": "A synthetic stored record for this unrun example.",
      "persona": null,
      "pointOfView": "first",
      "targetAudience": null,
      "audiencePainPoints": [],
      "audienceSophistication": "general",
      "toneFormality": 3,
      "toneBoldness": 3,
      "toneWarmth": 3,
      "toneHumor": 2,
      "sentenceStyle": null,
      "emojiUsage": "minimal",
      "punctuationStyle": null,
      "doList": [],
      "dontList": [],
      "bannedPhrases": [],
      "preferredVocabulary": [],
      "spellingLocale": "US",
      "hashtagMin": 0,
      "hashtagMax": 5,
      "hashtagThemes": [],
      "authorBackground": null,
      "authorCredentials": null,
      "authorExpertiseAreas": [],
      "authorCurrentFocus": null,
      "techStack": [],
      "industryExperience": [],
      "expertiseLevel": null,
      "writingSamples": [],
      "communicationQuirks": [],
      "topicsTheyAvoid": [],
      "strongOpinions": [],
      "contrarianTakes": [],
      "isBuiltin": false,
      "isDefault": true,
      "createdBy": "usr_fixture_author",
      "createdAt": "2026-10-01 12:00:00",
      "updatedAt": "2026-10-02 09:00:00"
    },
    {
      "id": "builtin_thought_leader",
      "name": "Thought Leader",
      "description": "Authoritative voice for sharing insights and industry expertise",
      "persona": "Industry expert sharing hard-won insights and contrarian takes",
      "pointOfView": "first",
      "targetAudience": "Professionals seeking cutting-edge insights",
      "audiencePainPoints": [
        "Information overload",
        "Generic advice",
        "Lack of actionable insights"
      ],
      "audienceSophistication": "expert",
      "toneFormality": 3,
      "toneBoldness": 4,
      "toneWarmth": 3,
      "toneHumor": 2,
      "sentenceStyle": {
        "mixLengths": true,
        "preferFragments": true
      },
      "emojiUsage": "minimal",
      "punctuationStyle": {
        "useExclamations": false,
        "preferDashes": true
      },
      "doList": [
        "Share specific data and examples",
        "Challenge conventional wisdom",
        "Use first-person experiences",
        "End with a provocative question",
        "Be direct and confident"
      ],
      "dontList": [
        "Use corporate jargon",
        "Be vague or hedge",
        "Start with \"I think\"",
        "Use passive voice",
        "Include obvious advice"
      ],
      "bannedPhrases": [
        "game-changer",
        "at the end of the day",
        "food for thought",
        "deep dive"
      ],
      "preferredVocabulary": [
        "actually",
        "here's the thing",
        "unpopular opinion"
      ],
      "spellingLocale": "US",
      "hashtagMin": 2,
      "hashtagMax": 4,
      "hashtagThemes": [
        "industry",
        "leadership"
      ],
      "brandId": "system",
      "isBuiltin": true,
      "isDefault": false,
      "createdBy": "system",
      "createdAt": "2026-10-21T00:00:00.000Z",
      "updatedAt": "2026-10-21T00:00:00.000Z"
    },
    {
      "id": "builtin_friendly_expert",
      "name": "Friendly Expert",
      "description": "Warm and approachable voice for educational content",
      "persona": "Helpful friend who happens to be an expert in your field",
      "pointOfView": "first",
      "targetAudience": "Learners and curious professionals",
      "audiencePainPoints": [
        "Intimidating jargon",
        "Condescending experts",
        "Overwhelming information"
      ],
      "audienceSophistication": "general",
      "toneFormality": 2,
      "toneBoldness": 2,
      "toneWarmth": 5,
      "toneHumor": 3,
      "sentenceStyle": {
        "mixLengths": true,
        "preferFragments": true
      },
      "emojiUsage": "moderate",
      "punctuationStyle": {
        "useExclamations": true,
        "preferDashes": true
      },
      "doList": [
        "Use analogies and metaphors",
        "Break down complex concepts",
        "Celebrate small wins",
        "Ask rhetorical questions",
        "Share relatable mistakes"
      ],
      "dontList": [
        "Use technical jargon without explanation",
        "Be condescending",
        "Assume prior knowledge",
        "Skip the \"why\"",
        "Be overly formal"
      ],
      "bannedPhrases": [
        "obviously",
        "simply",
        "just",
        "easy",
        "everyone knows"
      ],
      "preferredVocabulary": [
        "here's the deal",
        "real talk",
        "pro tip"
      ],
      "spellingLocale": "US",
      "hashtagMin": 1,
      "hashtagMax": 3,
      "hashtagThemes": [
        "learning",
        "tips"
      ],
      "brandId": "system",
      "isBuiltin": true,
      "isDefault": false,
      "createdBy": "system",
      "createdAt": "2026-10-21T00:00:00.000Z",
      "updatedAt": "2026-10-21T00:00:00.000Z"
    },
    {
      "id": "builtin_punchy_founder",
      "name": "Punchy Founder",
      "description": "Bold, direct voice for founders and entrepreneurs",
      "persona": "Confident founder who's been in the trenches",
      "pointOfView": "first",
      "targetAudience": "Entrepreneurs, startup teams, aspiring founders",
      "audiencePainPoints": [
        "Lack of real-world advice",
        "Survivorship bias",
        "Platitudes"
      ],
      "audienceSophistication": "general",
      "toneFormality": 1,
      "toneBoldness": 5,
      "toneWarmth": 2,
      "toneHumor": 3,
      "sentenceStyle": {
        "maxLength": 15,
        "preferFragments": true,
        "mixLengths": true
      },
      "emojiUsage": "minimal",
      "punctuationStyle": {
        "useExclamations": false,
        "preferDashes": true
      },
      "doList": [
        "Start with a bold claim",
        "Use short, punchy sentences",
        "Share real numbers",
        "Admit failures openly",
        "Give actionable takeaways"
      ],
      "dontList": [
        "Hedge or qualify too much",
        "Use corporate speak",
        "Be preachy",
        "Bury the lead",
        "Overcomplicate"
      ],
      "bannedPhrases": [
        "hustle",
        "grind",
        "crush it",
        "killing it",
        "10x",
        "scale"
      ],
      "preferredVocabulary": [
        "truth is",
        "here's what happened",
        "lesson learned"
      ],
      "spellingLocale": "US",
      "hashtagMin": 0,
      "hashtagMax": 2,
      "hashtagThemes": [
        "startup",
        "founder"
      ],
      "brandId": "system",
      "isBuiltin": true,
      "isDefault": false,
      "createdBy": "system",
      "createdAt": "2026-10-21T00:00:00.000Z",
      "updatedAt": "2026-10-21T00:00:00.000Z"
    },
    {
      "id": "builtin_warm_community",
      "name": "Warm Community Builder",
      "description": "Inclusive voice for building engaged communities",
      "persona": "The welcoming host who makes everyone feel included",
      "pointOfView": "first",
      "targetAudience": "Community members, fans, engaged followers",
      "audiencePainPoints": [
        "Feeling invisible",
        "Generic broadcasts",
        "Lack of connection"
      ],
      "audienceSophistication": "general",
      "toneFormality": 2,
      "toneBoldness": 2,
      "toneWarmth": 5,
      "toneHumor": 4,
      "sentenceStyle": {
        "mixLengths": true
      },
      "emojiUsage": "frequent",
      "punctuationStyle": {
        "useExclamations": true
      },
      "doList": [
        "Address the audience directly",
        "Celebrate community wins",
        "Ask for input and opinions",
        "Share behind-the-scenes",
        "Use inclusive language (we, us)"
      ],
      "dontList": [
        "Sound corporate",
        "Broadcast without engaging",
        "Ignore comments/replies",
        "Be exclusive or gatekeep",
        "Focus only on selling"
      ],
      "bannedPhrases": [
        "valued customer",
        "loyal followers",
        "tribe"
      ],
      "preferredVocabulary": [
        "you all",
        "we",
        "together",
        "our community"
      ],
      "spellingLocale": "US",
      "hashtagMin": 2,
      "hashtagMax": 5,
      "hashtagThemes": [
        "community",
        "engagement"
      ],
      "brandId": "system",
      "isBuiltin": true,
      "isDefault": false,
      "createdBy": "system",
      "createdAt": "2026-10-21T00:00:00.000Z",
      "updatedAt": "2026-10-21T00:00:00.000Z"
    },
    {
      "id": "builtin_minimalist",
      "name": "Minimalist Operator",
      "description": "Clean, no-nonsense voice that gets to the point",
      "persona": "Efficient professional who values clarity over flair",
      "pointOfView": "first",
      "targetAudience": "Busy professionals who value their time",
      "audiencePainPoints": [
        "Verbose content",
        "Unnecessary fluff",
        "Time wasters"
      ],
      "audienceSophistication": "expert",
      "toneFormality": 3,
      "toneBoldness": 3,
      "toneWarmth": 2,
      "toneHumor": 1,
      "sentenceStyle": {
        "maxLength": 12,
        "preferFragments": true
      },
      "emojiUsage": "none",
      "punctuationStyle": {
        "useExclamations": false,
        "preferDashes": false
      },
      "doList": [
        "Lead with the key point",
        "Use bullet points when possible",
        "Cut unnecessary words",
        "Be specific with numbers",
        "One idea per post"
      ],
      "dontList": [
        "Add filler words",
        "Use emojis",
        "Write long intros",
        "Over-explain",
        "Use multiple CTAs"
      ],
      "bannedPhrases": [
        "let me explain",
        "in other words",
        "basically",
        "honestly"
      ],
      "preferredVocabulary": [],
      "spellingLocale": "US",
      "hashtagMin": 0,
      "hashtagMax": 1,
      "hashtagThemes": [],
      "brandId": "system",
      "isBuiltin": true,
      "isDefault": false,
      "createdBy": "system",
      "createdAt": "2026-10-21T00:00:00.000Z",
      "updatedAt": "2026-10-21T00:00:00.000Z"
    }
  ]
}

The saved default appears first. The five system templates follow in shipped order and lack the stored author-context additions; no pagination or limit field is returned.

Refusals

{"limit": 0} is a local-preflight invalid-input example: the current schema requires a positive integer. It is not a simulated HTTP response, a resource probe or permission to send malformed input. Correct the actual field error before transport.

500 / internal_error: The handler catches a preset query/mapping failure, including malformed stored JSON. Preserve request and actual refusal evidence and route the underlying data/dependency issue to its owner; do not change presets or treat it as an empty list.

A missing-brand400 guard exists defensively in the handler, but the normal dispatcher resolves getBrandForVoice first. Omitted selection resolves a verified default or is refused earlier; a named-workspace refusal must not be described as that guard response. Outer Auth/workspace/dependency refusals can use a different carrier. Preserve actual status/code/request id; no precise localized message or live refusal capture is invented here.

Verify and recover

Compare each custom non-builtin brandId to the intended verified workspace and retain actual saved ids/default flags. Treat system template ids as templates, never workspace grants.

Distinguish custom ordering from appended template order. Do not infer a persisted template edit from its read-time timestamps, a stable total from repeated reads or an applied limit from the accepted schema alone.

Read the full presets field and actual response/refusal. A storage/parsing failure is not an empty workspace; a broad schema passing alone does not establish source-to-serving currency.

No automatic compensation is defined for possible authorization-side mirror synchronization. This read does not authorize a preset/audit mutation. Preserve the actual scope/query/request evidence and resolve the specific permission, storage or malformed-data issue through its owner before another authorized read; do not erase or fabricate history.

Change log

  • 2026-10-21: Added source-qualified request, actual ordering/projection/limit behavior and complete synthetic/unrun response examples. Source review does not certify serving deployment, runtime data or provider outcomes; no application imports/tests/business/model/provider calls were performed.