exports

Your raw data, streamed

Pull raw events or payments as CSV or NDJSON. The response streams, so large windows never blow up memory on either side. Needs the export scope.

GET/api/v1/sites/{id}/export
ParamTypeDescription
datasetstringevents (default), payments, or rollup — see below.
formatstringcsv (default) or ndjson.
fromdateWindow start (YYYY-MM-DD). Defaults to 7 days ago.
todateWindow end. Defaults to now.
fieldsstringComma-separated columns to keep. timestamp is always included. Defaults to all.
eventstringKeep only this event name.
channelstringKeep only this channel.
countrystringKeep only this country code.
pathstringKeep only paths starting with this prefix.
limitnumberStop after this many rows. Defaults to the 5M cap.
cursordate-timeResume after this timestamp when a previous export hit the cap.
curl "https://datalenk.com/api/v1/sites/3/export?dataset=events&format=csv&from=2026-07-01&to=2026-07-08" \
  -H "Authorization: Bearer dlk_live_…" -o events.csv

Analysing, not archiving

The raw export is built to fill a warehouse: up to five million rows of twenty columns. That is the wrong shape for reading — including handing your data to an AI assistant, where the file is usually too large to be read at all. Almost all of those bytes are the same dimension values repeated thousands of times.

dataset=rollup returns one row per combination of dimensions instead of one row per event. Three months of traffic usually fits in a few hundred lines rather than a few hundred thousand — small enough to paste anywhere.

ParamTypeDescription
group_bystringDimensions to group by, comma-separated: event_name, pathname, channel, country, region, city, device, browser, os, language, referrer, utm_source, utm_medium, utm_campaign, type. Omit for a single total.
bystringTime step: day (default), week, month, or none for no time dimension at all.
limitnumberMax rows, default 5000. The X-Truncated response header tells you whether it cut.
# Traffic and revenue per channel per week — a few dozen lines
curl "https://datalenk.com/api/v1/sites/3/export?dataset=rollup&group_by=channel&by=week&from=2026-06-01" \
  -H "Authorization: Bearer dlk_live_…"

# Top pages over the whole period, no time dimension
curl "https://datalenk.com/api/v1/sites/3/export?dataset=rollup&group_by=pathname&by=none&limit=100" \
  -H "Authorization: Bearer dlk_live_…"

Every row carries visitors, events, pageviews and revenue. An unknown group_by is rejected rather than ignored: a silently dropped dimension would give you correct totals over the wrong rows, and nothing would show it.

Columns

Public columns only. We never export raw IP, session id or user id. Each row carries a visitorId, a short non-reversible hash that is stable per visitor so you can group without identifying anyone.

That same visitorId opens the visitor's full journey: GET /v1/sites/:id/visitors/<visitorId>. Take the value straight from the CSV, no transformation. The endpoint accepts both the short hash and a raw reference captured with window.datalenk.ref, so an export row and a live capture reach the same journey.

events.csv
timestamp,type,event_name,pathname,channel,country,region,city,device,browser,os,language,referrer,utm_source,utm_medium,utm_campaign,revenue,currency,props,visitorId
2026-07-08 05:38:26,event,purchase,/pricing,Organic Search,US,,,Desktop,Safari,macOS,en,,,,,49,USD,,a3f9c1d20e7b

Large exports, and how you know one was cut

A single request returns up to five million rows. The window is counted before anything is sent, so the response always tells you where you stand: X-Total-Rows is what the window actually holds and X-Truncated is 1 when the file does not contain all of it.

A cut file also says so in its own name: yoursite.com-events-PARTIAL-5000000-of-7412903-rows.csv. Headers are invisible to anyone downloading a file in a browser or handing it to an assistant, and a truncated export is indistinguishable from a complete one once it is open. To fetch the rest, note the last timestamp in the file and call again with ?cursor= set to it.

If you are exporting to analyse rather than to archive, none of this should concern you: dataset=rollup answers the same questions in a few hundred lines.