---
title: "Learn the workspace voice from past posts"
method: POST
path: "/api/v1/strategy/learn"
tags: ["strategy"]
---

# Learn the workspace voice from past posts

`POST /api/v1/strategy/learn`

## Request

- Base URL: `https://api.cadencz.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.cadencz.com/api/v1/strategy/learn`
- Auth: HTTP bearer

Runs the smart-tier voice agent over 5-10 past posts, extracts a tone profile, and stores it on the strategy so every future draft is written in the user's voice.

## Request body

- LearnVoiceRequest
  - `posts` string[], required: 5-10 of the user's past posts. The voice agent learns their tone from these.
  - `niche` string, nullable
  - `writing_notes` string, nullable
  - `avoid_style` string, nullable
  - `platform` string, nullable: The platform these posts were written for (x, linkedin, threads, …). The tone learned from them is then used for that platform's drafts only. Omit for posts that stand for every platform.

## Response `200`

Successful Response

- LearnVoiceResponse
  - `run_id` string, required
  - `voice` object, required
  - `strategy` StrategyRead, required
    - `workspace_id` string, required
    - `niche` string, nullable, required
    - `goals` string[], required
    - `whats_new` string, nullable
    - `tags` string[], required
    - `tone_profile` object, required
    - `voice_profile` VoiceProfile, required: The whole authored document. Empty is valid — it just means untouched.
      - `personas` VoicePersona[]
        - `id` string, required
        - `name` string
        - `audience` string
        - `context` string
        - `mission` string
        - `traits` string[]
        - `goals` string[]
        - `tone` ToneAxis[]
          - `id` string, required
          - `low` string, required
          - `high` string, required
          - `value` integer
        - `vocabulary` string[]
        - `banned_words` string[]
        - `ctas` string[]
        - `formatting` string[]
        - `active` boolean
        - `created_at` string, date-time, nullable
        - `updated_at` string, date-time, nullable
      - `versions` VoiceVersion[]
        - `id` string, required
        - `persona_id` string, required
        - `label` string
        - `saved_at` string, date-time, required
        - `snapshot` VoicePersona, required: A named way of speaking. Exactly one persona is active at a time.
          - `id` string, required
          - `name` string
          - `audience` string
          - `context` string
          - `mission` string
          - `traits` string[]
          - `goals` string[]
          - `tone` ToneAxis[]
            - `id` string, required
            - `low` string, required
            - `high` string, required
            - `value` integer
          - `vocabulary` string[]
          - `banned_words` string[]
          - `ctas` string[]
          - `formatting` string[]
          - `active` boolean
          - `created_at` string, date-time, nullable
          - `updated_at` string, date-time, nullable
    - `voice_samples` string[], required
    - `voice_sample_platforms` object
    - `voice_platforms_learned` string[]
    - `cadence_per_week` integer, required
    - `platforms` string[], required
    - `automation` AutomationSettings, required: When the agents plan, and when the posts they produce go out.
      - `enabled` boolean: Off by default. Auto-planning spends credits, so it's opt-in.
      - `suspended_by_plan` boolean: Cadencz turned automation off after plan access was lost. The saved schedule remains, but the customer must explicitly enable it again.
      - `auto_write_week` boolean: Write the week's posts on their own at the planning hour, so the stack always has a fresh week on it. Every plan; bounded by the tier's weekly number and the monthly pool. Distinct from `enabled`, which is the paid Automation feature (rules, auto-approve).
      - `plan_weekday` integer: 0 = Monday.
      - `plan_hour` integer: Local hour, 24h.
      - `timezone` string: IANA zone.
      - `posting_weekdays` integer[]: Days posts may be scheduled on. 0 = Monday.
      - `posting_times` string[]: HH:MM slots, cycled through in order.
      - `day_platforms` object: Which channel each weekday posts to, keyed by weekday index as a string ('0' = Monday). A day with no entry falls back to the workspace's platform rotation.
      - `platform_quota` object: How many posts each channel gets per batch, keyed by platform id. The batch is their sum. Zero (or absent) means the channel gets none; empty means the planner decides per post from cadence.
      - `brain_id` string, nullable: Ground posts in this Brain. None = the most recently updated.
      - `auto_approve` boolean: Schedule straight to the calendar instead of holding for review.
    - `updated_at` string, date-time, required

## Other responses

- `401`: Missing or invalid Supabase bearer token.
- `422`: Validation Error
- `502`: The upstream provider rejected the request.
- `503`: Required infrastructure or provider config is unavailable.

---

[API](https://skmtc.dev/cadencz/apis/cadencz-api.md) · [All operations](https://skmtc.dev/cadencz/apis/cadencz-api/llms.txt) · [OpenAPI document](https://skmtc.dev/cadencz/apis/cadencz-api/revisions/3392fe5e93db?raw)
