Announcement API
Play a text-to-speech announcement on a Speaker device, optionally combined with audio, video, images, on-screen text or a website.
Endpoint
Section titled “Endpoint”GET/POST https://api-v3.voicemonkey.io/announcePOST 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.
Example request
Section titled “Example request”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!" }'Parameters
Section titled “Parameters”| 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. |
Advanced image display
Section titled “Advanced image display”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). |
Full-screen text display
Section titled “Full-screen text display”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. |
Screens
Section titled “Screens”| 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.
How long it stays on screen
Section titled “How long it stays on screen”| 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.
Hiding the Voice Monkey logo
Section titled “Hiding the Voice Monkey logo”| 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.
Screen example
Section titled “Screen example”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!" }'Text display example
Section titled “Text display example”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.
Several Speakers at once
Section titled “Several Speakers at once”List up to 10 Speaker IDs in device to send the same announcement to all of them in one call:
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
screendoesn’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.
Placeholders
Section titled “Placeholders”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.
Response
Section titled “Response”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.
Setting variables in the same request
Section titled “Setting variables in the same 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:
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
Section titled “Errors”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_urland 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,
speechis 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.
