Normalize numbers, currency, phone numbers and units for text-to-speech

$0.005 USDC per call · Business, finance and compliance · POST /api/v1/speech-normalize · Id speech-normalize

Rewrites digits in up to 20000 characters of text into spoken words for a TTS engine, for locales en-US and en-GB: cardinals, ordinals, years (with a preceding cue such as "in" or a month) and decades, decimals, percentages, currency with ISO 4217 minor units ("$12.50" -> "twelve dollars and fifty cents"), phone numbers read digit by digit, and SI/common units with locale spelling (meter/metre). Other locales return unsupported. Dates, times, fractions, decimal-comma numbers, and currencies or units outside the built-in tables are left unchanged and reported as witnesses with status unknown; bare four-digit numbers are read as cardinals and flagged because year versus quantity is ambiguous. Deterministic; no language model.

What you get

A voice agent that reads "$1,234.50" or "+1 555-123-4567" wrongly loses customer trust; this makes the spoken form explicit and flags what it could not read.

Call it

Send the JSON body below to https://agents.writerslogic.com/api/v1/speech-normalize. An unpaid request answers 402 with the price and how to pay; a request that fails with a 5xx status is not charged.

curl -i -X POST https://agents.writerslogic.com/api/v1/speech-normalize \
  -H 'content-type: application/json' \
  -d '{"text":"Call +1 555-123-4567 before the 3rd: it costs $12.50 (15% off).","locale":"en-US"}'

Input

FieldTypeRequiredDescription
textstring; length 1..20000yes
localestring; length 0..16noBCP 47 tag. en-US (default) and en-GB are supported; anything else returns unsupported.

Example request body

{
  "text": "Call +1 555-123-4567 before the 3rd: it costs $12.50 (15% off).",
  "locale": "en-US"
}

Result

The response is { "data": ..., "_provenance": ... }. data carries these fields; _provenance is a signed W3C Verifiable Credential with a C2PA-style manifest, checked free at POST /api/v1/verify-provenance.

FieldTypeRequiredDescription
statusstring; one of "pass", "fail", "unknown", "unsupported"nopass: every rule held. fail: a rule was violated (see witnesses). unknown: the input lacks the evidence to decide. unsupported: outside what this engine covers. Missing evidence is never a pass.
localestringno
normalizedstringnoThe text with every resolved token replaced by its spoken form.
replacementCountintegerno
replacementsarray<object>noFirst 500 replacements in text order.
truncatedbooleanno
witnessesarray<object>no
versionsobjectnoEvery semantic dependency of this answer (engine, tables and their as-of dates, tokenizer, calendar, rounding profile).
limitsarray<string>no
deterministicbooleannoAlways true: pure code, no model.

Pay and connect

Available through: x402 (USDC on Base), MCP. MCP clients reach it through the identifier-text-kit package.

Machine-readable