Variables API
Read and write variables over HTTP. Use it to plug Voice Monkey into automations that need to share state — sensor readings, occupancy flags, counters, dynamic announcement text — between systems.
Endpoint
Section titled “Endpoint”GET/POST/PUT/DELETE https://api-v3.voicemonkey.io/variablesThe method picks the operation:
GET— read one, several, or all variables.POSTorPUT— upsert a variable by name (interchangeable).DELETE— remove a variable by name.
Reading variables
Section titled “Reading variables”One variable
Section titled “One variable”curl "https://api-v3.voicemonkey.io/variables?token=YOUR_TOKEN&variable=FIRST_NAME"{ "name": "FIRST_NAME", "value": "Joe" }Returns 404 with { "error": "VARIABLE_NOT_FOUND" } if the variable doesn’t exist.
Several variables in one call
Section titled “Several variables in one call”curl "https://api-v3.voicemonkey.io/variables?token=YOUR_TOKEN&variables=FIRST_NAME,CAMERA_STATUS"{ "FIRST_NAME": "Joe", "CAMERA_STATUS": "motion" }Variables that don’t exist come back as null rather than producing a 404, so a single call always returns the full requested map.
All variables
Section titled “All variables”curl "https://api-v3.voicemonkey.io/variables?token=YOUR_TOKEN"{ "variables": [ { "name": "FIRST_NAME", "value": "Joe" }, { "name": "CAMERA_STATUS", "value": "motion" }] }Creating or updating a variable
Section titled “Creating or updating a variable”POST and PUT behave identically — both upsert the variable by name. Use whichever fits your tooling.
curl -X PUT https://api-v3.voicemonkey.io/variables \ -H "Content-Type: application/json" \ -d '{ "token": "YOUR_TOKEN", "variable": "CAMERA_STATUS", "value": "motion" }'{ "name": "CAMERA_STATUS", "value": "motion", "created": false }Returns 201 (with created: true) the first time a variable is created, then 200 (with created: false) on every subsequent update.
Deleting a variable
Section titled “Deleting a variable”curl -X DELETE https://api-v3.voicemonkey.io/variables \ -H "Content-Type: application/json" \ -d '{ "token": "YOUR_TOKEN", "variable": "CAMERA_STATUS" }'{ "success": true, "name": "CAMERA_STATUS" }Setting variables alongside any other API call
Section titled “Setting variables alongside any other API call”Every public endpoint (/announce, /trigger, /flow, /variables) accepts a var-<NAME> parameter shorthand. Any parameter whose name starts with var- is upserted as a variable before the main action runs, so the new value is visible to placeholders, conditions and webhook chains in the same 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": "Hello {NAME}, you have {UNREAD} unread messages.", "var-NAME": "Joe", "var-UNREAD": "3" }'{NAME} and {UNREAD} are resolved against the values you just sent — no extra round-trip needed.
The same shorthand works on the query string for GET-style calls:
curl "https://api-v3.voicemonkey.io/trigger?token=YOUR_TOKEN&device=DEV&var-CAMERA_STATUS=motion"When one or more var- updates are applied the response includes a variableUpdates summary so you can verify what landed. For example, calling /announce with two var- params returns:
{ "success": true, "data": "OK", "variableUpdates": [ { "name": "NAME", "created": false, "updated": true }, { "name": "UNREAD", "created": true, "updated": false } ]}Each entry has one of three shapes:
{ name, created: true, updated: false }— brand-new variable.{ name, created: false, updated: true }— existing variable’s value was overwritten.{ name, error: "RESERVED_NAME" | "UPSERT_FAILED" | … }— the update was skipped. Reserved names (built-in placeholders likeWEBHOOK) are surfaced this way so you can see why the update didn’t apply, without failing the primary action.
If you call POST/PUT /variables with only var-… shorthand parameters and no variable field, the response is { "success": true, "variableUpdates": [...] } instead of the usual MISSING_VARIABLE error — the request is treated as a pure batch upsert.
Rules for var- parameters
Section titled “Rules for var- parameters”- Names are normalised to upper-case (
var-nameandvar-NAMEboth targetNAME). - Names must match
[A-Z][A-Z0-9_]*— anything else (e.g.var-1bad,var-foo!) is silently dropped. - Reserved names (
WEBHOOK,WEB_RESPONSE) are rejected and reported via thevariableUpdatesarray aserror: "RESERVED_NAME". - Object/array values are JSON-stringified, so structured payloads survive intact:
"var-PAYLOAD": { "temp": 72 }stores{"temp":72}. Reference fields with the dotted-path syntax inside Flow nodes —{PAYLOAD.temp}. - Plan limits only apply when creating a new variable. Updates to existing variables always succeed, even after a plan downgrade.
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_VARIABLE" } | No variable provided on a write/delete (and no var-… sidecars to fall back on). |
400 | { "error": "MISSING_VALUE" } | No value provided on a write. |
400 | { "error": "INVALID_VARIABLE_NAME" } | Name doesn’t match [A-Z][A-Z0-9_]*. |
400 | { "error": "RESERVED_VARIABLE_NAME", "message": "<details>" } | Name collides with a built-in placeholder (WEBHOOK, WEB_RESPONSE). |
401 | { "error": "UNAUTHORIZED" } | No token supplied. |
401 | { "error": "INVALID_TOKEN" } | Token doesn’t match an active token. |
403 | { "error": "Variable limit reached for your plan", "upgrade": true } | Plan cap hit on a brand-new variable; existing ones can still be updated. |
404 | { "error": "VARIABLE_NOT_FOUND" } | Read or delete of a name that doesn’t exist. |
429 | { "error": "THROTTLED", "lockoutUntil": "<ISO>" } | Per-user safety lockout — back off until the timestamp. |
500 | { "error": "Failed to upsert variable" } | Generic upstream failure on a write — retry with backoff. |