20,919,685Total Points24,106Total Sites23,382Cell Towers69,500Racks Monitored56,753HVAC Units Monitored31,322UPS Units Monitored24,788Generators Monitored20,919,685Total Points24,106Total Sites23,382Cell Towers69,500Racks Monitored56,753HVAC Units Monitored31,322UPS Units Monitored24,788Generators Monitored20,919,685Total Points24,106Total Sites23,382Cell Towers69,500Racks Monitored56,753HVAC Units Monitored31,322UPS Units Monitored24,788Generators Monitored

Chapter 3: Data Sources & ProtocolsLesson 17 of 65

Getting Started with the Mango REST API

How to authenticate with and use the Mango by Radix IoT REST API to read data point values, set values, and query historical data programmatically.

  • 10 min read
  • Intermediate
  • Mango 4.x / 5.x

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:

  1. The machine-readable OpenAPI definition is at http://your-mango:8080/rest/latest/api-docs (configured explicitly as springdoc.api-docs.path=/api-docs)
  2. The Swagger UI is served under the same /rest/latest prefix – browse endpoints, parameters and response formats there
  3. 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

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

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 limit and offset parameters
  • 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-TOKEN header that matches the XSRF-TOKEN cookie. 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

Get free access to all 65 Mango by Radix IoT training lessons

One short form unlocks every lesson and its video in this browser.

This form is hosted by Zoho. It loads only after you enable support cookies or choose to load it below.

We honored your browser’s Global Privacy Control signal — optional cookies are off and nothing is tracked.