Connect with MCP
For assistants that support local MCP servers. Requires Node.js 20 or newer.
npx -y @unlimitedtts/mcp@0.1.0
Give your AI assistant a voice. Connect a tool below, then ask it to turn text into an audio file.
Copy this into an assistant with web or HTTP tools. Replace the final sentence with your text.
The MCP server and OpenClaw plugin use an external wallet signer. Connect a compatible EVM wallet through your assistant’s wallet tool, fund it with USDC (six-decimal atomic units) on Base mainnet (eip155:8453), and set a per-request and daily spending budget in the integration configuration. The wallet tool signs the quoted payment; UnlimitedTTS does not ask for your private key or seed phrase.
Check the live payment challenge for the required asset and network before funding. Never send funds to an address copied from an unverified prompt. Start with a quote and approve the first payment.
Prefer a card? Ask an HTTP-capable assistant to follow the card-credit flow in the live agent guide. Card funding starts at $5. The published MCP and OpenClaw integrations currently use x402.
https://api.unlimitedtts.com is a paid text-to-speech API for AI agents and automated systems. It offers 3 independent payment flows, all priced from the same per-character rate: pay each request directly in USDC over x402 with no account, prepay a USDC balance and authorize each request with a signature, or fund prepaid card credits through Stripe Checkout.
This page is generated from the API's own contract. Read the canonical OpenAPI document, the agent guide, and the voice list at integration time — they are authoritative, and a client should read them rather than hardcode anything below.
| Flow | Endpoints | Identity | Minimum |
|---|---|---|---|
| Card credits | GET /ttsPOST /ttsGET/POST /top-upGET /credits/:accountId |
x-credit-account bearer token | 500 cents per top-up; request debits can be sub-cent. |
| Direct x402 | GET /x402/ttsPOST /x402/tts |
No API account or prepaid balance; the payment credential authorizes the request. | No application minimum and no top-up. The only lower bound is one atomic USDC unit (0.000001 USDC). |
| Prepaid x402 | POST /x402/depositGET /x402/accounts/:addressGET /x402/ttsPOST /x402/tts |
The payer's public EVM address. This is not a bearer token: spending requires an EIP-712 signature from that address on every request. | — |
Pick one flow per request and do not mix them. /x402/tts never
accepts x-credit-account, and /tts never reads x402 payment headers.
Stripe funds card credits only; it is not an x402 top-up.
GET https://api.unlimitedtts.com/openapi.json for the current contract.GET /.well-known/x402-service-metadata against a public key you pinned
out of band. Never bootstrap trust from the challenge itself.GET /tts/models and a voice from GET /tts/voices.POST /x402/tts with no payment header.402, Base64-decode PAYMENT-REQUIRED and select a compatible
entry from accepts.@x402/fetch, or sign the x402 v2 payload yourself.PAYMENT-SIGNATURE.200 audio/mpeg and keep PAYMENT-RESPONSE as the settlement
receipt.Production settles the exact EVM scheme in
USDC (six-decimal atomic units) on Base mainnet
(eip155:8453) through
https://facilitator.payai.network. Treat the challenge as the authority for
network, asset, recipient, amount, and timeout; never hardcode the receiving address.
Every paid PaymentPayload must carry the official x402 Payment Identifier
extension. It is the idempotency key: persist the identifier alongside the exact request, the
audio, and the receipt. If a response is lost in transit, replaying the identical paid request
within 24 hours returns the original audio and receipt with no second
charge and no second synthesis.
PAYMENT_OUTCOME_UNKNOWN is the one exception: it is not
retryable. An agent must not construct and pay a replacement request without explicit human
approval.
A manual client Base64-encodes this JSON into PAYMENT-SIGNATURE:
{
"x402Version": 2,
"accepted": {
"...": "the complete selected PAYMENT-REQUIRED.accepts entry, copied unmodified"
},
"payload": {
"signature": "0x...",
"authorization": {
"...": "scheme-specific exact-EVM authorization"
}
},
"extensions": {
"payment-identifier": { "id": "your-stable-16-to-128-char-id" }
}
}
accepted and the Payment Identifier extension are both required. Top-level
scheme and network fields are the legacy v1 shape and are not
substitutes for accepted. A malformed or legacy envelope returns
400 INVALID_PAYMENT_PAYLOAD before any verification or synthesis.
The direct flow sends your text in the unpaid request. If an agent must not disclose text
before payment, quote by hash instead: POST /x402/tts/quote takes only the character
length and a SHA-256 digest, and returns a signed quoteToken. Send
{quoteToken} alone to get the challenge, then {quoteToken, text} with
the payment.
A quote is a price, not a ticket: read expiresAt from the response rather than
assuming a fixed lifetime, and note that within that lifetime the same token can be spent more
than once — each spend is charged. Payment is what is consumed, not the token. The
length-and-digest binding is enforced at synthesis, where a mismatch returns
400 QUOTE_BODY_MISMATCH and charges nothing.
Deposit once with POST /x402/deposit using the ordinary x402 challenge and paid
retry. The balance is credited to the paying EVM address after the transfer reaches the required
confirmation depth on Base mainnet. Afterwards, /x402/tts requests skip the
facilitator entirely.
The balance is not a bearer token. Spending requires an EIP-712
PrepaidRequest signature from the owning address on every request,
binding the method, path, body hash, maximum amount, nonce, and expiry. EOA signers only —
EIP-1271 smart-account signatures are rejected, matching the exact scheme's EIP-3009
requirement.
GET /tts/models and GET /tts/voices.POST /tts, or the GET /tts fallback.402 carrying a topUpUrl.topUpUrl, complete Stripe Checkout, and save the returned
x-credit-account value./tts with the x-credit-account header. Only the exact
synthesis price is debited./tts/jobs/:jobId and download from the returned link.GET /credits/:accountId.An individual debit can be far below one cent; the $5 minimum applies only to a funding transaction. Failed card-credit requests restore the exact debit to the balance. On Stripe Checkout, confirm the country selector matches the card's billing country — proxy geolocation often picks the wrong default.
| Model id | Name | Max characters | Price per character | Available |
|---|---|---|---|---|
openai/tts-1 |
OpenAI TTS-1 | 4096 | $0.000018 | Yes |
openai/tts-1-hd |
OpenAI TTS-1 HD | 4096 | $0.000036 | Yes |
openai_alloy, openai_ash, openai_coral, openai_echo, openai_fable, openai_onyx, openai_nova, openai_sage, openai_shimmer
The default voice for openai/tts-1 is
openai_alloy. Read
GET /tts/voices?model=… for the current list per model.
Service metadata.
| Method | Path | Summary |
|---|---|---|
| GET | / | Get service health and endpoint links. |
Wallet-authenticated integration feedback.
| Method | Path | Summary |
|---|---|---|
| POST | /feedback/challenge | Create a short-lived wallet-signing challenge for feedback. |
| POST | /feedback | Submit wallet-signed feedback about an agent integration. |
Machine-readable documentation endpoints.
| Method | Path | Summary |
|---|---|---|
| GET | /docs | Get the legacy machine-readable payment and agent guide. |
| GET | /.well-known/x402-service-metadata | Get signed x402 network, asset, payee, pricing, and rotation metadata. |
| GET | /openapi.json | Get the canonical OpenAPI 3.0.3 contract. |
Text-to-speech operations.
| Method | Path | Summary |
|---|---|---|
| GET | /tts/voices | List supported public voice ids and current pricing. |
| GET | /tts/models | List selectable TTS models, limits, voices, and current pricing. |
| POST | /tts | Synthesize speech using prepaid card credits. |
| GET | /tts | Synthesize speech using a GET fallback and prepaid card credits. |
| POST | /x402/tts/quote | Create a hash-bound x402 TTS quote without disclosing text. |
| POST | /x402/tts | Synthesize speech using an exact per-request x402 USDC payment. |
| GET | /x402/tts | Synthesize speech using a GET fallback and x402 USDC payment. |
Asynchronous TTS job polling and audio retrieval.
| Method | Path | Summary |
|---|---|---|
| GET | /tts/jobs/{jobId} | Get an asynchronous TTS job. |
| GET | /tts/jobs/{jobId}/audio | Download audio for a completed asynchronous TTS job. |
Prepaid Stripe-funded credit accounts.
| Method | Path | Summary |
|---|---|---|
| GET | /top-up | Open the Stripe Checkout top-up launcher. |
| POST | /top-up | Create a Stripe Checkout Session. |
| GET | /top-up/complete | Verify a returned Stripe Checkout Session and credit the account. |
| GET | /top-up/status | Check whether a credit account is active after Checkout. |
| GET | /credits/{accountId} | Get the balance of a prepaid credit account. |
Signature-authenticated prepaid USDC balances that remove facilitator and settlement latency from each request.
| Method | Path | Summary |
|---|---|---|
| POST | /x402/deposit | Fund a prepaid x402 balance with one confirmed USDC payment. |
| GET | /x402/accounts/{address} | Get a prepaid x402 balance. |
Voice ids always use the provider_voice form; bare upstream names like
nova are rejected.
POST https://api.unlimitedtts.com/x402/tts
Content-Type: application/json
{
"text": "Hello from an AI agent",
"model": "openai/tts-1",
"voice": "openai_alloy",
"speed": 1
}
POST https://api.unlimitedtts.com/x402/tts
Content-Type: application/json
PAYMENT-SIGNATURE: <base64-x402-v2-payment-payload>
{
"text": "Hello from an AI agent",
"model": "openai/tts-1",
"voice": "openai_alloy",
"speed": 1
}
GET https://api.unlimitedtts.com/x402/tts?text=Hello%20world&voice=openai_alloy
GET https://api.unlimitedtts.com/x402/tts?text=Hello%20world&voice=openai_alloy
PAYMENT-SIGNATURE: <base64-x402-v2-payment-payload>
POST https://api.unlimitedtts.com/x402/tts/quote
Content-Type: application/json
{
"textLength": 11,
"textSha256": "<lowercase-sha256-hex-of-trimmed-utf8-text>",
"model": "openai/tts-1",
"voice": "openai_alloy"
}
POST https://api.unlimitedtts.com/x402/tts
Content-Type: application/json
x-x402-account: <your-evm-address>
x-x402-nonce: <unique-per-request>
x-x402-expiry: <unix-seconds>
x-x402-max-amount: <micro-usd-ceiling>
x-x402-signature: <eip-712-signature>
{
"text": "Hello world",
"voice": "openai_alloy"
}
POST https://api.unlimitedtts.com/tts
Content-Type: application/json
x-credit-account: <your-account-uuid>
{
"text": "Hello world",
"model": "openai/tts-1",
"voice": "openai_alloy",
"speed": 1
}
POST https://api.unlimitedtts.com/tts?async=true&storeAudio=false
Content-Type: application/json
x-credit-account: <your-account-uuid>
{
"text": "Hello world",
"voice": "openai_alloy"
}
?async=true; idempotency-key up to
512 characters.Retry-After, X-RateLimit-Limit, X-RateLimit-Policy, X-RateLimit-Remaining, X-RateLimit-Reset, X-RateLimit-Scope.These values change. Read GET /openapi.json and GET /tts/models
rather than hardcoding them in a client.
Errors return a structured body with a stable code. The full set:
CONFIG_ERROR, INVALID_JSON, INVALID_REQUEST, UNKNOWN_TTS_MODEL, INVALID_VOICE, INVALID_SPEED, TEXT_TOO_LONG, TTS_PROVIDER_NOT_CONFIGURED, INVALID_PAYMENT_PAYLOAD, INVALID_QUOTE, QUOTE_EXPIRED, QUOTE_BODY_MISMATCH, UNSUPPORTED_CONTENT_TYPE, PAYMENT_REQUIRED, PAYMENT_ERROR, PAYMENT_IDENTIFIER_CONFLICT, PAYMENT_REPLAY_PENDING, PAYMENT_OUTCOME_UNKNOWN, REPLAY_CACHE_UNAVAILABLE, RATE_LIMITED, FEEDBACK_CHALLENGE_INVALID, FEEDBACK_CHALLENGE_EXPIRED, FEEDBACK_PAYLOAD_MISMATCH, FEEDBACK_SIGNATURE_INVALID, FEEDBACK_CHALLENGE_REPLAYED, FEEDBACK_RATE_LIMITED, REQUEST_TOO_LARGE, NOT_FOUND, UNAUTHORIZED, JOB_NOT_READY, AUDIO_NOT_STORED, TTS_UPSTREAM_ERROR, TTS_UNAVAILABLE, INTERNAL_ERROR
storeAudio=false to opt out; a completed no-store job has no downloadable link.Yes. The direct x402 flow pays each /x402/tts request in USDC with no API account, bearer token, checkout, prepaid balance, or top-up.
Production uses USDC on Base mainnet (eip155:8453) with the x402 v2 exact EVM scheme. Always treat the PAYMENT-REQUIRED challenge as authoritative for the network, asset, recipient, amount, and timeout, and verify the signed service metadata against a pinned key before trusting a payee.
No. The API requires no Coinbase, CDP, or facilitator account. A buyer needs a compatible Base wallet holding USDC and an x402 v2 exact-EVM signer.
Yes. @x402/fetch is an optional JavaScript convenience. Any client can implement the raw HTTP flow: read PAYMENT-REQUIRED, sign the selected challenge entry, and retry with a valid x402 v2 PaymentPayload carrying the required Payment Identifier extension in PAYMENT-SIGNATURE.
No. Retry the identical method and URL. A GET challenge is paid with a second GET carrying PAYMENT-SIGNATURE; it never changes to POST.
Replay the identical paid request with the same Payment Identifier within 24 hours. The API returns the original audio and settlement receipt without verifying, synthesizing, or charging again. Do not automatically retry PAYMENT_OUTCOME_UNKNOWN — that one requires explicit approval.
Every flow uses the same USD per-character rate for the selected model, rounded up to the nearest micro-dollar. openai/tts-1 is $0.000018 per character. The $5 minimum applies only to a card funding transaction, never to x402 or to an individual synthesis.
Direct and prepaid x402 responses are synchronous and do not enter the async storage workflow. Card-credit async audio is retained temporarily by default; storeAudio=false disables that retention.