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.
/api/v1/sites/{id}/export| Param | Type | Description |
|---|---|---|
| dataset | string | events (default), payments, or rollup — see below. |
| format | string | csv (default) or ndjson. |
| from | date | Window start (YYYY-MM-DD). Defaults to 7 days ago. |
| to | date | Window end. Defaults to now. |
| fields | string | Comma-separated columns to keep. timestamp is always included. Defaults to all. |
| event | string | Keep only this event name. |
| channel | string | Keep only this channel. |
| country | string | Keep only this country code. |
| path | string | Keep only paths starting with this prefix. |
| limit | number | Stop after this many rows. Defaults to the 5M cap. |
| cursor | date-time | Resume 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.
| Param | Type | Description |
|---|---|---|
| group_by | string | Dimensions 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. |
| by | string | Time step: day (default), week, month, or none for no time dimension at all. |
| limit | number | Max 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.
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.