Skip to main content

Export data as CSV

What you'll build​

A spreadsheet or BI tool requests GET /temperature.csv with an authorization token and receives 200 with text/csv, ready to import. The Analysis reads up to 100 recent temperature readings from a device you choose, not from an ID supplied by the caller.

curl "$ENDPOINT_URL/temperature.csv" -H "authorization: $AUTHORIZATION_TOKEN" -o temperature.csv

For a device containing these example readings, the file contains:

time,temperature_c
2026-10-14T12:00:00.000Z,23.5
2026-10-14T12:05:00.000Z,24

Downloaded temperature CSV opened as text

Set up​

Create a Luau Analysis and enable its Endpoint in Token mode. $ENDPOINT_URL is the copied URL without a trailing slash; $AUTHORIZATION_TOKEN is an authorization token on the same profile. Configure your importing tool to send that token in its authorization header, not in a query parameter.

ItemValue
Analysis variableEXPORT_DEVICE_ID = the device to export
Device variabletemperature, with numeric values in degrees Celsius
Example data23.5 at 2026-10-14T12:00:00.000Z; 24 at 2026-10-14T12:05:00.000Z
ResultLatest 100 readings, presented oldest first

Any authorization token on this profile can call this example. Use it only for a dataset that those integrations may read. The token does not identify a particular integration to the script.

Write the Luau​

Paste these blocks in order into the same Analysis; they form one script.

Restrict the caller and route before reading data.

Analysis.use(function(context, scope)
local request = context.request
if not request then return end
if request.caller.type ~= "authorization" then
return { json = { error = "Forbidden." }, status = 403 }
end
if request.method ~= "GET" or request.path ~= "/temperature.csv" then
return { json = { error = "Not found." }, status = 404 }
end

Fetch recent numeric temperatures and put them in chronological order.

local rows = Devices.get(context.environment.EXPORT_DEVICE_ID):getData({
variables = "temperature", qty = 100, ordination = "descending",
})
local lines = { "time,temperature_c" }
for i = #rows, 1, -1 do
local row = rows[i]
if type(row.value) == "number" then
table.insert(lines, row.time .. "," .. tostring(row.value))
end
end

Return a CSV string rather than JSON or an HTML page.

return table.concat(lines, "\n") .. "\n", {
content_type = "text/csv; charset=utf-8",
headers = { ["content-disposition"] = 'attachment; filename="temperature.csv"' },
}
end)

This export includes platform timestamps and numeric values only. If you add arbitrary text columns, escape CSV quotes, commas, and newlines, and protect spreadsheet consumers from formula injection. Keep the result within the Endpoint's response limit.

Permissions​

The Analysis reads device data, rather than using the platform's bulk-export operation.

TargetResourceActions
This AnalysisExport deviceAccess, Get data
Importing toolAuthorization token on the same profileNo Call Endpoint policy required

Add the Analysis's Allow permission in Access Management. Export data is not required for this script.

Try it​

  1. Add the example readings to an otherwise empty test device and set EXPORT_DEVICE_ID to it.
  2. Run the curl command and open temperature.csv as text. It matches the CSV above, including a final newline. Your own device produces its own timestamps and values.
  3. Import the file into a spreadsheet, or configure the tool's HTTP import with the same URL and header.

Admin's Try it uses a profile token, which this authorization-only script rejects with 403; use the curl request to test the intended caller.