API reference

Brand voice

4 endpoints, served at https://orbitwrite.com/api/v1. Each one lists the credentials it accepts, its parameters and every response it can give.

Read a workspace's brand-voice profile#

GET/api/v1/brand-voice

Any member may read. This is the grounding an AI generation uses — brand description, audience, product context, tone, style rules, exemplars and the distilled learned memo.

Authentication

A signed-in session only. The Orbitwrite app calls this; an API key is refused.

Query parameters

organizationIdstringRequired

At least 1 character.

Responses

200BrandVoiceReadResult

The workspace's profile, or null

Response attributes
okbooleanRequired
profileBrandVoiceProfile | any | nullRequired

Null when the workspace has never configured a profile — a legitimate answer, not an error.

Child attributes
idstringRequired
organizationIdstringRequired
brandDescriptionstringRequired
audiencestringRequired
productContextstringRequired
defaultTonestring | nullRequired
  • "professional"
  • "casual"
  • "bold"
  • "friendly"
  • "thought_leader"
  • "playful"
  • "hype"
  • "punchy"
  • null
styleRulesobjectRequired
Child attributes
dosstring[]

At most 20 items. Defaults to [].

dontsstring[]

At most 20 items. Defaults to [].

bannedPhrasesstring[]

At most 20 items. Defaults to [].

emojiPolicystring
  • "never"
  • "sparing"
  • "freely"
hashtagPolicystring
  • "never"
  • "sparing"
  • "freely"
ctaPolicystring
  • "never"
  • "when_relevant"
  • "always"
languagestring

At most 100 characters. Defaults to "".

exemplarsobject[]Required
Child attributes
idstringRequired

At least 1 character.

textstringRequired

Between 1 and 2000 characters.

notestring

At most 200 characters.

learnedMemostring | nullRequired
learnedMemoVersionintegerRequired

Bumped by the distillation job when it rewrites the memo, so a caller can tell whether a cached memo is stale. Never moved by a settings save.

learnedMemoUpdatedAtstring | nullRequired

ISO 8601.

aiLearningEnabledbooleanRequired
useVoiceSamplesbooleanRequired
createdAtstringRequired

ISO 8601.

updatedAtstringRequired

ISO 8601.

400Error

Invalid request

Response attributes
errorstringRequired
issuesany[]
401Error

Not signed in

Response attributes
errorstringRequired
issuesany[]
403Error

Not a member of the organization

Response attributes
errorstringRequired
issuesany[]
GET /api/v1/brand-voice
curl -X GET "https://orbitwrite.com/api/v1/brand-voice?organizationId=organizationId" \
  -H "Authorization: Bearer $ORBITWRITE_API_KEY"
Response
{
  "ok": true,
  "profile": {
    "id": "string",
    "organizationId": "string",
    "brandDescription": "string",
    "audience": "string",
    "productContext": "string",
    "defaultTone": "professional",
    "styleRules": {
      "dos": [],
      "donts": [],
      "bannedPhrases": [],
      "emojiPolicy": "never",
      "hashtagPolicy": "never",
      "ctaPolicy": "never",
      "language": ""
    },
    "exemplars": [
      {
        "id": "string",
        "text": "string",
        "note": "string"
      }
    ],
    "learnedMemo": "string",
    "learnedMemoVersion": 0,
    "learnedMemoUpdatedAt": "string",
    "aiLearningEnabled": true,
    "useVoiceSamples": true,
    "createdAt": "string",
    "updatedAt": "string"
  }
}

Seed a workspace's default tone (onboarding)#

POST/api/v1/brand-voice

Creates a profile carrying only the chosen tone. Any member may seed — it is part of onboarding — but an existing profile is never overwritten.

Authentication

A signed-in session only. The Orbitwrite app calls this; an API key is refused.

Body application/json

organizationIdstringRequired

At least 1 character.

defaultTonestringRequired
  • "professional"
  • "casual"
  • "bold"
  • "friendly"
  • "thought_leader"
  • "playful"
  • "hype"
  • "punchy"

Responses

200BrandVoiceSeedResult

The profile, and whether this call created it

Response attributes
okbooleanRequired
seededbooleanRequired

False when a profile already existed and was left untouched — so a caller isn't left assuming its tone was applied.

profileBrandVoiceProfile | any | nullRequired
Child attributes
idstringRequired
organizationIdstringRequired
brandDescriptionstringRequired
audiencestringRequired
productContextstringRequired
defaultTonestring | nullRequired
  • "professional"
  • "casual"
  • "bold"
  • "friendly"
  • "thought_leader"
  • "playful"
  • "hype"
  • "punchy"
  • null
styleRulesobjectRequired
Child attributes
dosstring[]

At most 20 items. Defaults to [].

dontsstring[]

At most 20 items. Defaults to [].

bannedPhrasesstring[]

At most 20 items. Defaults to [].

emojiPolicystring
  • "never"
  • "sparing"
  • "freely"
hashtagPolicystring
  • "never"
  • "sparing"
  • "freely"
ctaPolicystring
  • "never"
  • "when_relevant"
  • "always"
languagestring

At most 100 characters. Defaults to "".

exemplarsobject[]Required
Child attributes
idstringRequired

At least 1 character.

textstringRequired

Between 1 and 2000 characters.

notestring

At most 200 characters.

learnedMemostring | nullRequired
learnedMemoVersionintegerRequired

Bumped by the distillation job when it rewrites the memo, so a caller can tell whether a cached memo is stale. Never moved by a settings save.

learnedMemoUpdatedAtstring | nullRequired

ISO 8601.

aiLearningEnabledbooleanRequired
useVoiceSamplesbooleanRequired
createdAtstringRequired

ISO 8601.

updatedAtstringRequired

ISO 8601.

400Error

Invalid request

Response attributes
errorstringRequired
issuesany[]
401Error

Not signed in

Response attributes
errorstringRequired
issuesany[]
403Error

Not a member of the organization

Response attributes
errorstringRequired
issuesany[]
POST /api/v1/brand-voice
curl -X POST "https://orbitwrite.com/api/v1/brand-voice" \
  -H "Authorization: Bearer $ORBITWRITE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "organizationId": "string",
  "defaultTone": "professional"
}'
Response
{
  "ok": true,
  "seeded": true,
  "profile": {
    "id": "string",
    "organizationId": "string",
    "brandDescription": "string",
    "audience": "string",
    "productContext": "string",
    "defaultTone": "professional",
    "styleRules": {
      "dos": [],
      "donts": [],
      "bannedPhrases": [],
      "emojiPolicy": "never",
      "hashtagPolicy": "never",
      "ctaPolicy": "never",
      "language": ""
    },
    "exemplars": [
      {
        "id": "string",
        "text": "string",
        "note": "string"
      }
    ],
    "learnedMemo": "string",
    "learnedMemoVersion": 0,
    "learnedMemoUpdatedAt": "string",
    "aiLearningEnabled": true,
    "useVoiceSamples": true,
    "createdAt": "string",
    "updatedAt": "string"
  }
}

Save a workspace's brand-voice profile#

PUT/api/v1/brand-voice

Requires brandVoice:update (owner/admin/manager). A full save of the content fields; learnedMemo and the AI toggles fall back to their stored values when omitted, so a partial client never wipes what the distillation job learned or silently turns learning off.

Authentication

A signed-in session only. The Orbitwrite app calls this; an API key is refused.

Body application/json

brandDescriptionstring

At most 2000 characters. Defaults to "".

audiencestring

At most 2000 characters. Defaults to "".

productContextstring

At most 2000 characters. Defaults to "".

defaultTonestring | null
  • "professional"
  • "casual"
  • "bold"
  • "friendly"
  • "thought_leader"
  • "playful"
  • "hype"
  • "punchy"
  • null
styleRulesobject

Defaults to {}.

Child attributes
dosstring[]

At most 20 items. Defaults to [].

dontsstring[]

At most 20 items. Defaults to [].

bannedPhrasesstring[]

At most 20 items. Defaults to [].

emojiPolicystring
  • "never"
  • "sparing"
  • "freely"
hashtagPolicystring
  • "never"
  • "sparing"
  • "freely"
ctaPolicystring
  • "never"
  • "when_relevant"
  • "always"
languagestring

At most 100 characters. Defaults to "".

exemplarsobject[]

At most 8 items. Defaults to [].

Child attributes
idstringRequired

At least 1 character.

textstringRequired

Between 1 and 2000 characters.

notestring

At most 200 characters.

learnedMemostring | null

At most 8000 characters.

organizationIdstringRequired

At least 1 character.

Responses

200BrandVoiceUpdateResult

The saved profile

Response attributes
okbooleanRequired
profileBrandVoiceProfileRequired
Child attributes
idstringRequired
organizationIdstringRequired
brandDescriptionstringRequired
audiencestringRequired
productContextstringRequired
defaultTonestring | nullRequired
  • "professional"
  • "casual"
  • "bold"
  • "friendly"
  • "thought_leader"
  • "playful"
  • "hype"
  • "punchy"
  • null
styleRulesobjectRequired
Child attributes
dosstring[]

At most 20 items. Defaults to [].

dontsstring[]

At most 20 items. Defaults to [].

bannedPhrasesstring[]

At most 20 items. Defaults to [].

emojiPolicystring
  • "never"
  • "sparing"
  • "freely"
hashtagPolicystring
  • "never"
  • "sparing"
  • "freely"
ctaPolicystring
  • "never"
  • "when_relevant"
  • "always"
languagestring

At most 100 characters. Defaults to "".

exemplarsobject[]Required
Child attributes
idstringRequired

At least 1 character.

textstringRequired

Between 1 and 2000 characters.

notestring

At most 200 characters.

learnedMemostring | nullRequired
learnedMemoVersionintegerRequired

Bumped by the distillation job when it rewrites the memo, so a caller can tell whether a cached memo is stale. Never moved by a settings save.

learnedMemoUpdatedAtstring | nullRequired

ISO 8601.

aiLearningEnabledbooleanRequired
useVoiceSamplesbooleanRequired
createdAtstringRequired

ISO 8601.

updatedAtstringRequired

ISO 8601.

400Error

Invalid request

Response attributes
errorstringRequired
issuesany[]
401Error

Not signed in

Response attributes
errorstringRequired
issuesany[]
403Error

Not a member of the organization

Response attributes
errorstringRequired
issuesany[]
PUT /api/v1/brand-voice
curl -X PUT "https://orbitwrite.com/api/v1/brand-voice" \
  -H "Authorization: Bearer $ORBITWRITE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "organizationId": "string"
}'
Response
{
  "ok": true,
  "profile": {
    "id": "string",
    "organizationId": "string",
    "brandDescription": "string",
    "audience": "string",
    "productContext": "string",
    "defaultTone": "professional",
    "styleRules": {
      "dos": [],
      "donts": [],
      "bannedPhrases": [],
      "emojiPolicy": "never",
      "hashtagPolicy": "never",
      "ctaPolicy": "never",
      "language": ""
    },
    "exemplars": [
      {
        "id": "string",
        "text": "string",
        "note": "string"
      }
    ],
    "learnedMemo": "string",
    "learnedMemoVersion": 0,
    "learnedMemoUpdatedAt": "string",
    "aiLearningEnabled": true,
    "useVoiceSamples": true,
    "createdAt": "string",
    "updatedAt": "string"
  }
}

Distill learned style notes from editing history#

POST/api/v1/brand-voice/distill

Requires brandVoice:update. Rewrites the learned memo from the workspace's generation history and bumps learnedMemoVersion.

Authentication

A signed-in session only. The Orbitwrite app calls this; an API key is refused.

Body application/json

organizationIdstringRequired

At least 1 character.

Responses

200BrandVoiceDistillResult

The refreshed memo

Response attributes
okbooleanRequired
memostringRequired
versionintegerRequired
countsobjectRequired
Child attributes
editedPairsintegerRequired
shippedUnchangedintegerRequired
refineEventsintegerRequired
rejectionCommentsintegerRequired
400Error

Invalid request

Response attributes
errorstringRequired
issuesany[]
401Error

Not signed in

Response attributes
errorstringRequired
issuesany[]
403Error

Not a member of the organization

Response attributes
errorstringRequired
issuesany[]
422Error

Learning disabled for the workspace, or not enough signal

Response attributes
errorstringRequired
issuesany[]
500Error

Distillation failed

Response attributes
errorstringRequired
issuesany[]
POST /api/v1/brand-voice/distill
curl -X POST "https://orbitwrite.com/api/v1/brand-voice/distill" \
  -H "Authorization: Bearer $ORBITWRITE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "organizationId": "string"
}'
Response
{
  "ok": true,
  "memo": "string",
  "version": 0,
  "counts": {
    "editedPairs": 0,
    "shippedUnchanged": 0,
    "refineEvents": 0,
    "rejectionComments": 0
  }
}