Skip to content
These docs are for Voice Monkey v3.

Announcement API

Play a text-to-speech announcement on a Speaker device, optionally combined with audio, video, images, on-screen text or a website.

GET/POST https://api-v3.voicemonkey.io/announce

POST is recommended for non-trivial requests (longer speech, JSON body, media URLs). GET is supported for quick browser tests and tools that can only build URLs.

Terminal window
curl -X POST https://api-v3.voicemonkey.io/announce \
-H "Content-Type: application/json" \
-d '{
"token": "YOUR_TOKEN",
"device": "YOUR_SPEAKER_DEVICE_ID",
"speech": "Dinner is ready!"
}'
Parameter Required Description
token yes Your API token. See Authentication.
device yes The ID of the Speaker device to announce on. List your devices with GET /devices. To announce on several Speakers at once, give up to 10 IDs separated by commas, or a JSON array.
speech yes* The text to speak via TTS. Required unless you’re playing media or showing on-screen text only. Supports placeholders.
voice no An Alexa voice ID (e.g. Joanna, Brian, Hans, Celine) or the ID of one of your own voices (e.g. butler-8k2p9). Leave blank for the user’s default. List every voice you can use with GET /voices.
language no BCP-47 language code passed to the Alexa TTS engine (e.g. en-US, de-DE, fr-FR).
chime no Soundbank URL of a built-in Alexa sound to play before the speech (e.g. soundbank://soundlibrary/alarms/air_horns/air_horn_01). The Playground has a dropdown of all supported chimes.
Parameter Required Description
audio no URL (or media://<slug> Media Library reference) of an audio file to play.
background_audio no Audio that plays underneath the speech rather than before/after it.
audio_tracks no Array of audio tracks for advanced sequencing. Easiest to build via the Playground.
image no URL (or Media Library reference) of an image to display on Echo Shows.
video no URL (or Media Library reference) of a video to play on Echo Shows.
video_repeat no How many times to loop the video. -1 for infinite, 0 (or blank) to play once. Looping isn’t guaranteed — actions on the Echo Show may interrupt the session.
website_url no URL of a website to load in the Echo Show’s on-device browser.

These map directly onto the APL Image component on screen-enabled Echos. Values include their unit suffix (e.g. 100%, 48dp, 10vw).

Parameter Description
media_scale none, fill, best-fill, best-fit, best-fit-down.
media_align top-left, top, top-right, left, center, right, bottom-left, bottom, bottom-right.
media_border_radius Border radius (e.g. 12dp).
media_width Width (e.g. 100%, 480dp).
media_height Height (e.g. 60vh, 200dp).

Big centered text shown full-screen on screen-enabled devices (Echo Show / Spot / Hub).

Parameter Description
text_display The text to display. Pair with the styling params below.
text_display_colour Hex font colour (e.g. #FFFFFF). Defaults to white.
text_display_bg_colour Hex background colour (e.g. #000000). Defaults to black.
text_display_size Font size in dp as a plain number (e.g. 40). Suggested: 24 (Small), 40 (Medium), 120 (Large), 200 (XL). Defaults to 40.
Parameter Description
screen The ID of a Screen you designed in the console, e.g. kitchen-board-x7k2p. Shown on Echo Show, Echo Spot and Fire TV. Its text can use the same placeholders as speech, so combine it with var-NAME parameters to change what it shows. A screen takes the place of image, video, text_display and website_url.

List your screen IDs with GET /screens.

Parameter Description
display_seconds How many seconds the visual stays on an Echo Show, Echo Spot or Fire TV before it goes back to its home screen, from 1 to 3600. Applies to whatever the announcement shows: an image, video, text display, Screen, or the Voice Monkey background shown while speech plays.

If you leave display_seconds out, the visual stays for its usual time: an hour for text_display, the Screen’s own Display for setting for screen, and the device’s own default for everything else. The value is a suggestion to the Echo. Touching the screen restarts the timer, and some devices may close it sooner. It doesn’t affect website_url, which opens in the Echo’s browser, or character_display.

Parameter Description
no_bg Set to true to stop the Voice Monkey logo appearing on an Echo Show, Echo Spot or Fire TV while the speech or audio plays. The sound is unchanged. An image, video, text_display, screen or website_url in the same request still shows; no_bg only replaces the logo.

no_bg has the same name as in v2, so v2 URLs that use no_bg=true keep working once you switch them to api-v3.

Parameter Description
character_display Text to show on the segmented character display of an Echo Dot with Clock.

You can combine any subset of these — e.g. send speech + image + text_display in one call to talk, show a picture and overlay big text. Omit speech entirely to make the screen the whole response.

Terminal window
curl -X POST https://api-v3.voicemonkey.io/announce \
-H "Content-Type: application/json" \
-d '{
"token": "YOUR_TOKEN",
"device": "YOUR_SPEAKER_DEVICE_ID",
"screen": "noticeboard-a1b2c",
"var-FRIDGE_NOTE": "Pizza night!"
}'
Terminal window
curl -X POST https://api-v3.voicemonkey.io/announce \
-H "Content-Type: application/json" \
-d '{
"token": "YOUR_TOKEN",
"device": "YOUR_SPEAKER_DEVICE_ID",
"text_display": "Dinner is ready!",
"text_display_colour": "#FFFFFF",
"text_display_bg_colour": "#DC2626",
"text_display_size": "64",
"display_seconds": 30
}'

This shows the text for 30 seconds instead of the default hour.

List up to 10 Speaker IDs in device to send the same announcement to all of them in one call:

Terminal window
curl "https://api-v3.voicemonkey.io/announce?token=YOUR_TOKEN&device=kitchen-echo-3f7k2,office-dot-8h2p1&speech=Dinner%20is%20ready"

In a JSON body you can also send an array:

{
"token": "YOUR_TOKEN",
"device": ["kitchen-echo-3f7k2", "office-dot-8h2p1"],
"speech": "Dinner is ready!"
}
  • Every Speaker gets the whole announcement: speech, media, Screen and the rest.
  • {VM.DEVICE.NAME} is filled in separately for each Speaker, so "Hello from the {VM.DEVICE.NAME}" names the right room on each. Random built-ins such as {VM.RANDOM.DICE} are rolled once, so every room hears the same value.
  • var- updates run once, before anything is sent.
  • Each Speaker counts as one request, both against your plan and against the safety throttle. If you always announce on the same group of Echos, a multi-room Speaker reaches all of them for one request.
  • Every ID is checked first. If one doesn’t exist, or a screen doesn’t, nothing is sent.

The response lists each Speaker:

{
"success": true,
"data": "OK",
"devices": [
{ "device": "kitchen-echo-3f7k2", "ok": true },
{ "device": "office-dot-8h2p1", "ok": true }
]
}

If some Speakers fail, data is PARTIAL and each failed entry has an error (the same codes as in Errors). If the safety throttle, the monthly quota or the Alexa skill link stops the first send, the rest aren’t tried, and the call fails as a single-device call would.

Every parameter except token and device can contain placeholders, including media URLs and the fields inside audio_tracks. Voice Monkey fills them in when the request arrives, before anything is sent to your Echo:

Placeholder Replaced with
{NAME} The current value of your variable NAME.
{NAME.field} A field inside a variable that holds JSON, e.g. {FORECAST.high} or {FORECAST.days[0].summary}.
{VM.…} A built-in variable, e.g. {VM.TIME.TEXT12}, {VM.DATE.WEEKDAY} or {VM.DEVICE.NAME} (the Speaker you’re announcing on).
{WEBHOOK.<slug>.<key>} A value from the latest payload received by an inbound webhook.
{
"token": "YOUR_TOKEN",
"device": "YOUR_SPEAKER_DEVICE_ID",
"speech": "Good morning {VM.USER.FIRST_NAME}, it's {VM.TIME.TEXT12} and the garage is {GARAGE_STATUS}.",
"audio": "{DOORBELL_SOUND}"
}

A variable can hold a media:// Media Library reference, as DOORBELL_SOUND does above.

  • Placeholders that don’t match anything are left as typed, so a typo is easy to spot.
  • Values are inserted once. A variable whose value contains {SOMETHING} isn’t expanded a second time.
  • {VM.FLOW.NAME}, {VM.FLOW.REF} and {VM.RUN.SCHEDULE} are empty outside a Flow, and {WEB_RESPONSE.…} only exists inside a Flow.

Successful calls return 200:

{
"success": true,
"data": "OK"
}

If any var- sidecar updates ran, the response also includes a variableUpdates array — see below.

When voice is one of your own voices, the response also says how the speech was made:

{
"success": true,
"data": "OK",
"voice": { "provider": "elevenlabs", "clips": 1, "cached": 0, "chars": 16 }
}

cached counts clips replayed from earlier announcements (no credits used). If the clip couldn’t be generated, fallback gives the reason (for example QUOTA_EXCEEDED) and the announcement plays in the voice’s Alexa fallback voice instead. It still counts as a successful request.

Any parameter prefixed with var- is upserted as a variable before the announcement runs, so the new value is available to {NAME} placeholders inside speech (and other text fields) in the same call:

Terminal window
curl -X POST https://api-v3.voicemonkey.io/announce \
-H "Content-Type: application/json" \
-d '{
"token": "YOUR_TOKEN",
"device": "YOUR_SPEAKER_DEVICE_ID",
"speech": "Hello {NAME}, the camera detected {STATUS}.",
"var-NAME": "Joe",
"var-STATUS": "motion"
}'

See Variables API → Setting variables alongside any other API call for the full rules.

Errors return a JSON body with an error field and an HTTP status code:

Status Response body Meaning
400 { "error": "MISSING_DEVICE" } No device parameter supplied.
400 { "error": "TOO_MANY_DEVICES", "max": 10 } device lists more than 10 Speakers.
404 { "error": "DEVICE_NOT_FOUND" } The device ID isn’t on this account. When device lists several, the body also names the one that wasn’t found: { "error": "DEVICE_NOT_FOUND", "device": "<id>" }.
404 { "error": "SCREEN_NOT_FOUND" } The screen ID isn’t on this account.
401 { "error": "UNAUTHORIZED" } No token supplied.
401 { "error": "INVALID_TOKEN" } Token doesn’t match an active token.
429 { "error": "THROTTLED", "lockoutUntil": "<ISO>" } Per-user safety lockout — back off until the timestamp.
429 { "error": "MONTHLY_QUOTA_EXCEEDED", "periodEnd": "<ISO>" } Plan’s monthly request budget exhausted. Wait for the period end or upgrade.
500 { "error": "ALEXA_TRIGGER_FAILED" } Generic upstream Alexa failure — retry with backoff.
  • Use placeholders inside speech, website_url and other fields to insert variables and built-ins like the current time.
  • For long-form TTS, break content into multiple sentences — Alexa handles shorter TTS much more reliably.
  • With Alexa voices, speech is passed to Alexa as SSML, so tags like <break time="1s"/>, <emphasis> and <say-as> work. With your own voices they’re removed before the text goes to ElevenLabs.
  • Use the Playground to compose requests visually — it has dropdowns for voices, languages and chimes, and generates ready-to-paste snippets in cURL, Python, JavaScript, Home Assistant YAML and more.