Skip to main content

Simple API

The Simple API uses query parameters for authentication and simple request shapes. It is intended for environments where sending custom headers is inconvenient.

Plan requirement

Simple API access requires a Pro plan or higher.

Enable Simple API first

The Simple API is disabled by default for every device.

Before calling any Simple API endpoint, open Dashboard -> Devices -> select your device -> Device Settings and enable Simple API for that device.

The device token is sent in the URL, so it can appear in logs or monitoring tools. Enable it only when needed and prefer the RESTful API for server-side integrations.

Base URL

https://app.vwire.io/external/api

Authentication

Pass your device token as the token query parameter on every request. You can copy the token from Dashboard -> Devices -> select your device -> Device Settings -> Auth Token.

Device tokens are prefixed with iot_:

iot_**********

If the per-device toggle is off, the API returns:

{
"success": false,
"error": {
"code": "SIMPLE_API_DISABLED",
"message": "The Simple API is disabled for this device. Enable it in the VWire dashboard under Device Settings."
}
}

GET /get — Read a pin

GET /external/api/get?token=TOKEN&pin=V0
ParamRequiredDescription
tokenDevice auth token
pinPin name: V0-V255, D0-D255, A0-A255

Response:

{
"success": true,
"pin": "V0",
"value": "23.5",
"updatedAt": "2026-03-18T10:00:00.000Z"
}

value is null only when the pin exists but has no stored value yet. If the pin has never been recorded, the endpoint returns 404 PIN_NOT_FOUND.

Examples:

curl "https://app.vwire.io/external/api/get?token=iot_xxx&pin=V0"
import requests

r = requests.get(
"https://app.vwire.io/external/api/get",
params={"token": "iot_xxx", "pin": "V0"},
)
print(r.json()["value"])
HTTPClient http;
http.begin("https://app.vwire.io/external/api/get?token=iot_xxx&pin=V0");
int code = http.GET();
String body = http.getString();

GET /update — Write a pin

GET /external/api/update?token=TOKEN&pin=V0&value=1
ParamRequiredDescription
tokenDevice auth token
pinPin name
valueValue to set (see payload limits)

This stores the value, writes a history point, updates open dashboards in real time, and sends the command to the device immediately if it is online.

Response:

{
"success": true,
"pin": "V0",
"value": "1",
"delivered": true
}

delivered: true means the command was published to the online device immediately. false means the value was stored but could not be delivered right away.

Examples:

curl "https://app.vwire.io/external/api/update?token=iot_xxx&pin=V0&value=1"
import requests

r = requests.get(
"https://app.vwire.io/external/api/update",
params={"token": "iot_xxx", "pin": "V0", "value": "1"},
)
print(r.json()["delivered"])
String url = "https://app.vwire.io/external/api/update?token=iot_xxx&pin=V1&value=1";
http.begin(url);
http.GET();

GET /get-all — Read all pins

GET /external/api/get-all?token=TOKEN

Returns all recorded pin values for the device as a JSON object.

Response:

{
"success": true,
"deviceId": "uuid",
"pins": {
"V0": { "value": "23.5", "label": "Temperature", "updatedAt": "2026-03-18T10:00:00.000Z" },
"V1": { "value": "1", "label": "Relay", "updatedAt": "2026-03-18T09:55:00.000Z" },
"A0": { "value": "512", "label": null, "updatedAt": "2026-03-18T09:50:00.000Z" }
}
}
import requests

r = requests.get(
"https://app.vwire.io/external/api/get-all",
params={"token": "iot_xxx"},
)
pins = r.json()["pins"]
for pin, data in pins.items():
print(f"{pin} = {data['value']}")

GET /is-online — Check device status

GET /external/api/is-online?token=TOKEN

Response:

{
"success": true,
"deviceId": "uuid",
"isOnline": true,
"lastSeenAt": "2026-03-18T10:01:00.000Z",
"statusChangedAt": "2026-03-18T09:00:00.000Z"
}

POST /notify — Send a notification

POST /external/api/notify?token=TOKEN
Content-Type: application/json

Body:

{
"title": "Alert",
"message": "Temperature exceeded 30°C",
"priority": "high"
}
FieldTypeRequiredDefault
messagestring (max 500)
titlestring (max 100)"Device Notification"
prioritylow | normal | high"normal"

Response:

{
"success": true,
"notificationId": "uuid"
}
import requests

requests.post(
"https://app.vwire.io/external/api/notify",
params={"token": "iot_xxx"},
json={"title": "Alert", "message": "Temp > 30°C", "priority": "high"},
)

POST /batch-update — Write multiple pins

POST /external/api/batch-update?token=TOKEN
Content-Type: application/json

Body:

{
"pins": [
{ "pin": "V0", "value": "23.5" },
{ "pin": "V1", "value": "1" },
{ "pin": "A0", "value": "512" }
]
}

Max 50 pins per request. Locked pins are skipped.

Response:

{
"success": true,
"updated": 3,
"results": [
{ "pin": "V0", "delivered": true },
{ "pin": "V1", "delivered": true },
{ "pin": "A0", "delivered": false }
]
}
import requests

requests.post(
"https://app.vwire.io/external/api/batch-update",
params={"token": "iot_xxx"},
json={"pins": [{"pin": "V0", "value": "23.5"}, {"pin": "V1", "value": "1"}]},
)

Errors and rate limits

All errors follow this shape:

{
"success": false,
"error": {
"code": "INVALID_TOKEN",
"message": "Invalid device token."
}
}
HTTPCodeMeaning
400INVALID_PIN / VALUE_TOO_LARGERequest payload is invalid or exceeds pin size limit
401MISSING_TOKEN / INVALID_TOKENAuth failed
403SIMPLE_API_DISABLEDEnable Simple API in the device settings before using token-based calls
403PLAN_FEATURE_UNAVAILABLEPlan upgrade required
403PIN_LOCKEDPin is protected by a Keypad widget lock
404PIN_NOT_FOUNDPin has no recorded value
429RATE_LIMIT_EXCEEDEDToo many requests

Rate limit headers are included on every response:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1710756060
PlanRequests per minuteRequests per day
FreeNo access
Pro6010,000
Pro Plus300100,000
Enterprise1,000Unlimited