Overview
Mango by Radix IoT provides a comprehensive REST API that lets you interact with the system programmatically. Use it to build custom integrations, automate tasks, pull data into external systems, or build custom UIs.
API Documentation
Mango serves its whole REST API under one servlet path, /rest/latest, set by spring.mvc.servlet.path in mango.properties. The OpenAPI documentation is served under that same path, not at the web root:
- The machine-readable OpenAPI definition is at
http://your-mango:8080/rest/latest/api-docs(configured explicitly asspringdoc.api-docs.path=/api-docs) - The Swagger UI is served under the same
/rest/latestprefix – browse endpoints, parameters and response formats there - Try endpoints directly from the Swagger interface
Note
Older Mango documentation describes a swagger.enabled property and a /rest/{version}/swagger/v2/api-docs path. Those belong to the previous Springfox setup. Mango 5.7.4 uses springdoc, and neither the property nor that path exists.
Authentication
Method 1: Token-Based Authentication (Recommended)
A token does not come from the login endpoint. POST /rest/latest/login authenticates you and returns your user object, establishing a session – there is no token in that response. JWTs are minted by a different endpoint:
curl -X POST http://localhost:8080/rest/latest/auth-tokens/create \
-u admin:admin \
-H "Content-Type: application/json" \
-d '{"username": "admin", "expiry": "2026-12-31T00:00:00.000Z"}'
It answers 201 Created, not 200, and the body holds the token:
{
"token": "eyJhbGciOiJFUzI1NiJ9..."
}
Omit username to mint a token for yourself. Omit expiry and you get Mango’s REST-only default, which is five minutes – long enough to look like a bug rather than a setting.
Use the token in subsequent requests:
curl http://localhost:8080/rest/latest/data-points \
-H "Authorization: Bearer eyJhbGciOiJFUzI1NiJ9..."
Note
Anyone who authenticates with a password – basic auth as above, or a session login – can create a token, but only for themselves unless they are a superadmin. authentication.mango-jwt.allowTokenCreation (default false) does not turn token creation off: it only decides whether a caller who is authenticated by a Mango JWT may mint another one.
Method 2: Basic Authentication
For simple scripts, use HTTP Basic Auth. It is enabled by default (authentication.basic.enabled=true, realm Mango):
curl -u admin:admin http://localhost:8080/rest/latest/data-points
Method 3: Session Cookie
POST /rest/latest/login sets a session cookie, so any HTTP client that keeps cookies stays authenticated afterwards without a token. The cookie name defaults to the Mango instance GUID (sessionCookie.useGuid=true). A session login needs an XSRF token. Send an XSRF-TOKEN cookie with the login and the same value in an X-XSRF-TOKEN header, or Mango refuses the login with 403. Login then issues a new XSRF-TOKEN cookie, and every later POST, PUT, PATCH or DELETE on that session must send the new value in the header. A request that carries an Authorization header – basic auth or a token – needs none of this, which is why the Python example below uses basic auth.
Warning
Basic auth sends credentials with every request. Use token-based auth for production integrations and always use HTTPS.
Common API Endpoints
Read a Data Point’s Current Value
# By XID
curl http://localhost:8080/rest/latest/point-values/latest/DP_TEMP_001 \
-H "Authorization: Bearer YOUR_TOKEN"
The response is an array, in time-descending order, and by default each entry carries only timestamp and value:
[
{ "timestamp": 1707400000000, "value": 72.5 }
]
Ask for more with the fields parameter, which accepts VALUE, TIMESTAMP, ANNOTATION, CACHED, BOOKEND, RENDERED, RAW, XID, NAME, DEVICE_NAME and DATA_SOURCE_NAME:
curl "http://localhost:8080/rest/latest/point-values/latest/DP_TEMP_001?fields=XID,TIMESTAMP,VALUE,ANNOTATION&limit=1" \
-H "Authorization: Bearer YOUR_TOKEN"
Query Historical Data
The history path is /point-values/time-period/{xid}. A plain /point-values/{xid} has no GET at all – that path exists only for PUT and DELETE, so a GET against it returns 405, not data.
# Get values for a time range
curl "http://localhost:8080/rest/latest/point-values/time-period/DP_TEMP_001?from=2024-01-01T00:00:00Z&to=2024-01-02T00:00:00Z&limit=1000" \
-H "Authorization: Bearer YOUR_TOKEN"
From is inclusive, to is exclusive. Both are optional here; omit them and you get everything. Useful extras: bookend=true adds a value at each end of the range, timezone, and dateTimeFormat to get string timestamps instead of epoch milliseconds.
Rolled-Up Historical Data
To aggregate, add the rollup as a path segment – it is not a query parameter:
curl "http://localhost:8080/rest/latest/point-values/time-period/DP_TEMP_001/AVERAGE?from=2024-01-01T00:00:00Z&to=2024-01-02T00:00:00Z&timePeriodType=HOURS&timePeriods=1" \
-H "Authorization: Bearer YOUR_TOKEN"
On this variant from and to are required, and timePeriodType with timePeriods set the bucket size.
Set a Data Point Value
curl -X PUT http://localhost:8080/rest/latest/point-values/DP_SETPOINT_001 \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"dataType": "NUMERIC", "value": 75.0}'
dataType must be one of BINARY, MULTISTATE, NUMERIC or ALPHANUMERIC. The body also accepts timestamp and annotation.
List All Data Sources
curl http://localhost:8080/rest/latest/data-sources \
-H "Authorization: Bearer YOUR_TOKEN"
Get System Events
curl "http://localhost:8080/rest/latest/events?alarmLevel=URGENT&active=true" \
-H "Authorization: Bearer YOUR_TOKEN"
Example: Python Integration
import requests
MANGO_URL = "http://localhost:8080"
USERNAME = "admin"
PASSWORD = "admin"
# Authenticate with basic auth: requests sends the credentials with every
# call, and a request with an Authorization header needs no XSRF token.
# (A plain POST to /rest/latest/login without one is refused with 403.)
session = requests.Session()
session.auth = (USERNAME, PASSWORD)
# To use a JWT instead, POST to /rest/latest/auth-tokens/create (basic auth
# works there too), read response.json()["token"] from the 201 response, and
# set session.headers["Authorization"] = f"Bearer {token}" in place of session.auth.
headers = {}
# Get current value of a data point
response = session.get(
f"{MANGO_URL}/rest/latest/point-values/latest/DP_TEMP_001",
headers=headers
)
# /point-values/latest/{xid} returns a LIST, newest first -- index it
print(f"Current temperature: {response.json()[0]['value']}")
# Get historical data -- note the time-period path
response = session.get(
f"{MANGO_URL}/rest/latest/point-values/time-period/DP_TEMP_001",
headers=headers,
params={
"from": "2024-01-01T00:00:00Z",
"to": "2024-01-02T00:00:00Z",
"limit": 100
}
)
for point in response.json():
print(f" {point['timestamp']}: {point['value']}")
Discovering RQL Queries
Tip
You can reverse-engineer the exact RQL query Mango uses for any filtered view. Open your browser dev tools (F12), go to the Network tab, then apply a filter on a watchlist or data point table in Mango. Inspect the XHR request URL to see the RQL query string Mango generated. Copy that query and use it directly in your own API calls.
Rate Limiting and Best Practices
- Don’t poll too frequently - Use WebSocket subscriptions for real-time data instead of repeated polling
- Use pagination for large result sets - Pass
limitandoffsetparameters - Cache tokens - Don’t re-authenticate on every request
- Handle errors gracefully - Check HTTP status codes (401 = unauthorized, 404 = not found, 500 = server error)
- Use batch endpoints when reading or writing multiple points to reduce HTTP overhead
- Always use HTTPS in production to protect tokens and credentials in transit
- Rotate API keys regularly and avoid embedding credentials in client-side code
Note
API permissions mirror your Mango user permissions. If your API user cannot see a data source in the UI, API calls for that data source will return 403 Forbidden. Create a dedicated API user with only the roles and permissions needed for your integration.
Troubleshooting
401 Unauthorized
- Token may have expired - re-authenticate
- Check username/password are correct
- Verify the user has API access permissions
403 Forbidden
- The authenticated user doesn’t have permission for that resource
- Check the user’s roles and the resource’s permissions
- On a session login, the login itself and every later POST, PUT, PATCH or DELETE need an
X-XSRF-TOKENheader that matches theXSRF-TOKENcookie. Login issues a new cookie value, so send that one afterwards
404 Not Found
- Verify the data point XID exists
- Check the API endpoint URL is correct
- Check the verb. A 405 rather than a 404 means the path exists but not for that method –
/point-values/{xid}is the classic case: PUT and DELETE only - There is only one REST prefix,
/rest/latest/. There is no/rest/v2/in Mango 5