Brand voice, factsheet, and profile
Read and edit the brand voice, factsheet, and company profile that ground every piece of content.
Brand voice, the factsheet, the company profile, and the business facts are a brand's source-of-truth context: how it writes, what it does, who it's for, and how to reach it. Read these before generating any content so it matches the brand; edit them to keep the brand's positioning current. This context is what content workflows draw on when writing — see Build a workflow.
When to use
Read (get_*) before writing content, so tone and facts are accurate. Patch by hand (update_*) for targeted edits. Rebuild from the knowledge base (rebuild_brand_voice / regenerate_factsheet) when the underlying material has changed and you want a fresh pass. A field returned as null is empty in Pendium, not unsupported.
Typical sequence
get_brand_voice,get_factsheet, and/orget_company_profileto load current context.- Edit by hand:
update_brand_voice,update_factsheet,update_company_profile. - Or regenerate from knowledge:
rebuild_brand_voice,regenerate_factsheet(background, Paid). - For contact details, hours, service areas, testimonials, and the brand's star rating:
get_business_facts, thenupdate_business_facts.
Tools
get_brand_voice
Get brand voice guidelines plus the core company profile — voice summary, tone traits, style guide, emotional tone targets, storytelling style, do/don't examples, writing examples, visual aesthetics, and the positioning fields (what we do, offerings label, who it's for, target audience, key facts, credibility signals, AI-ready answers, business profiles, and more). Use it to write content that matches the brand's tone.
Authentication: Required.
Type: Read-only.
| Parameter | Type | Required | Description |
|---|---|---|---|
syntheticId | integer | Yes | The agent ID to get brand voice for. |
Either brandVoice or companyProfile may be null if the brand hasn't completed onboarding for that data. For only the company profile (every stored field), use get_company_profile.
update_brand_voice
Patch a brand's voice guidelines — the tone and style settings that steer how content is written. Partial update: only the fields you pass change; object fields (storytellingStyle, examples, writingExamples, visualAesthetics) are replaced wholesale. Synchronous, no LLM call, no credit cost. Pass at least one field — an all-empty update is rejected. Call get_brand_voice first to see current values.
Authentication: Required.
Type: Write — non-destructive.
| Parameter | Type | Required | Description |
|---|---|---|---|
syntheticId | integer | Yes | The agent whose brand voice to update. |
voiceSummary | string | No | How the brand communicates — tone, personality, positioning. |
formalityLevel | enum | No | casual, neutral, or professional. |
sentenceLength | enum | No | short, medium, or long. |
useOfEmojis | enum | No | never, sometimes, or often. |
useOfHashtags | enum | No | minimal, moderate, or strategic. |
preferredPerspective | string | No | Preferred narrative perspective (e.g. first-person, third-person, mixed). |
coreToneTraits | array | No | Core tone traits (replaces the existing list). Each item is { trait, description }. |
emotionalToneTargets | array | No | Emotional goals for content, e.g. ["inspire action", "build trust"] (replaces the existing list). |
storytellingStyle | object | No | { narrativePreference, callToActionStyle } (replaces the existing object). |
examples | object | No | Do / don't examples: { do[], dont[] } (replaces the existing object). |
writingExamples | object | No | { headlineExample, captionExample, responseExample } (replaces the existing object). |
visualAesthetics | object | No | { typography, designAesthetic, logoPresence, logoStyle } (replaces the existing object). |
The style enums plus preferredPerspective are stored under styleGuide; passing only some leaves the rest of styleGuide untouched. To edit the company profile instead, use update_company_profile. To rebuild the whole voice from the knowledge base, use rebuild_brand_voice.
rebuild_brand_voice
Regenerate the brand voice from the agent's knowledge base, falling back to the company profile when no knowledge sources exist. Runs in the background — returns immediately after enqueueing (status: "queued"); the rebuilt voice lands a short while later. Already-populated fields are preserved. Poll get_brand_voice after a minute or two to see the result.
Authentication: Paid — requires a Starter or Pro plan (LLM regeneration).
Type: Write — non-destructive.
| Parameter | Type | Required | Description |
|---|---|---|---|
syntheticId | integer | Yes | The agent whose brand voice to rebuild. |
To patch individual voice fields by hand instead (no plan requirement), use update_brand_voice.
get_factsheet
Get the brand's factsheet — a comprehensive markdown overview of the company, its products, positioning, and key facts. Auto-generated during onboarding from website content and optionally refined by the brand owner. Use it as foundational context when writing any content.
Authentication: Required.
Type: Read-only.
| Parameter | Type | Required | Description |
|---|---|---|---|
syntheticId | integer | Yes | The agent ID to get the factsheet for. |
Returns content (markdown), autoGeneratedAt, lastEditedAt, and interviewAnswers (onboarding responses — differentiators, customers, etc.). The factsheet field is null if the brand hasn't completed onboarding.
update_factsheet
Replace the brand's factsheet content. This overwrites the whole factsheet with the text you provide (it's not a merge). Synchronous, no LLM call, no credit cost. The change takes effect immediately across the dashboard's brand-context surfaces. Use get_factsheet first to see the current content.
Authentication: Required.
Type: Write — non-destructive.
| Parameter | Type | Required | Description |
|---|---|---|---|
syntheticId | integer | Yes | The agent whose factsheet to update. |
content | string | Yes | The full factsheet content (replaces the existing factsheet). |
To regenerate it from the knowledge base instead, use regenerate_factsheet.
regenerate_factsheet
Regenerate the brand factsheet from the agent's knowledge base. Runs in the background — returns immediately after enqueueing (status: "queued"); the new factsheet lands a short while later and replaces the existing one even if a factsheet already exists. Poll get_factsheet after a minute or two to see the result.
If the brand's knowledge comes only from its own website and nobody has edited the factsheet by hand, it's rebuilt from the facts already read off the site, each listed with the page it came from. Your Do NOT Claim list and interview answers stay. The website itself isn't re-read.
Authentication: Paid — requires a Starter or Pro plan (LLM regeneration).
Type: Write — non-destructive.
| Parameter | Type | Required | Description |
|---|---|---|---|
syntheticId | integer | Yes | The agent whose factsheet to regenerate. |
To set the factsheet text by hand instead (no plan requirement), use update_factsheet.
get_company_profile
Get the complete company profile — every stored positioning field, exactly as entered in the Pendium UI. This is the full read-only export of the brand's source-of-truth positioning data.
Authentication: Required.
Type: Read-only.
| Parameter | Type | Required | Description |
|---|---|---|---|
syntheticId | integer | Yes | The agent ID to get the company profile for. |
Includes offeringsLabel, whatWeDo, whoItsFor (personas), targetAudience, keyFacts, credibilitySignals, aiReadyAnswers, businessProfiles, brandAliases (other names the same business answers to), and more. companyProfile is null if the brand hasn't created a profile yet; any individual field returned as null is empty, not unsupported. For brand voice (tone, style guide, writing examples), use get_brand_voice.
update_company_profile
Patch a brand's company profile — what it does, who it's for, key facts, credibility signals, offerings, AI-ready answers, and more. Partial update: only the fields you pass change; array/object fields are replaced wholesale. Synchronous, no LLM call, no credit cost. Pass at least one field — an all-empty update is rejected. Use get_company_profile first to see current values.
Authentication: Required.
Type: Write — non-destructive.
| Parameter | Type | Required | Description |
|---|---|---|---|
syntheticId | integer | Yes | The agent whose company profile to update. |
name | string | No | Company or brand name. |
tagline | string | No | Company tagline or slogan. |
industry | string | No | Primary industry or sector. |
website | string | No | Company website URL. |
description | string | No | Comprehensive company description. |
missionStatement | string | No | Company mission or purpose statement. |
uniqueValueProposition | string | No | What makes the company unique. |
geographicFocus | string | No | Geographic market focus. |
brandPersonality | string | No | Brand personality description. |
whatWeDo | string | No | Rich explanation of what the company does (2-4 sentences). |
offeringsLabel | enum | No | Offerings category label: Services, Products, or Features. |
productsOrServices | array | No | Products or services offered (replaces the existing list). |
competitorsOrPeers | array | No | Competitors or peer brands (replaces the existing list). |
brandAliases | array | No | Other names this same business answers to: its pre-rebrand name, a DBA, an alternate spelling (replaces the existing list). Visibility scans credit a mention of any alias to the brand. Put the current name in name, never a compound like "X fka Y". |
credibilitySignals | array | No | Trust signals — awards, partnerships, metrics (replaces the existing list). |
keyFacts | array | No | Business facts — each item is { label, value } (replaces the existing list). |
whoItsFor | array | No | Target personas — each item is { title, description, painPoints[] } (replaces the existing list). |
targetAudience | object | No | Structured audience { demographics, psychographics, keyPainPoints, desiredOutcomes } (replaces the existing object). |
aiReadyAnswers | array | No | Q&A pairs, each { question, answer, group? } (replaces the existing list). These are also the questions on the brand's FAQ page; group is the FAQ section heading they appear under (omit it for the default section). |
socialHandles | object | No | Per-platform handles { instagram, facebook, linkedin, twitter_x, tiktok, youtube } (replaces the existing object — include every handle you want to keep). Scrapeable profiles (LinkedIn company pages, YouTube channels) are also read into the brand's knowledge base in the background; changing or clearing one cleans up the old profile's knowledge automatically. |
businessProfiles | object | No | External business profile URLs (replaces the existing object, so include every URL you want to keep; read get_company_profile first). Services: yelp, googleBusiness, angi, thumbtack, facebook, other. Tech: g2, capterra, githubOrg, substack, medium, otherTech. Products: trustpilot, sitejabber, consumerAffairs, amazon, otherProducts. Plus additionalLinks, a list of { url, category } (services, tech, or products) for extra links. Saved profile pages count as the brand's owned sources. |
keyPages | array | No | Curated brand pages for internal linking — each item is { url, title, description?, instructions? } (replaces the existing list). |
toneExamples | object | No | Example on-brand content { websiteExcerpt?, socialMediaExcerpt? } (replaces the existing object). |
To edit brand voice (tone, style, writing examples) instead, use update_brand_voice.
get_business_facts
Read the brand's business facts: phone, email, address, opening hours, service areas, named services, testimonials, star rating, and booking link. These are the details a customer looks for first, and the details an AI engine repeats when it answers a question about the brand.
rating is { value, count, source } — the score (above 0, up to 5), how many reviews it rests on (1 or more), and which platform reports it (yelp, google, or manual for a rating the owner typed in). It is null when no platform reports one; a score of zero, or a score with no reviews behind it, is stored as no rating rather than as a zero.
Authentication: Required.
Type: Read-only.
| Parameter | Type | Required | Description |
|---|---|---|---|
syntheticId | integer | Yes | The agent whose business facts to read. |
The response carries facts and a source that says where the answer came from:
source | Meaning |
|---|---|
row | The brand owner saved these values. |
listings | Nothing is saved yet. These are what the brand's Yelp and Google listings reported when the agent was created, and the owner has not confirmed them. |
none | Nothing is saved and there was no listing to read, so every field is empty. |
Read this before writing anything that states an address, a phone number, or opening hours. For positioning, offerings, and audience, use get_company_profile instead.
update_business_facts
Save the brand's business facts. Partial update: only the fields you pass change, and anything you leave out keeps its current value. Pass at least one field. List fields (hours, serviceAreas, services, testimonials) are replaced wholesale when you pass them, so include every entry you want to keep. To clear something, pass null for a single-value field (phone, email, address, bookingUrl, rating) and [] for a list field. Synchronous, no LLM call, no credit cost.
Authentication: Required.
Type: Write, non-destructive.
| Parameter | Type | Required | Description |
|---|---|---|---|
syntheticId | integer | Yes | The agent whose business facts to update. |
phone | string or null | No | Public phone number. |
email | string or null | No | Public contact email. Must look like an address a customer could write to. |
address | string or null | No | Street address on one line, as the brand would print it. |
hours | array | No | Opening hours. Each item is { day, hours }, for example { "day": "Mon", "hours": "9:00 AM - 5:00 PM" } (replaces the existing list). |
serviceAreas | array | No | Neighborhoods, cities, or regions the brand serves (replaces the existing list). |
services | array | No | Named services or offerings (replaces the existing list). |
testimonials | array | No | Customer quotes. Each item is { quote, author?, source, url? } (replaces the existing list). See the note on source below. |
rating | object or null | No | The brand's star rating: { value, count, source }. value is the score above 0 and up to 5, count is a whole number of reviews, 1 or more, and source is yelp, google, or manual. The brand's homepage states it above the headline as one line, for example 4.3 ★ from 114 Yelp reviews. See the note on rating below. |
bookingUrl | string or null | No | Where a visitor books, orders, or requests a quote. Must be a full http:// or https:// link, because the site renders it as a link. |
Call get_business_facts first. If it returns source: "listings", the values you can see came from the brand's listings and the owner has never confirmed them; saving any one field promotes the whole set to the owner's own, so check them before you write. Write only what the brand owner told you: these facts are what the brand's site states as its address, phone, and hours. Never invent a phone number, an address, a testimonial, or a rating, and never copy one from a search result or a competitor.
On a testimonial's source. A quote's source is a claim about where a real customer left it, so only Pendium's own listing import can set yelp or google. A quote you add, or one whose words you change, is saved as manual whatever you pass. A quote you send back unchanged keeps the source it already had. Nothing is rejected for this; the value is simply corrected on write, and the response shows what was stored.
On the rating. A rating starts out as whatever the brand's listings reported when the agent was created: the Yelp score when Yelp reports both a score and a review count, otherwise the Google one, with source naming the platform that answered. A platform is never named for a number that did not come from it, so the same rule as a testimonial's source applies here — change either half of a rating and it is saved as manual whatever you pass, and a rating you send back unchanged keeps the platform it already had. A score outside 0 to 5, a score of zero, or a review count that is not a whole number of at least one, is rejected rather than saved: a rating with no reviews behind it is the absence of a rating, which this field spells null.
To edit positioning, offerings, or audience instead, use update_company_profile.