connect hold your voice to your automations, ai agents, n8n workflows, and ci pipelines. pipe any document through voice analysis without opening a browser tab.
api keys live in the app under settings → api & mcp. you get up to 10 active keys per account — name them by integration so you can revoke individual ones without breaking everything else.
all keys start with hyv_live_ followed by 48 lowercase hex characters. never commit keys to git — use environment variables.
the full key is shown once at creation time. copy it immediately — we only store the hash. if you lose it, delete and recreate.
Authorization: Bearer hyv_live_<your-key>
curl https://holdyourvoice.com/v1/usage \ -H "Authorization: Bearer hyv_live_<your-key>"
base url: https://holdyourvoice.com — all v1 endpoints require the authorization header above. responses are json. errors return {"error": "...", "error_code": "..."} with the appropriate http status code.
| endpoint | what it does | quota? |
|---|---|---|
| POST /v1/analyze | analyze text against a voice profile — returns score, highlights, per-signal breakdown, and a cost block | unmetered |
| POST /v1/rewrite | rewrite a flagged passage to fix a specific drift signal | unmetered |
| GET /v1/profiles | list voice profiles you can access (own + team-shared) | free |
| GET /v1/usage | current month quota, limits, and per-brand 30-day token breakdown | free |
| GET /v1/context | slash-command context: plan, byok billing, profiles, recent documents, and team/byok user rollups | free |
| GET /v1/documents | list documents (paginated by limit and offset) | free |
| POST /v1/documents | create a new document | 1 slot |
| GET /v1/documents/:id | fetch a single document by id | free |
| PUT /v1/documents/:id | update title or content of an existing document (a substantial content swap charges 1 slot — see abuse guard below) | free* |
every endpoint that takes a voice profile accepts any of these identifier forms on a brand, profile, or profile_id field — matched in this precedence:
| form | example | matching |
|---|---|---|
| uuid | "550e8400-e29b-41d4-a716-446655440000" | exact — canonical id |
| slug | "acme-co" | exact, lowercase kebab-case |
| name | "Acme Co" | exact, case-insensitive, unicode-normalised |
| business | "Acme Corporation" | exact, case-insensitive |
| partial | "acme" | substring match (3+ chars) on name or business |
if a fuzzy query matches more than one profile, the api returns 400 with the candidate list so your tool can disambiguate instead of guessing.
{
"error": "Profile query 'Growth' is ambiguous — matched 2 profiles...",
"error_code": "profile_ambiguous",
"query": "Growth",
"candidates": [
{ "id": "...", "name": "Growth Inc", "business": "Growth Inc", "slug": "growth-a" },
{ "id": "...", "name": "Growth Labs", "business": "Growth Labs", "slug": "growth-b" }
]
}
pass any text and optionally a brand. get back a drift score, flagged highlights, remaining quota, and a cost block so you can see whether the call was billed to our platform or your own provider key (byok).
curl -X POST https://holdyourvoice.com/v1/analyze \
-H "Authorization: Bearer hyv_live_<your-key>" \
-H "Content-Type: application/json" \
-d '{
"text": "our platform leverages best-in-class ai to deliver robust synergies",
"brand": "Acme Co"
}'
{
"highlights": [
{ "text": "leverages best-in-class ai", "signal": "corporate_filler", "severity": "high", "suggestion": "try: uses ai" },
{ "text": "robust synergies", "signal": "buzzword_stacking", "severity": "high", "suggestion": "try: real results" }
],
"signal_score_delta": { "corporate_filler": -28, "buzzword_stacking": -30 },
"trust_tools_present": [],
"trust_tools_missing": [ "specific_numbers", "attributed_quote" ],
"profile_id": "550e8400-e29b-41d4-a716-446655440000",
"remaining": { "documents": 47, "rewrites": null },
"cost": {
"paid_by": "hyv_platform",
"model": "claude-haiku-4-5-20251001",
"input_tokens": 420,
"output_tokens": 180
}
}
takes the original sentence and a specific drift signal. returns a rewrite that fixes that signal while preserving meaning. uses the same brand-resolution rules.
curl -X POST https://holdyourvoice.com/v1/rewrite \
-H "Authorization: Bearer hyv_live_<your-key>" \
-H "Content-Type: application/json" \
-d '{
"text": "leverages best-in-class ai to deliver robust synergies",
"issue": "corporate_filler",
"brand": "acme-co"
}'
{
"rewritten": "uses ai to get real results",
"original": "leverages best-in-class ai to deliver robust synergies",
"profile_id": "550e8400-e29b-41d4-a716-446655440000",
"remaining": { "documents": 47, "rewrites": null },
"cost": {
"paid_by": "hyv_platform",
"model": "claude-haiku-4-5-20251001",
"input_tokens": 180,
"output_tokens": 95
}
}
returns every profile you can access — your own and any shared with your team. each row carries an ownership marker so your tool can distinguish them.
curl https://holdyourvoice.com/v1/profiles \ -H "Authorization: Bearer hyv_live_<your-key>"
{
"profiles": [
{
"id": "550e8400-...",
"name": "Acme Co",
"business": "Acme Corporation",
"slug": "acme-co",
"industry": "saas",
"voice_keywords": [ "direct", "specific", "first-person" ],
"voice_descriptions": { "direct": "...", "specific": "..." },
"is_default": true,
"ownership": "own",
"team_id": null,
"created_at": "2026-02-10T12:00:00Z",
"updated_at": "2026-04-18T09:14:22Z"
},
{
"id": "6ba7b810-...",
"name": "Shared Brand",
"business": "Shared Brand LLC",
"slug": "shared-brand",
"ownership": "team",
"team_id": "team-acme-0000",
"is_default": false
/* ... */
}
]
}
the by_brand_30d array lets agencies managing many brands see which one is consuming what. null-profile rows land in the unattributed bucket for legacy calls that predate brand tagging.
{
"plan": "team",
"plan_active": true,
"is_byok": false,
"token_billing": "hyv_platform",
"period": "2026-04",
"documents_used": 12,
"rewrites_used": 0,
"remaining": { "documents": 288, "rewrites": null },
"limits": {
"documents": 300,
"rewrites": null,
"rpm": 60
},
"quota_model": {
"document_create": "counted_monthly",
"analyze": "unmetered",
"rewrite": "unmetered_monthly_legacy"
},
"by_brand_30d": [
{ "profile_id": "550e...", "name": "Acme Co", "slug": "acme-co", "scope": "own", "analyses": 47, "rewrites": 18, "input_tokens": 32100, "output_tokens": 9200 },
{ "profile_id": "6ba7...", "name": "Shared Brand", "slug": "shared-brand", "scope": "team", "analyses": 22, "rewrites": 5, "input_tokens": 14500, "output_tokens": 3400 },
{ "profile_id": null, "name": null, "slug": null, "scope": "unattributed", "analyses": 3, "rewrites": 0, "input_tokens": 1900, "output_tokens": 400 }
]
}
documents created via the api appear in your hold your voice editor. create uses 1 monthly slot. updates are free unless the new content is substantially different from the last counted version — see the abuse guard note below.
curl -X POST https://holdyourvoice.com/v1/documents \
-H "Authorization: Bearer hyv_live_<your-key>" \
-H "Content-Type: application/json" \
-d '{
"title": "q2 product announcement",
"content": "your draft text here...",
"brand": "Acme Co"
}'
curl -X PUT https://holdyourvoice.com/v1/documents/doc_abc123 \
-H "Authorization: Bearer hyv_live_<your-key>" \
-H "Content-Type: application/json" \
-d '{ "content": "updated draft..." }'
| status | error_code | meaning |
|---|---|---|
| 401 | — | missing or invalid api key |
| 402 | — | plan inactive (none / expired) — renew to resume api access |
| 403 | — | scope denied (e.g. key without rewrite scope calling /v1/rewrite) |
| 400 | profile_ambiguous | brand query matched more than one profile — see candidates array |
| 404 | profile_not_found | the brand query didn't resolve in your workspace |
| 429 | — | rpm exceeded (60 req/min on paid plans) |
| 429 | submission_quota_exceeded | a put hit the abuse guard and you have no remaining document slots — upgrade plan or edit existing doc |
| 500 | — | server error — retry with exponential backoff |
v1 onboarding is intentionally simple: upgrade to a paid plan, create a scoped key under settings → api & mcp, then paste the prompt below into codex, cursor, or another local agent. the agent installs the mcp server and verifies the connection for you.
set up hold your voice mcp in this local agent environment. context: - hold your voice api and mcp access require an active paid plan. this key was created from a paid account. - the public setup contract is https://holdyourvoice.com/.well-known/agent-onboarding - the mcp server card is https://holdyourvoice.com/.well-known/mcp/server-card.json requirements: 1. prefer remote MCP at https://holdyourvoice.com/mcp and complete OAuth when this client supports remote MCP. 2. otherwise configure a local server named hyv with command "npx" and args ["@holdyourvoice/hyv", "mcp"]. 3. use HYV_API_KEY only for the local transport; do not print, commit, or share it. 4. set HYV_BASE_URL to https://holdyourvoice.com unless i explicitly gave you another endpoint. 5. install /hyv-status from https://holdyourvoice.com/.well-known/agent-commands/hyv-status.md if your agent supports custom slash commands. 6. verify the setup by calling hyv_get_context, hyv_get_usage, and hyv_profiles. 7. after verification, use /hyv-status for account context and use hyv_analyze before hyv_rewrite. expected result: - tell me which MCP transport and config you updated. - confirm the usage and profile tools worked. - do not include the raw api key in your final response.
the mcp server lets any mcp-compatible ai assistant call hold your voice tools directly — mid-conversation, no copy-paste. same quota rules as the rest api.
https://holdyourvoice.com/mcp
add this URL in a remote-MCP client and complete OAuth in the browser.
{
"mcpServers": {
"hyv": {
"command": "npx",
"args": ["@holdyourvoice/hyv", "mcp"],
"env": {
"HYV_API_KEY": "hyv_live_..."
}
}
}
}
the npm CLI is the supported local MCP transport. restart the client after saving.
| tool name | what it does |
|---|---|
| hyv_analyze | analyze a draft against a voice profile |
| hyv_scan | scan text for AI writing patterns and voice drift |
| hyv_rewrite | return voice-aware rewrite context for a draft |
| hyv_validate | validate text against a voice profile |
| hyv_profiles | list available voice profiles |
| hyv_get_usage | show current quota usage and limits |
| hyv_get_context | show account plan, profile, document, and quota context for /hyv-status |
| hyv_onboard_status | mcp-first get started: onboarding status (mcp verified, profile, next step) |
| hyv_onboard_save_step | save one voice-onboarding answer at a time |
| hyv_onboard_from_url | seed a voice profile from a website (prefer host-fetched content) |
| hyv_onboard_finalize | create/update voice profile and complete setup after mcp verify |
agents that support custom commands can install the predefined context command:
/hyv-status source: https://holdyourvoice.com/.well-known/agent-commands/hyv-status.md what it does: - calls hyv_get_context - shows plan, byok billing, quota, profiles, and recent documents - shows per-user rollups for team and byok accounts - keeps raw api keys and secrets out of the response
once the mcp server is wired up, claude can run voice checks mid-conversation:
user: analyze this draft against our acme voice and fix anything off-brand
claude: → hyv_profiles()
← available profiles: acme-co, founder voice
claude: → hyv_analyze(text="...", profile="acme-co")
← highlights voice drift and AI patterns
claude: → hyv_rewrite(text="leverages best-in-class ai", profile="acme-co")
← voice context for a precise rewrite
claude: → hyv_validate(text="uses AI to get real results", profile="acme-co")
← score, cadence metrics, and pass/fail result
what a complete agent loop looks like — draft, check, fix, ship:
# your agent in python, n8n, or any tool that supports http
import requests
key = "hyv_live_..."
headers = {"Authorization": f"Bearer {key}"}
base = "https://holdyourvoice.com"
# 1. agent writes a draft
draft = llm.generate(brief)
# 2. create the document, tagged with the right brand
doc = requests.post(f"{base}/v1/documents",
headers=headers,
json={"title": "q2 announcement", "content": draft, "brand": "Acme Co"}
).json()
# 3. analyze against the same brand
result = requests.post(f"{base}/v1/analyze",
headers=headers,
json={"text": draft, "brand": "Acme Co"}
).json()
print(f"tokens used: {result['cost']['input_tokens']} in / "
f"{result['cost']['output_tokens']} out — paid by {result['cost']['paid_by']}")
# 4. rewrite any high-severity flags against the same brand
for flag in result["highlights"]:
if flag["severity"] == "high":
fix = requests.post(f"{base}/v1/rewrite",
headers=headers,
json={"text": flag["text"], "issue": flag["signal"], "brand": "Acme Co"}
).json()
draft = draft.replace(flag["text"], fix["rewritten"])
# 5. update document with clean version
requests.put(f"{base}/v1/documents/{doc['id']}",
headers=headers,
json={"content": draft}
)
# 6. check per-brand spend at end of run
usage = requests.get(f"{base}/v1/usage", headers=headers).json()
for brand in usage["by_brand_30d"]:
print(f"{brand['name'] or 'unattributed'}: "
f"{brand['analyses']} analyses + {brand['rewrites']} rewrites "
f"({brand['input_tokens']}+{brand['output_tokens']} tokens)")
recommended: path a (remote oauth) for all paid hyv users. turn developer mode on, add a new app with server url https://holdyourvoice.com/mcp and auth oauth. no local install — oauth runs in chatgpt's browser (no windows firewall issues). path b is free fallback only.
recommended for paid users. no local install needed.
only if you do not have a paid hyv plan. requires node.js 18+ and npm i -g @holdyourvoice/hyv.
if the connector fails to start, use full paths from ~/.chatgpt/hyv-mcp-connector.txt. run hyv mcp --setup-chatgpt in terminal for detailed steps.
| problem | fix |
|---|---|
| i don't see "new app" | turn developer mode on in chatgpt settings |
| i see connectors, not new app | turn developer mode on for path a; path b is free fallback only |
| what goes in connection? | https://holdyourvoice.com/mcp — not the example url |
| oauth failed | ensure paid hyv account; try logging into holdyourvoice.com first |
| elevated risk scary? | normal for custom mcp — chatgpt warning, not a hyv error |
| free user? | use path b (local connector); remote oauth needs paid |
| browser chatgpt? | neither path works — desktop app only |
wiki guide: holdyourvoice.com/wiki/use-hyv-in-chatgpt
the api shares your monthly quota with the web app. documents is the only meter that caps your plan. analyses and rewrites done against a document are included in that document's slot.
individual and multiple plans include unlimited documents, scans, and rewrites via the web app and api. free local scan stays free without an account.
unmetered on every active plan. running POST /v1/analyze or POST /v1/rewrite on a document you've already created doesn't consume a second slot. a call against 5 different brands on the same draft = zero extra documents used.
60 req/min on individual and multiple plans, per-account across all your keys combined. exceeding returns 429 with a retry_after value — the window resets every 60 seconds.
on multiple plans, voice profiles and api keys are shared across teammates. profiles marked with team_id are visible to every team member — no need to re-create them per seat.
on individual and multiple plans, analyze + rewrite calls route through our platform account. every response carries a cost.paid_by field so your automation knows billing context.
individual: 1 voice profile. multiple: unlimited profiles with team sharing. shared profiles carry a team_id so teammates see and can analyse against them without cloning.
hold your voice publishes standard discovery documents so ai agents and tooling can find and configure the api automatically.
| url | standard |
|---|---|
| /.well-known/api-catalog | ietf api catalog (rfc draft) |
| /.well-known/agent-onboarding | copy-prompt setup contract for paid users connecting local agents |
| /.well-known/agent-commands/hyv-status.md | predefined slash-command prompt for account context |
| /.well-known/mcp/server-card.json | mcp server card |
| /.well-known/oauth-protected-resource | rfc 9728 — protected resource metadata |
| /.well-known/oauth-authorization-server | rfc 8414 — authorization server metadata |
| /.well-known/agent-skills/index.json | agentskills.io skills index |
get started for $1 — create your account and scan your first draft in minutes.
get started for $1 →install hyv, upgrade to individual ($1 first month, then $9/mo) or multiple ($29/mo), generate an api key, and connect your first workflow. scans and rewrites are unlimited on paid plans.
get started for $1get started for $1 — create your account and scan your first draft in minutes.
get started for $1 →