Voice Monitor API: watch published pages for voice drift
By Jack Stovell X · Instagram · LinkedIn · published 2026-10-29
The Voice Monitor API scores the pages where a voice is published against its profile every month. Drift gets caught on the live site, not in review. You call it with an sg_live_ key, from the REST API or the MCP server, and it works for anyone who owns or looks after published copy.
At a glance
What it does: Scores the pages where a voice is published against its profile every month and flags the ones that drifted.
| Endpoints | `GET /v1/profiles/{id}/monitor`, `POST .../monitor/urls`, `DELETE .../monitor/urls/{urlId}`, `POST .../monitor/run` |
| MCP tools | `get_voice_monitor`, `add_monitor_url`, `remove_monitor_url`, `run_voice_monitor` |
| Cost | No generation credit |
| Plans | Pages per profile: Writer 5, Operator 5, Studio 15, Agency 50. Free: 0 |
| Schedule | Automatically on the 1st of each month at 09:00 UTC, or once a month on demand |
What a monthly run does
A run has four jobs. Fetch, score, skip what hasn't changed, and report what broke.
First, add_monitor_url tells the monitor which public http(s) page to watch for a profile. Private or internal hosts are refused. Then a cron runs on the 1st of each month at 09:00 UTC. Or you call run_voice_monitor yourself.
Each run fetches every watched page, directly first, with a Firecrawl fallback. It reads up to 3,500 words, scores that text against the profile and records one run. Every page gets a score, a band, top_differences and top_matches. So you see where the copy drifted, and which habits still hold.
Unchanged pages are cheap. If the content hasn't moved, the page reuses its score, flagged unchanged, with no new model call.
Failures stay local. A page that can't be fetched, or has under 120 readable words, comes back fetched_ok false with an error. The run carries on.
Allowances and limits
Monitor pages are allowed per profile, and the allowance follows the plan:
- Free: 0
- Writer: 5
- Operator: 5
- Studio: 15
- Agency: 50
That's pages per profile, so a Studio account with several profiles gets 15 on each. Free has none.
The run limit is once per profile per calendar month, counted in UTC. The cron run counts. If you trigger run_voice_monitor on the 1st after the cron has fired, you've already used the month. A failed run doesn't use it, though, so you can try again.
Runs carry no generation credit. They do count against the account's monthly AI usage ceiling. Everything else is the usual API arrangement: 60 requests a minute per key, and the REST API and MCP server (https://mcp.scriptgrain.com/mcp) are on every plan, Free included. Payments never happen through the API.
To read results, get_voice_monitor returns the pages, the allowance, the last 12 runs and the two latest completed runs for comparison. remove_monitor_url stops watching a page. Past results stay.
When to use it
Three situations come up again and again.
An agency watching client sites. You wrote the voice guide, the client's team has been publishing since, and nobody has measured the gap. A monthly score per page tells you which sections slipped before the client notices. The agency page covers that workflow in more detail.
A brand after a redesign or new hires. Both change who writes and where the words sit. Redesigns rewrite templates and headings; new hires bring their own habits. Watch the pages that matter and let the bands show whether the voice survived.
Pairing with Brand Mimic. Brand Mimic builds the profile from the site; the monitor then shows which pages wander from it. For a one-off comparison of two texts rather than a monthly watch, voice compare is the better fit. And if you want a quick manual check first, the brand voice consistency checker does that without any setup.
Request and response
Watch a page, then read the state (from the OpenAPI spec's examples; the result is cut to one page).
curl -X POST https://auth.scriptgrain.com/functions/v1/api-v1/v1/profiles/{id}/monitor/urls \
-H "Authorization: Bearer sg_live_..." \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/about", "label": "About page"}'
# then read the monitor's state
curl https://auth.scriptgrain.com/functions/v1/api-v1/v1/profiles/{id}/monitor -H "Authorization: Bearer sg_live_..."
{
"plan": "writer",
"allowance": 5,
"latest": {
"run": {
"period_key": "2026-10",
"trigger": "manual",
"status": "complete",
"urls_total": 1,
"on_voice": 0,
"drifting": 1,
"off_voice": 0,
"avg_score": 0.68
},
"results": [
{
"url": "https://example.com/about",
"score": 0.68,
"band": "drifting",
"top_differences": [
{
"feature": "sentence_length",
"label": "Sentence length",
"detail": "this page averages 27 words a sentence vs your profile's 14",
"similarity": 0.31
}
],
"unchanged": false,
"fetched_ok": true
}
]
},
"can_run_now": false,
"next_cron_run": "2026-11-01T09:00:00Z"
}
In Claude, ChatGPT or Cursor
Over MCP this is the tools `add_monitor_url`, `run_voice_monitor`, `get_voice_monitor` and `remove_monitor_url`. Connect `https://mcp.scriptgrain.com/mcp` once (a custom connector in claude.ai, developer mode in ChatGPT on the web, the MCP settings in Cursor, or `claude mcp add` in Claude Code), then ask in plain words:
Watch our about, pricing and careers pages against the brand voice in ScriptGrain, run this month's check and tell me which page drifted most.
Get a key
API and MCP access is on every plan, Free included. Create a free account (no card), then mint a key at Settings, then API: it starts `sg_live_`, is shown once, and goes in an `Authorization: Bearer` header. Every request, field and error code is in the OpenAPI spec.
Questions
How often does the Voice Monitor run?
Once a month on a schedule. The cron fires on the 1st at 09:00 UTC. You can also call run_voice_monitor on demand, but only once per profile per calendar month (UTC), and the cron run counts toward that. A failed run doesn't use up the month, so a retry is allowed.
How many pages can I watch?
It depends on your plan, and the allowance is per profile: Free 0, Writer 5, Operator 5, Studio 15, Agency 50. Each page you add with add_monitor_url uses one slot. Calling remove_monitor_url stops watching a page, and past results for it stay on record.
What happens if a page can't be fetched?
The run doesn't fail. A page that can't be fetched, or has under 120 readable words, comes back with fetched_ok false and an error message. The other pages are still scored, and the run is recorded. The monitor tries a direct fetch first, then falls back to Firecrawl.
Does the monitor cost credits?
No generation credit is used. API calls draw on the same credits as the app, with no separate API quota, but a monitor run carries no generation charge. It does count against the account's monthly AI usage ceiling. Unchanged pages reuse their earlier score, so they trigger no new model call.